Skip to main content

SDK Guide

The Seesaw TypeScript SDK for building applications on the binary prediction market protocol.

Installation

npm install @seesaw/sdk @solana/web3.js

Overview

Quick Start

import { Connection, PublicKey, Keypair, Transaction } from '@solana/web3.js';
import {
  findMarketPda,
  findPositionPda,
  findOrderbookPda,
  findVaultPda,
  createPlaceOrderInstruction,
  parseMarket,
  OrderSide,
  OrderType,
} from '@seesaw/sdk';

// Setup
const connection = new Connection('https://api.mainnet-beta.solana.com');
const programId = new PublicKey('SEESAW_PROGRAM_ID');
const durationSeconds = 900; // default; configurable per market (60–604800)
const marketId = BigInt(Math.floor(Date.now() / 1000 / durationSeconds));

// 1. Derive PDAs
const [marketPda] = findMarketPda(marketId, programId);
const [orderbookPda] = findOrderbookPda(marketPda, programId);
const [vaultPda] = findVaultPda(marketPda, programId);
const [positionPda] = findPositionPda(marketPda, wallet.publicKey, programId);

// 2. Read market data
const marketAccount = await connection.getAccountInfo(marketPda);
const market = parseMarket(marketAccount!.data);

console.log('Market ID:', market.marketId);
console.log('Start Time:', new Date(market.tStart * 1000));
console.log('End Time:', new Date(market.tEnd * 1000));

// 3. Build place order instruction
const placeOrderIx = createPlaceOrderInstruction({
  market: marketPda,
  orderbook: orderbookPda,
  vault: vaultPda,
  position: positionPda,
  user: wallet.publicKey,
  userTokenAccount: userUsdcAccount,
  side: OrderSide.BuyYes,
  priceBps: 6000, // 60%
  quantity: BigInt(100), // 100 shares
  orderType: OrderType.Limit,
});

// 4. Send transaction
const tx = new Transaction().add(placeOrderIx);
const signature = await sendAndConfirmTransaction(connection, tx, [wallet]);

In This Section

Key Concepts

PDAs (Program Derived Addresses)

All Seesaw accounts are PDAs derived from deterministic seeds:

AccountSeedsPurpose
Config["seesaw", "config"]Protocol configuration
Market["seesaw", "market", market_id]Market state
Orderbook["seesaw", "orderbook", market]Order book state
Vault["seesaw", "vault", market]Token vault
Position["seesaw", "position", market, user]User position

Order Sides

enum OrderSide {
  BuyYes = 0, // Buy YES shares (bullish)
  SellYes = 1, // Sell YES shares
  BuyNo = 2, // Buy NO shares (bearish)
  SellNo = 3, // Sell NO shares
}

Order Types

enum OrderType {
  Limit = 0, // Match + rest on book
  PostOnly = 1, // Reject if would match
  ImmediateOrCancel = 2, // Match + cancel rest
}

Core Functions

PDA Derivation

// Config PDA (singleton)
const [configPda, configBump] = findConfigPda(programId);

// Market PDA
const marketId = BigInt(1234567);
const [marketPda, marketBump] = findMarketPda(marketId, programId);

// Orderbook PDA
const [orderbookPda, orderbookBump] = findOrderbookPda(marketPda, programId);

// Vault PDA
const [vaultPda, vaultBump] = findVaultPda(marketPda, programId);

// Position PDA
const [positionPda, positionBump] = findPositionPda(marketPda, userWallet, programId);

Account Parsing

// Parse market
const marketData = await connection.getAccountInfo(marketPda);
const market = parseMarket(marketData!.data);

// Parse orderbook
const orderbookData = await connection.getAccountInfo(orderbookPda);
const orderbook = parseOrderbook(orderbookData!.data);

// Parse position
const positionData = await connection.getAccountInfo(positionPda);
const position = parsePosition(positionData!.data);

// Parse config
const configData = await connection.getAccountInfo(configPda);
const config = parseConfig(configData!.data);

Instruction Builders

// Place order
const placeOrderIx = createPlaceOrderInstruction({...});

// Cancel order
const cancelOrderIx = createCancelOrderInstruction({...});

// Settle position
const settleIx = createSettlePositionInstruction({...});

// Crank operations
const snapshotStartIx = createSnapshotStartInstruction({...});
const snapshotEndIx = createSnapshotEndInstruction({...});
const resolveMarketIx = createResolveMarketInstruction({...});

Data Flow

Error Handling

import { SeesawError, ErrorCode } from '@seesaw/sdk';

try {
  const tx = new Transaction().add(placeOrderIx);
  await sendAndConfirmTransaction(connection, tx, [wallet]);
} catch (error) {
  if (error.message.includes('TradingEnded')) {
    console.error('Cannot trade: market has ended');
  } else if (error.message.includes('InsufficientCollateral')) {
    console.error('Cannot trade: need more USDC');
  } else if (error.message.includes('InsufficientShares')) {
    console.error('Cannot sell: not enough shares');
  } else {
    throw error;
  }
}

Type Definitions

Market Account

interface MarketAccount {
  marketId: bigint;
  pythFeed: PublicKey;
  settlementMint: PublicKey;
  tStart: bigint;
  tEnd: bigint;
  startPrice: bigint | null;
  endPrice: bigint | null;
  outcome: Outcome | null;
  totalYesShares: bigint;
  totalNoShares: bigint;
  totalCollateral: bigint;
  bump: number;
}

enum Outcome {
  Up = 1,
  Down = 2,
}

Position Account

interface PositionAccount {
  market: PublicKey;
  owner: PublicKey;
  yesShares: bigint;
  noShares: bigint;
  lockedYesShares: bigint;
  lockedNoShares: bigint;
  collateralLocked: bigint;
  settled: boolean;
  payout: bigint;
  bump: number;
}

Order

interface Order {
  orderId: bigint;
  owner: PublicKey;
  priceBps: number;
  quantity: bigint;
  originalQuantity: bigint;
  timestamp: bigint;
  originalSide: OrderSide;
  isActive: boolean;
}

Requirements

  • Node.js 18+
  • TypeScript 5.0+ (recommended)
  • @solana/web3.js 1.9+

Related