Package Exports
- @pit-protocol/sdk
Readme
@pit-protocol/sdk
TypeScript SDK for interacting with the PIT prediction market protocol on Solana.
Installation
npm install @pit-protocol/sdk
# or
pnpm add @pit-protocol/sdkDesign Principles
- SDK provides instruction builders only - Transaction sending/signing is user's responsibility
- Keeper module handles RPC/signing - Only for automation use cases
- Maximum flexibility - Users can compose, batch, simulate as they wish
Quick Start
Creating Instructions
import { createTradeInstruction, PoolType, getMarketAddress, WSOL_MINT } from "@pit-protocol/sdk";
import { Connection, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import BN from "bn.js";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
// Create a trade instruction
const ix = createTradeInstruction({
weekNumber: 1,
poolType: PoolType.High,
strikeIndex: 0,
isHit: true,
amount: new BN(1_000_000_000), // 1 token (9 decimals)
isBuy: true,
user: wallet.publicKey,
userTokenAccount: hitTokenAta,
userWsolAccount: wsolAta,
wsolVault: market.wsolVault,
tokenMint: hitMint,
wsolMint: WSOL_MINT,
tokenProgram: TOKEN_PROGRAM_ID,
});
// User sends the transaction themselves
const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [wallet]);Fetching Market State
import { getMarketAddress, parseMarketAccount } from "@pit-protocol/sdk";
// Get market PDA
const marketPda = getMarketAddress(1); // week number
// Fetch and parse account
const accountInfo = await connection.getAccountInfo(marketPda);
if (accountInfo) {
const market = parseMarketAccount(accountInfo.data.slice(8)); // skip discriminator
console.log(`Week: ${market.weekNumber}`);
console.log(`End: ${new Date(market.endTimestamp.toNumber() * 1000)}`);
console.log(`High Pool Outcome: ${market.highPool.winningOutcome}`);
}Getting Pyth Price
import { PythPriceService } from "@pit-protocol/sdk";
const priceService = new PythPriceService();
// Get latest SOL/USD price
const price = await priceService.getLatestPrice();
console.log(`SOL/USD: $${price.price}`);
console.log(`Price in cents: ${price.priceInCents}`);
// Calculate expected outcome based on price
const outcome = priceService.calculateOutcome(price.priceInCents, strikes);
console.log(`High outcome: ${outcome.highOutcome}`);
console.log(`Low outcome: ${outcome.lowOutcome}`);Keeper Bot (Automated Market Watching)
import { MarketWatcher } from "@pit-protocol/sdk";
import { Connection, Keypair } from "@solana/web3.js";
const connection = new Connection(RPC_URL);
const signer = Keypair.fromSecretKey(/* ... */);
const watcher = new MarketWatcher({
connection,
signer,
weekNumber: 1,
verbose: true,
});
watcher.on("priceUpdate", (price) => {
console.log(`Price: $${price.price}`);
});
watcher.on("outcomeChange", (event) => {
console.log(`${event.poolType} outcome changed: ${event.outcome}`);
console.log(`TX: ${event.signature}`);
});
watcher.on("settled", (event) => {
console.log(`Market ${event.weekNumber} settled!`);
});
watcher.on("error", (err) => {
console.error(`Error: ${err.message}`);
});
// Start watching (runs until both pools settled)
await watcher.start();API Reference
Instruction Builders
All builders return TransactionInstruction - user handles transaction sending.
// Trading
createTradeInstruction(params: TradeInstructionParams): TransactionInstruction
// Market operations (operator only)
createInitializeMarketInstruction(params: InitializeMarketParams): TransactionInstruction
createInitializePoolInstruction(params: InitializePoolParams): TransactionInstruction
createClaimFeesInstruction(params: ClaimFeesParams): TransactionInstruction
createWithdrawSubsidyInstruction(params: WithdrawSubsidyParams): TransactionInstruction
createPauseMarketInstruction(params: PauseMarketParams): TransactionInstruction
createUnpauseMarketInstruction(params: PauseMarketParams): TransactionInstruction
// Permissionless operations (anyone/keeper)
createMarkExtremeInstruction(params: MarkExtremeParams): TransactionInstruction
createSettleMarketInstruction(params: SettleMarketParams): TransactionInstruction
createRedeemInstruction(params: RedeemParams): TransactionInstructionAccount Utilities
// PDA derivation
getMarketAddress(weekNumber: number): PublicKey
getMarketAddressWithBump(weekNumber: number): [PublicKey, number]
getWsolVaultAddress(marketPda: PublicKey, wsolMint: PublicKey): PublicKey
getUserTokenAddress(owner: PublicKey, mint: PublicKey, programId?: PublicKey): PublicKey
// Account parsing
parseMarketAccount(data: Buffer): MarketState
isMarketEnded(market: MarketState): boolean
isFullySettled(market: MarketState): boolean
getTokenMint(pool: PoolState, strikeIndex: number, isHit: boolean): PublicKeyPyth Price Service
class PythPriceService {
constructor(hermesUrl?: string, feedId?: string);
// Get current price
getLatestPrice(): Promise<PythPrice>;
// Get VAA data for on-chain posting
getPriceUpdateData(): Promise<string[]>;
// Calculate outcome from price
calculateOutcome(priceInCents: number, strikes: [BN, BN, BN]): OutcomeResult;
// Check if mark_extreme should be called
shouldMarkExtreme(currentOutcome: number, newOutcome: number): boolean;
}Keeper Module
class MarketWatcher extends EventEmitter {
constructor(config: MarketWatcherConfig)
start(): Promise<void> // Start watching
stop(): void // Stop watching
getStatus(): WatcherStatus
// Events
on('priceUpdate', (price: PythPrice) => void)
on('outcomeChange', (event: OutcomeChangeEvent) => void)
on('settled', (event: SettledEvent) => void)
on('error', (error: WatcherError) => void)
on('stopped', () => void)
}Constants
import {
PROGRAM_ID, // PIT program ID
OPERATOR, // Hardcoded operator address
WAD, // 10^18 precision
TRADE_FEE_PERCENTAGE, // 3% in WAD
SOL_USD_FEED_ID, // Pyth feed ID (bytes)
SOL_USD_PRICE_FEED_ACCOUNT, // Sponsored push feed account (PublicKey)
HERMES_URL, // Pyth Hermes API
WSOL_MINT, // wSOL mint address
TOKEN_2022_PROGRAM_ID,
PYTH_RECEIVER_PROGRAM_ID,
} from "@pit-protocol/sdk";Types
enum PoolType {
High = 0,
Low = 1,
}
interface MarketState {
weekNumber: number;
operator: PublicKey;
wsolVault: PublicKey;
startTimestamp: BN;
endTimestamp: BN;
totalSubsidy: BN;
feesCollected: BN;
isPaused: boolean;
highPool: PoolState;
lowPool: PoolState;
bump: number;
}
interface PoolState {
isInitialized: boolean;
isSettled: boolean;
winningOutcome: number;
qVector: [BN, BN, BN, BN];
b: BN;
strikes: [BN, BN, BN];
hitMints: [PublicKey, PublicKey, PublicKey];
missMints: [PublicKey, PublicKey, PublicKey];
claimedWinnings: BN;
}
interface PythPrice {
price: number; // USD
priceInCents: number; // For strike comparison
confidence: number;
timestamp: number;
}
interface TradeSimulationResult {
grossCost: BN; // Cost before fees (lamports)
fee: BN; // Trading fee (lamports)
netCost: BN; // Total after fees
tokensAmount: BN; // Token amount
pricePerToken: number; // Average price
priceImpact: number; // Impact %
}Trade Simulation Functions
The SDK provides functions to simulate trades before executing them:
import {
tokensForSolBudget,
solCostForTokens,
solRefundForTokens,
tokensForSolTarget,
} from "@pit-protocol/sdk";
// Calculate how many tokens you can buy with X SOL
const result = tokensForSolBudget(poolState, strikeIndex, isHit, solBudget);
console.log(`Can buy ${result.tokensAmount} tokens for ${result.netCost} lamports`);
// Calculate how much SOL to buy X tokens
const buyCost = solCostForTokens(poolState, strikeIndex, isHit, tokenAmount);
console.log(`Buying ${tokenAmount} tokens costs ${buyCost.netCost} lamports`);
// Calculate how much SOL you'll get for selling X tokens
const sellRefund = solRefundForTokens(poolState, strikeIndex, isHit, tokenAmount);
console.log(`Selling ${tokenAmount} tokens returns ${sellRefund.netCost} lamports`);Development
# Install dependencies
pnpm install
# Build
pnpm build
# Clean
pnpm cleanLicense
Apache-2.0