# Sphere — Complete Protocol Documentation for AI Agents ## What is Sphere? Sphere is a pool-backed binary betting protocol on Solana. You bet on whether an asset will move UP or DOWN by X% within a time window. The prize pool (funded by user losses) takes the other side of every bet — no peer matching needed. All bets are in USDC. **How it works:** 1. Pick an asset, direction, move size, and time window 2. The protocol prices the bet using a volatility model and shows you the multiplier 3. You deposit your stake (USDC) on-chain 4. The protocol deposits its side (the house stake) from the protocol wallet 5. At expiry, a dual oracle checks the price and the winner is paid automatically **Key features:** - **House-backed**: Instant fills, no waiting for a counterparty - **Stacks (parlays)**: Combine 2-5 bets for higher multipliers - **Cash-out**: Exit early at live probability-based pricing - **Gasless**: All Solana transaction fees paid by the protocol - **Non-custodial**: Each bet has its own escrow wallet --- ## Underlying Assets ### 17 Assets (14 Stocks & ETFs + 3 Crypto) Stocks are Token-2022 program mints issued by Backed Finance on Solana. Sphere only needs price oracles — you don't need to hold the underlying tokens. Crypto assets (BTC, ETH, SOL) are also supported — no on-chain token required, just price feeds. - TSLAx (Tesla): XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB - NVDAx (NVIDIA): Xsc9qvGR1efVDFGLrVsmkzv3qi45LTBjeUKSPmx9qEh - AAPLx (Apple): XsbEhLAtcf6HdfpFZ5xEMdqW8nfAvcsP5bdudRLJzJp - SPYx (S&P 500 ETF): XsoCS1TfEyfFhfvj8EtZ528L3CaKBDBRqRapnBbDF2W - QQQx (Invesco QQQ ETF): Xs8S1uUs1zvS2p7iwtsG3b6fkhpvmwz4GYU3gWAmWHZ - AMZNx (Amazon): Xs3eBt7uRfJX8QUs4suhyU8p2M6DoUDrJyWBa8LLZsg - GOOGLx (Alphabet): XsCPL9dNWBMvFtTmwcCA5v3xWPSMEBCszbQdiLLq6aN - METAx (Meta): Xsa62P5mvPszXL1krVUnU5ar38bBSVcWAB6fmPCo5Zu - COINx (Coinbase): Xs7ZdzSHLU9ftNJsii5fCeJhoRWSC32SQGzGQtePxNu - HOODx (Robinhood): XsvNBAYkrDRNhA7wPHQfX3ZUXZyZLdnCQDfHZ56bzpg - MSTRx (MicroStrategy): XsP7xzNPvEHS1m6qfanPUGjNmdnmsLKEoNAnHjdxxyZ - CRCLx (Circle): XsueG8BtpquVJX9LVLLEGuViXUungE6WmK5YZ3p3bd1 - GLDx (Gold / SPDR): Xsv9hRk1z5ystj9MhnA7Lq4vjSsLwzL2nxrwmwtD3re - MSFTx (Microsoft): XspzcW1PRtgf6Wj92HCiZdjzKCyFekVD8P5Ueh3dRMX ### Base Currency - USDC: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v (6 decimals, SPL Token) --- ## Protocol Configuration - **Chain**: Solana mainnet-beta - **Model**: House-backed (protocol takes the other side of every bet) - **Fee**: 5% (500 bps) on user stake, deducted at bet time - **Protocol wallet**: EELdnvgCdAohRcxhLuG37XMvCC5Jr7BfTWZAuYk8RrBe - **Max single bet**: $500 ($100 for 1H, $50 for 5M, $25 for 60S) - **Max payout**: 1/3 of protocol wallet USDC balance (1/6 for 5M, 1/8 for 60S) - **Settlement**: Automated every 1 minute via dual oracle (DexScreener + Jupiter). Rapid (60S/5M) uses historical VPS price cache for fair settlement. --- ## Market Structure ### Market ID Format `{asset}_{direction}_{moveBps}_{tenor}` Examples: - `TSLAx_UP_500_7D` = "Tesla goes UP 5% within 7 days" - `SPYx_DOWN_100_1D` = "S&P 500 goes DOWN 1% within 1 day" - `COINx_UP_200_1H` = "Coinbase goes UP 2% within 1 hour" ### Parameters - **Assets**: TSLAx, NVDAx, AAPLx, SPYx, QQQx, AMZNx, GOOGLx, METAx, COINx, HOODx, MSTRx, CRCLx, GLDx, MSFTx (+ crypto: BTCx, ETHx, SOLx) - **Directions**: UP, DOWN - **Move sizes** (bps → percent): 100 (1%), 200 (2%), 500 (5%), 1000 (10%), 2000 (20%) - **Tenors**: 60S (60 sec, crypto only), 5M (5 min, crypto only), 1H (1 hour), 1D (24h), 7D, 30D ### 1-Hour Tenor (1H) — Special Rules The 1H tenor has tighter limits and restricted assets: - **Market hours**: 10:00 AM – 2:55 PM ET, weekdays only - **Max bet**: $100 - **Cash-out cutoff**: 10 minutes before expiry (vs 60 minutes) **Allowed 1H moves by asset:** - SPYx, QQQx, GLDx: 0.25%, 0.5%, 1% - GOOGLx, AAPLx, AMZNx, TSLAx: 0.5%, 1%, 2% - NVDAx, METAx: 0.5%, 1%, 2% - MSFTx: 0.5%, 1%, 2% - COINx, MSTRx, CRCLx, HOODx: 1%, 2%, 5% ### 60-Second Tenor (60S) — Rapid Crypto Markets Ultra-short crypto-only binary bets settled via historical VPS price cache. - **Assets**: BTCx, ETHx, SOLx (24/7, no market hours) - **Max bet**: $25 - **Max payout**: 1/8 of protocol balance - **Liquidity buffer**: 75% - **Vol multiplier**: 2.5x on realized sigma - **Cash-out cutoff**: 20 seconds before expiry - **Settlement**: Historical price from VPS WebSocket cache (30-second tolerance) - **Direction-only markets**: `movePctBps=1` = pure UP/DOWN bet, fixed price 0.51 (~1.96x multiplier) **Allowed 60S moves by asset:** - BTCx: UP/DOWN, 0.02%, 0.05%, 0.1%, 0.25%, 0.5% - ETHx: UP/DOWN, 0.03%, 0.05%, 0.15%, 0.25%, 0.5% - SOLx: UP/DOWN, 0.05%, 0.1%, 0.25%, 0.5%, 1% ### 5-Minute Tenor (5M) — Rapid Crypto Markets - **Assets**: BTCx, ETHx, SOLx (24/7) - **Max bet**: $50 - **Max payout**: 1/6 of protocol balance - **Liquidity buffer**: 65% - **Vol multiplier**: 2.0x on realized sigma - **Cash-out cutoff**: 2 minutes before expiry - **Settlement**: Historical price from VPS cache (60-second tolerance) **Allowed 5M moves by asset:** - BTCx: 0.05%, 0.1%, 0.25%, 0.5%, 1% - ETHx: 0.05%, 0.15%, 0.25%, 0.5%, 1% - SOLx: 0.1%, 0.25%, 0.5%, 1%, 2% ### Bet Economics - **Your stake**: The USDC amount you choose to bet - **Fee**: 5% of your stake (deducted upfront) - **Binary price**: Model-priced probability of the move happening - **Multiplier**: 1 / binaryPrice (e.g., binaryPrice 0.40 = 2.5x multiplier) - **House stake**: stake × (multiplier - 1) - **Potential payout**: stake + houseStake - fee ### Settlement Settlement is fully automated — agents do not need to call any settlement endpoint. 1. Every 1 minute, the settlement engine finds expired positions 2. **Standard tenors (1H+)**: Dual oracle fetches current price from DexScreener + Jupiter; prices must agree within 2% (1% for 1H) 3. **Rapid tenors (60S/5M)**: Uses historical price from VPS WebSocket cache at exact expiry time (30s tolerance for 60S, 60s for 5M). Falls back to live dual oracle if historical data unavailable. 4. **UP bets**: WIN if settlement price ≥ target price 5. **DOWN bets**: WIN if settlement price ≤ target price 6. Winner's payout is sent automatically from the escrow wallet --- ## API Reference Base URL: `https://sphere.galactic.inc/v1` --- ### GET /v1/stocks List all supported assets with Solana mint addresses. Response: ```json { "stocks": [ { "symbol": "TSLAx", "name": "Tesla", "mint": "XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB", "decimals": 8, "tokenProgram": "token2022", "issuer": "Backed Finance" } ], "baseMints": { "USDC": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" } } ``` ### GET /v1/prices Get real-time USD prices for all assets. Optional query: `?symbols=TSLAx,NVDAx` to filter. Response: ```json { "prices": [ { "symbol": "TSLAx", "name": "Tesla", "priceUsd": "259.74", "priceChange24h": "-2.31", "volume24h": "1250000", "mint": "XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB" } ] } ``` ### GET /v1/chart/:symbol 30-day daily close prices for an asset via Tiingo. Cached for 4 hours. Response: ```json { "symbol": "TSLAx", "points": [ { "date": "2025-02-20T00:00:00.000Z", "close": 259.74 } ] } ``` ### GET /v1/portfolio/:walletAddress Get wallet balances (SOL, USDC, asset holdings). Response: ```json { "walletAddress": "YourSolanaPublicKey...", "sol": { "balance": "1.5" }, "usdc": { "balance": "500.00" }, "holdings": [ { "symbol": "TSLAx", "name": "Tesla", "mint": "XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB", "balance": "0.385", "balanceRaw": "38500000" } ] } ``` --- ## Sphere Single Bet API ### GET /v1/sphere/markets/:asset Get the bet grid for an asset — all available bets with their multipliers. Response: ```json { "underlying": "TSLAx", "grid": [ { "marketId": "TSLAx_UP_500_7D", "underlying": "TSLAx", "tenor": "7D", "direction": "UP", "movePctBps": 500, "movePercent": 0.05, "multiplier": 2.50 } ] } ``` ### POST /v1/sphere/bet Place a house-backed bet. Returns an unsigned Solana transaction. Request: ```json { "marketId": "TSLAx_UP_500_7D", "stake": 100, "wallet": "YourSolanaPublicKey..." } ``` - `marketId`: Market cell ID (see grid endpoint) - `stake`: USDC amount (min $0.10, max $500 or $100 for 1H) - `wallet`: Your Solana public key Response: ```json { "positionId": "a1b2c3d4e5f6...", "unsignedTx": "AQAAAA...base64...", "multiplier": 2.50, "binaryPrice": 0.40, "houseStake": 150.00, "fee": 2.50, "potentialPayout": 247.50, "entryPrice": 259.74, "targetPrice": 272.73 } ``` The `unsignedTx` is a base64-encoded Solana VersionedTransaction. Deserialize it, sign with your keypair, then confirm. ### POST /v1/sphere/bet/confirm Confirm bet after signing the transaction. Request: ```json { "positionId": "a1b2c3d4e5f6...", "signedTx": "AQAAAA...base64signedtx..." } ``` Response: Full `SpherePosition` object with `status: "ACTIVE"` and `expiresAt` set. ```json { "id": "a1b2c3d4e5f6...", "marketId": "TSLAx_UP_500_7D", "status": "ACTIVE", "expiresAt": 1709913600000, "entryPrice": 259.74, "targetPrice": 272.73, "direction": "UP", "movePctBps": 500, "yesParty": { "wallet": "YourKey...", "stake": 100, "feePaid": 2.50, "size": 250 }, "noParty": { "wallet": "EELdnvg...", "stake": 150, "feePaid": 0, "size": 250 }, "outcome": null, "settlementPrice": null, "createdAt": 1709308800000 } ``` ### GET /v1/sphere/cashout/quote/:positionId Get a live cash-out quote for an active position. Response: ```json { "positionId": "a1b2c3d4e5f6...", "currentPrice": 265.50, "oracleSource": "dual-oracle", "oracleConfidence": "high", "timeRemainingMs": 432000000, "totalPot": 250.00, "cashOutValue": 145.00, "liveProb": 0.65, "fairValue": 162.50, "eligible": true } ``` **Eligibility rules:** - Position must be ACTIVE - Time remaining > 60 minutes (10 minutes for 1H) - Cash-out value ≥ $0.50 - If `eligible: false`, the `reason` field explains why ### POST /v1/sphere/cashout/execute Execute cash-out for a position. The USDC is sent to your wallet on-chain. Request: ```json { "positionId": "a1b2c3d4e5f6...", "wallet": "YourSolanaPublicKey..." } ``` Response: Full `SpherePosition` with `outcome: "CASHED_OUT"`, `status: "SETTLED"`, and `cashOutDetails`. ### GET /v1/sphere/positions/:wallet Get all positions and stacks for a wallet. Response: ```json { "wallet": "YourSolanaPublicKey...", "pending": [], "active": [ { "id": "a1b2c3d4e5f6...", "marketId": "TSLAx_UP_500_7D", "status": "ACTIVE", "expiresAt": 1709913600000, "entryPrice": 259.74, "targetPrice": 272.73, "yesParty": { "wallet": "YourKey...", "stake": 100, "feePaid": 2.50, "size": 250 }, "noParty": { "wallet": "EELdnvg...", "stake": 150, "feePaid": 0, "size": 250 }, "outcome": null } ], "settled": [], "stacks": { "active": [], "settled": [] }, "stats": { "totalPositions": 1, "pendingCount": 0, "activeCount": 1, "settledCount": 0, "activeStackCount": 0, "settledStackCount": 0 } } ``` --- ## Sphere Stack (Parlay) API Stacks are multi-leg parlay bets. All legs must win for the stack to pay out. The combined multiplier is the product of individual leg multipliers. ### POST /v1/sphere/stack/bet Place a multi-leg parlay bet. Request: ```json { "legs": [ { "marketId": "TSLAx_UP_500_7D" }, { "marketId": "SPYx_DOWN_100_1D" }, { "marketId": "NVDAx_UP_1000_30D" } ], "stake": 50, "wallet": "YourSolanaPublicKey..." } ``` - `legs`: 2-5 legs, each with a unique asset (no duplicates) - `stake`: USDC amount (min $0.10, max $500 or $100 if any leg is 1H) - `wallet`: Your Solana public key Response: ```json { "stackId": "x1y2z3...", "unsignedTx": "AQAAAA...base64...", "legs": [ { "marketId": "TSLAx_UP_500_7D", "underlying": "TSLAx", "direction": "UP", "movePctBps": 500, "tenor": "7D", "entryPrice": 259.74, "targetPrice": 272.73, "multiplier": 2.50, "binaryPrice": 0.40 }, { "marketId": "SPYx_DOWN_100_1D", "underlying": "SPYx", "direction": "DOWN", "movePctBps": 100, "tenor": "1D", "entryPrice": 450.12, "targetPrice": 445.62, "multiplier": 1.80, "binaryPrice": 0.556 }, { "marketId": "NVDAx_UP_1000_30D", "underlying": "NVDAx", "direction": "UP", "movePctBps": 1000, "tenor": "30D", "entryPrice": 820.50, "targetPrice": 902.55, "multiplier": 3.20, "binaryPrice": 0.3125 } ], "combinedMultiplier": 14.40, "stake": 50.00, "fee": 1.25, "houseStake": 670.00, "potentialPayout": 718.75 } ``` ### POST /v1/sphere/stack/bet/confirm Confirm stack bet after signing. Request: ```json { "stackId": "x1y2z3...", "signedTx": "AQAAAA...base64signedtx..." } ``` Response: Full `SphereStack` object with `status: "ACTIVE"` and each leg's `expiresAt` set. ### GET /v1/sphere/stack/cashout/quote/:stackId Get a stack cash-out quote. Spread increases with more unsettled legs (10% base + 5% per unsettled leg). Response: ```json { "stackId": "x1y2z3...", "currentPrices": { "TSLAx": 265.50, "SPYx": 448.00, "NVDAx": 835.20 }, "cashOutValue": 280.00, "combinedProb": 0.45, "fairValue": 324.00, "spread": 0.25, "legProbs": [0.70, 0.80, 0.80], "eligible": true } ``` ### POST /v1/sphere/stack/cashout/execute Execute stack cash-out. Same request format as single cash-out. Request: ```json { "stackId": "x1y2z3...", "wallet": "YourSolanaPublicKey..." } ``` Response: Full `SphereStack` with `status: "CASHED_OUT"` and `cashOutDetails`. --- ## Info Endpoints ### GET /v1/sphere/config Protocol configuration and limits. Cached for 5 minutes. Response: ```json { "sphereFeeBps": 500, "maxStackLegs": 5, "maxCombinedMultiplier": 1000, "maxPayoutFraction": 0.3333, "cashoutSpread": 0.10, "cashoutMinValue": 0.50, "cashoutCutoffMs": 3600000, "stackCashoutSpreadBase": 0.10, "stackCashoutSpreadPerLeg": 0.05, "validTenors": ["60S", "5M", "1H", "1D", "7D", "30D"], "validMoveBps": [100, 200, 500, 1000, 2000], "oneHour": { "cashoutCutoffMs": 600000, "liquidityBuffer": 0.50, "marketOpenMin": 600, "marketCloseMin": 895, "allowedMoves": { "SPYx": [25, 50, 100], "QQQx": [25, 50, 100], "GLDx": [25, 50, 100], "GOOGLx": [50, 100, 200], "AAPLx": [50, 100, 200], "AMZNx": [50, 100, 200], "TSLAx": [50, 100, 200], "MSFTx": [50, 100, 200], "NVDAx": [50, 100, 200], "METAx": [50, 100, 200], "COINx": [100, 200, 500], "MSTRx": [100, 200, 500], "CRCLx": [100, 200, 500], "HOODx": [100, 200, 500] } } } ``` --- ## Rapid Market API (60S/5M Crypto) These endpoints serve the rapid crypto markets (BTCx, ETHx, SOLx). Bets are placed using the standard `/sphere/bet` and `/sphere/bet/confirm` endpoints with 60S or 5M tenor market IDs. ### GET /v1/rapid/markets All crypto market grids for rapid tenors. Optional query `?tenor=60S` or `?tenor=5M` to filter. Response: ```json { "markets": { "BTCx": [ { "marketId": "BTCx_UP_1_60S", "underlying": "BTCx", "tenor": "60S", "direction": "UP", "movePctBps": 1, "movePercent": 0.0001, "multiplier": 1.96 } ], "ETHx": [...], "SOLx": [...] } } ``` ### GET /v1/rapid/markets/:asset Market grid for a single crypto asset. Supports `?tenor=60S` or `?tenor=5M` filter. ### GET /v1/rapid/price/:asset Latest cached price for a crypto asset (15-second refresh from VPS WebSocket feeds). Response: ```json { "asset": "BTCx", "price": 67432.50, "updatedAt": 1711296000000 } ``` ### GET /v1/rapid/chart/:asset 30-minute price history for chart display. Response: ```json { "asset": "BTCx", "points": [ { "timestamp": 1711295000000, "price": 67400.25 }, { "timestamp": 1711295015000, "price": 67405.10 } ] } ``` ### GET /v1/rapid/positions/:wallet All rapid positions (60S and 5M) for a wallet. Response: ```json { "wallet": "YourSolanaPublicKey...", "active": [...], "settled": [...] } ``` --- ### GET /v1/sphere/volatility Current realized annualized volatility per asset. Response: ```json { "volatilities": { "TSLAx": 0.3545, "NVDAx": 0.4164, "AAPLx": 0.3009, "SPYx": 0.1179, "QQQx": 0.1694, "AMZNx": 0.3154, "GOOGLx": 0.2367, "METAx": 0.4324, "COINx": 0.9957, "HOODx": 0.8540, "MSTRx": 1.1519, "CRCLx": 1.2564, "GLDx": 0.1700, "MSFTx": 0.2500 } } ``` ### GET /v1/sphere/queue Settlement queue — upcoming expirations and recent settlements. Response: ```json { "upcoming": [ { "type": "single", "id": "abc123...", "expiresAt": 1709913600000, "stake": 100, "potentialPayout": 250, "status": "ACTIVE", "wallet": "User...", "underlying": "TSLAx", "direction": "UP", "movePctBps": 500, "tenor": "7D" } ], "settled": [ { "type": "single", "id": "def456...", "outcome": "YES", "settlementPrice": 275.50, "settledAt": 1709900000000, "stake": 50, "payout": 120 } ] } ``` ### GET /v1/sphere/leaderboard Top 10 all-time wins by payout amount. Response: ```json { "leaderboard": [ { "type": "stack", "id": "top1...", "wallet": "Winner...", "underlying": "TSLAx + SPYx + NVDAx", "direction": "UP/DOWN/UP", "stake": 25, "payout": 1200, "multiplier": 48.0, "settledAt": 1709800000000, "legs": [ { "underlying": "TSLAx", "direction": "UP", "movePctBps": 1000, "tenor": "7D", "multiplier": 4.0 }, { "underlying": "SPYx", "direction": "DOWN", "movePctBps": 200, "tenor": "1D", "multiplier": 3.0 }, { "underlying": "NVDAx", "direction": "UP", "movePctBps": 500, "tenor": "30D", "multiplier": 4.0 } ] } ] } ``` ### GET /v1/sphere/share/:id Public lookup for a position or stack by ID. Used for shareable links. Response: ```json { "type": "position", "data": { "...full SpherePosition or SphereStack object..." } } ``` Returns 404 for positions still in `AWAITING_DEPOSIT` status. --- ## Complete Agent Flows (TypeScript) ### Place a Single Bet ```typescript import { Connection, VersionedTransaction, Keypair } from '@solana/web3.js'; const API_BASE = 'https://sphere.galactic.inc/v1'; const SOLANA_RPC = 'https://api.mainnet-beta.solana.com'; const agentKeypair = Keypair.fromSecretKey(Uint8Array.from(/* your secret key bytes */)); const connection = new Connection(SOLANA_RPC, 'confirmed'); async function placeBet(marketId: string, stakeUsdc: number) { // Step 1: Place the bet const betRes = await fetch(`${API_BASE}/sphere/bet`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ marketId, stake: stakeUsdc, wallet: agentKeypair.publicKey.toBase58(), }), }); const { positionId, unsignedTx, multiplier, potentialPayout, entryPrice, targetPrice } = await betRes.json(); console.log(`Position ${positionId}: ${multiplier}x multiplier, payout $${potentialPayout}`); console.log(`Entry: $${entryPrice}, Target: $${targetPrice}`); // Step 2: Deserialize and sign the transaction const tx = VersionedTransaction.deserialize(Buffer.from(unsignedTx, 'base64')); tx.sign([agentKeypair]); // Step 3: Encode the signed transaction and confirm const signedTx = Buffer.from(tx.serialize()).toString('base64'); const confirmRes = await fetch(`${API_BASE}/sphere/bet/confirm`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ positionId, signedTx }), }); const position = await confirmRes.json(); console.log(`Status: ${position.status}, Expires: ${new Date(position.expiresAt).toISOString()}`); return position; } // Bet $100 that Tesla goes UP 5% within 7 days await placeBet('TSLAx_UP_500_7D', 100); ``` ### Place a Stack (Parlay) ```typescript async function placeStack(legs: { marketId: string }[], stakeUsdc: number) { // Step 1: Place the stack bet const betRes = await fetch(`${API_BASE}/sphere/stack/bet`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ legs, stake: stakeUsdc, wallet: agentKeypair.publicKey.toBase58(), }), }); const { stackId, unsignedTx, combinedMultiplier, potentialPayout } = await betRes.json(); console.log(`Stack ${stackId}: ${combinedMultiplier}x combined, payout $${potentialPayout}`); // Step 2: Sign the transaction const tx = VersionedTransaction.deserialize(Buffer.from(unsignedTx, 'base64')); tx.sign([agentKeypair]); // Step 3: Confirm const signedTx = Buffer.from(tx.serialize()).toString('base64'); const confirmRes = await fetch(`${API_BASE}/sphere/stack/bet/confirm`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ stackId, signedTx }), }); const stack = await confirmRes.json(); console.log(`Stack status: ${stack.status}`); return stack; } // 3-leg parlay: TSLA up 5%, SPY down 1%, NVDA up 10% await placeStack([ { marketId: 'TSLAx_UP_500_7D' }, { marketId: 'SPYx_DOWN_100_1D' }, { marketId: 'NVDAx_UP_1000_30D' }, ], 50); ``` ### Cash Out a Position ```typescript async function cashOut(positionId: string) { // Step 1: Get a quote const quoteRes = await fetch(`${API_BASE}/sphere/cashout/quote/${positionId}`); const quote = await quoteRes.json(); if (!quote.eligible) { console.log(`Cash-out not available: ${quote.reason}`); return null; } console.log(`Cash-out value: $${quote.cashOutValue} (live prob: ${quote.liveProb})`); // Step 2: Execute (no signing needed — payout is sent automatically) const execRes = await fetch(`${API_BASE}/sphere/cashout/execute`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ positionId, wallet: agentKeypair.publicKey.toBase58(), }), }); const result = await execRes.json(); console.log(`Cashed out: $${result.cashOutDetails.cashOutValue}`); return result; } await cashOut('a1b2c3d4e5f6...'); ``` ### Cash Out a Stack ```typescript async function cashOutStack(stackId: string) { const quoteRes = await fetch(`${API_BASE}/sphere/stack/cashout/quote/${stackId}`); const quote = await quoteRes.json(); if (!quote.eligible) { console.log(`Stack cash-out not available: ${quote.reason}`); return null; } console.log(`Stack cash-out: $${quote.cashOutValue} (combined prob: ${quote.combinedProb}, spread: ${quote.spread})`); const execRes = await fetch(`${API_BASE}/sphere/stack/cashout/execute`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ stackId, wallet: agentKeypair.publicKey.toBase58(), }), }); const result = await execRes.json(); console.log(`Cashed out stack: $${result.cashOutDetails.cashOutValue}`); return result; } ``` ### Browse Markets and Check Positions ```typescript async function browseMarkets(asset: string) { const res = await fetch(`${API_BASE}/sphere/markets/${asset}`); const { grid } = await res.json(); for (const cell of grid) { console.log(`${cell.marketId}: ${cell.multiplier}x`); } return grid; } async function getPositions() { const wallet = agentKeypair.publicKey.toBase58(); const res = await fetch(`${API_BASE}/sphere/positions/${wallet}`); const data = await res.json(); console.log(`Active: ${data.stats.activeCount}, Settled: ${data.stats.settledCount}`); console.log(`Active stacks: ${data.stats.activeStackCount}`); for (const pos of data.active) { console.log(` ${pos.marketId} — expires ${new Date(pos.expiresAt).toISOString()}`); } return data; } async function getPortfolio() { const wallet = agentKeypair.publicKey.toBase58(); const res = await fetch(`${API_BASE}/portfolio/${wallet}`); const data = await res.json(); console.log(`USDC: $${data.usdc.balance}, SOL: ${data.sol.balance}`); return data; } await browseMarkets('TSLAx'); await getPositions(); await getPortfolio(); ``` --- ## Integration Patterns ### As LangChain Tools ```typescript import { z } from 'zod'; const BrowseMarketsTool = { name: 'sphere_markets', description: 'Browse available bets for an asset on Sphere. Shows multipliers for each direction/move/tenor.', schema: z.object({ asset: z.string().describe('Asset symbol (e.g., TSLAx, NVDAx, BTCx, ETHx)'), }) }; const PlaceBetTool = { name: 'sphere_bet', description: 'Place a house-backed bet on a price move via Sphere.', schema: z.object({ marketId: z.string().describe('Market cell ID (e.g., TSLAx_UP_500_7D)'), stake: z.number().describe('USDC amount to bet (min $0.10, max $500)'), }) }; const PlaceStackTool = { name: 'sphere_stack', description: 'Place a multi-leg parlay bet on Sphere. All legs must win.', schema: z.object({ legs: z.array(z.object({ marketId: z.string().describe('Market cell ID for this leg'), })).min(2).max(5).describe('2-5 legs with unique assets'), stake: z.number().describe('USDC amount to bet'), }) }; const CashOutTool = { name: 'sphere_cashout', description: 'Cash out an active Sphere position early at live probability-based pricing.', schema: z.object({ positionId: z.string().describe('Position or stack ID to cash out'), type: z.enum(['single', 'stack']).describe('Whether this is a single position or stack'), }) }; const GetPositionsTool = { name: 'sphere_positions', description: 'Get all active and settled Sphere positions for a wallet.', schema: z.object({ wallet: z.string().optional().describe('Wallet address (defaults to agent wallet)'), }) }; const GetPriceTool = { name: 'sphere_price', description: 'Get the current USD price of an asset on Sphere.', schema: z.object({ symbol: z.string().describe('Asset symbol (e.g., TSLAx, BTCx)'), }) }; ``` ### As MCP Tools ```json { "name": "sphere_bet", "description": "Place a house-backed bet on a price move via Sphere", "inputSchema": { "type": "object", "properties": { "marketId": { "type": "string", "description": "Market cell ID (e.g., TSLAx_UP_500_7D)" }, "stake": { "type": "number", "description": "USDC amount to bet (min $0.10, max $500)" } }, "required": ["marketId", "stake"] } } ``` ```json { "name": "sphere_stack", "description": "Place a multi-leg parlay bet on Sphere. All legs must win for payout.", "inputSchema": { "type": "object", "properties": { "legs": { "type": "array", "items": { "type": "object", "properties": { "marketId": { "type": "string" } }, "required": ["marketId"] }, "minItems": 2, "maxItems": 5, "description": "2-5 legs with unique assets" }, "stake": { "type": "number", "description": "USDC amount to bet" } }, "required": ["legs", "stake"] } } ``` ```json { "name": "sphere_cashout", "description": "Cash out an active position or stack early at live probability pricing", "inputSchema": { "type": "object", "properties": { "positionId": { "type": "string", "description": "Position or stack ID" }, "type": { "type": "string", "enum": ["single", "stack"], "description": "Position type" } }, "required": ["positionId", "type"] } } ``` --- ## Common Failure Modes | Error | Cause | Solution | |-------|-------|----------| | Market not found | Invalid marketId format or market inactive | Use `GET /sphere/markets/:asset` to discover valid IDs | | Invalid stake | Stake below $0.10 or above max | Min $0.10, max $500 ($100 for 1H, $50 for 5M, $25 for 60S) | | 1H market closed | Bet placed outside market hours | 1H bets only available 10 AM - 2:55 PM ET weekdays | | 1H move not allowed | Move size not in allowed list for this asset | Check `GET /sphere/config` for allowed 1H moves | | Max payout exceeded | Payout would exceed 1/3 of protocol balance | Reduce stake or choose a lower multiplier | | Max combined multiplier | Stack multiplier exceeds 1000x | Use fewer legs or choose lower-multiplier markets | | Duplicate assets in stack | Two legs reference the same asset | Each stack leg must use a different asset | | Cash-out not eligible | Too close to expiry or value too low | Check quote endpoint for eligibility | | Oracle unavailable | DexScreener/Jupiter returned no price | Retry — temporary oracle issue | | Transaction expired | Solana blockhash is stale (~60 seconds) | Get a fresh bet and rebuild the transaction | | Insufficient funds | Wallet doesn't have enough USDC | Check balances via `/portfolio` first | | Rapid asset only | Non-crypto asset used with 60S/5M tenor | 60S and 5M tenors only support BTCx, ETHx, SOLx | | Historical price unavailable | VPS price cache missing data at expiry | Retries with live dual oracle; may take up to 10 min | --- ## Security Guidance for Agents 1. **Use a dedicated wallet** — Fund a separate hot wallet with only what you're willing to risk 2. **Set bet caps** — Implement your own maximum bet size limits in your agent logic 3. **Never share secret keys** — The Sphere API never needs your private key; you sign locally 4. **Verify transactions** — Simulate via `connection.simulateTransaction(tx)` before signing 5. **Monitor blockhash expiry** — Solana transactions expire after ~60 seconds; don't cache 6. **Check balances first** — Use `/portfolio/:wallet` to verify USDC balance before betting 7. **Use the config endpoint** — `GET /sphere/config` returns current limits; don't hardcode them --- ## Example Agent Prompts These prompts work with LLM agents that have Sphere tools: - "Show me the bet grid for TSLAx" - "Bet $100 that Tesla goes up 5% in 7 days" - "What's the multiplier for SPY going down 1% tomorrow?" - "Place a 3-leg parlay: TSLA up 5% 7D, SPY down 1% 1D, NVDA up 10% 30D, $50 stake" - "Show me my active positions" - "Cash out my TSLAx position" - "What are the current prices?" - "What's my USDC balance?" - "Show the leaderboard" - "What bets are expiring soon?" - "Show me the 60-second markets for BTC" - "Bet $10 that BTC goes UP in the next 60 seconds" - "What rapid bets do I have open?" - "Show the 5-minute ETH markets" --- ## Links - Website: https://sphere.galactic.inc - Machine-readable manifest: https://sphere.galactic.inc/.well-known/stack.manifest.json - OpenAPI spec: https://sphere.galactic.inc/openapi.json - LLM summary: https://sphere.galactic.inc/llms.txt