Reference
Quick reference for developers integrating with Seesaw.
Constants
Protocol Constants
| Constant | Value | Description |
|---|
DEFAULT_DURATION | 900 | Default market duration (15 min); configurable 60–604800 |
PRICE_SCALE | 10,000 | Basis points for price representation |
MAX_ORDERS_PER_USER | 10 | Maximum open orders per user per market |
MIN_ORDER_SIZE | 1 | Minimum shares per order |
MAX_ORDER_SIZE | 1,000,000 | Maximum shares per order |
TICK_SIZE | 100 | Price tick in basis points (0.01 USDC) |
Fee Constants
| Constant | Value | Description |
|---|
TAKER_FEE_BPS | 30 | Taker fee (0.30%) |
MAKER_REBATE_BPS | 10 | Maker rebate (0.10%) |
PROTOCOL_FEE_BPS | 20 | Net protocol fee (0.20%) |
CRANK_REWARD | 1,000 | Crank reward in lamports |
Time Constants
| Constant | Value | Description |
|---|
CREATE_WINDOW | 86,400 | Can create market up to 24h before start |
SETTLE_WINDOW | 604,800 | Must settle within 7 days |
SNAPSHOT_GRACE | 60 | Oracle timestamp grace period |
PDA Seeds
// TypeScript reference for PDA derivation
const PROGRAM_ID = 'SeesawPredictionMarket1111111111111111';
const seeds = {
config: ['seesaw', 'config'],
market: (marketId: bigint) => ['seesaw', 'market', u64ToLeBytes(marketId)],
orderbook: (market: PublicKey) => ['seesaw', 'orderbook', market.toBytes()],
vault: (market: PublicKey) => ['seesaw', 'vault', market.toBytes()],
position: (market: PublicKey, user: PublicKey) => [
'seesaw',
'position',
market.toBytes(),
user.toBytes(),
],
};
Account Layouts
Config Account
Offset Size Field
──────────────────────────────────
0 8 discriminator
8 32 authority
40 32 treasury
72 2 taker_fee_bps
74 2 maker_rebate_bps
76 1 paused
77 51 _reserved
──────────────────────────────────
Total: 128 bytes
Market Account
Offset Size Field
──────────────────────────────────
0 8 discriminator
8 8 market_id
16 32 pyth_feed
48 8 start_time
56 8 end_time
64 9 start_price (Option<i64>)
73 9 end_price (Option<i64>)
82 1 outcome (Option<Outcome>)
83 8 total_yes_shares
91 8 total_no_shares
99 8 total_collateral
107 1 state
108 148 _reserved
──────────────────────────────────
Total: 256 bytes
Position Account
Offset Size Field
──────────────────────────────────
0 8 discriminator
8 32 market
40 32 owner
72 8 yes_shares
80 8 no_shares
88 8 _reserved
──────────────────────────────────
Total: 96 bytes
Error Codes
| Code | Name | Description |
|---|
| 6000 | InvalidMarketState | Operation not valid for current state |
| 6001 | PriceOutOfRange | Price not in [0, 10000] |
| 6002 | InsufficientShares | Not enough shares to sell |
| 6003 | InsufficientCollateral | Not enough USDC |
| 6004 | InvalidOracleTimestamp | Pyth timestamp invalid |
| 6005 | InvalidOraclePrice | Pyth price <= 0 |
| 6006 | OracleConfidenceTooHigh | Pyth confidence exceeds limit |
| 6007 | SnapshotAlreadyCaptured | Price already recorded |
| 6008 | MarketNotResolved | Market still open |
| 6009 | PositionAlreadySettled | Already claimed |
| 6010 | OrderNotFound | Order doesn't exist |
| 6011 | Unauthorized | Wrong signer |
| 6012 | MathOverflow | Arithmetic error |
Pyth Feed IDs
Mainnet
| Asset | Feed Address |
|---|
| SOL/USD | H6ARHf6YXhG... |
| BTC/USD | GVXRSBjFk6e... |
| ETH/USD | JBu1AL4obB... |
| BONK/USD | 8ihFLu5FN... |
Devnet
| Asset | Feed Address |
|---|
| SOL/USD | J83w4HKfq... |
| BTC/USD | HovQMDrbA... |
| ETH/USD | EdVCmQ9F... |
Market ID Calculation
// Calculate market ID from timestamp and duration
function getMarketId(timestamp: number, durationSeconds: number = 900): bigint {
return BigInt(Math.floor(timestamp / durationSeconds));
}
// Get market boundaries
function getMarketBoundaries(
marketId: bigint,
durationSeconds: number = 900
): {
start: number;
end: number;
} {
const start = Number(marketId) * durationSeconds;
return {
start,
end: start + durationSeconds,
};
}
// Get current market
function getCurrentMarket(): bigint {
return getMarketId(Math.floor(Date.now() / 1000));
}
Order Side Encoding
enum OrderSide {
BuyYes = 0,
SellYes = 1,
BuyNo = 2, // Converted to SellYes internally
SellNo = 3, // Converted to BuyYes internally
}
Outcome Encoding
enum Outcome {
Up = 0, // YES wins
Down = 1, // NO wins
}
Market State Encoding
enum MarketState {
Created = 0,
Trading = 1,
Settling = 2,
Resolved = 3,
Closed = 4,
}
RPC Endpoints
Mainnet
https://api.mainnet-beta.solana.com
https://seesaw.helius-rpc.com (recommended)
Devnet
https://api.devnet.solana.com
SDK Installation
# npm
npm install @seesaw/sdk
# yarn
yarn add @seesaw/sdk
# pnpm
pnpm add @seesaw/sdk
Quick Examples
Read Market
import { getMarket } from '@seesaw/sdk';
const market = await getMarket(connection, marketPubkey);
console.log('State:', market.state);
console.log('YES shares:', market.totalYesShares);
Place Order
import { placeOrder, OrderSide } from '@seesaw/sdk';
const tx = await placeOrder({
connection,
market: marketPubkey,
user: userPubkey,
side: OrderSide.BuyYes,
price: 5500, // 0.55 USDC in bps
quantity: 100,
});
Settle Position
import { settlePosition } from '@seesaw/sdk';
const tx = await settlePosition({
connection,
market: marketPubkey,
user: userPubkey,
});
Glossary
| Term | Definition |
|---|
| Basis Point (bps) | 1/100th of a percent. 10,000 bps = 100% |
| Crank | Permissionless operation advancing protocol state |
| Epoch | Market window (configurable: 60s–7d) |
| Maker | Order placer whose order rests on book |
| Market ID | floor(timestamp / duration_seconds) |
| PDA | Program Derived Address |
| Pyth | Decentralized oracle network |
| Taker | Party executing against resting orders |
| Tick | Minimum price increment |