@sportsperp/sdk
v0.1.1
Published
TypeScript SDK for SportsPerp OBV Index Perpetual Futures on Solana
Maintainers
Readme
@sportsperp/sdk
TypeScript SDK for the SportsPerp OBV Index Perpetual Futures protocol on Solana.
Trade perpetual futures on football (soccer) team and player performance indices powered by on-chain oracle data.
Installation
npm install @sportsperp/sdk @coral-xyz/anchor @solana/web3.jsQuick Start
import { Connection, Keypair } from "@solana/web3.js";
import { Wallet } from "@coral-xyz/anchor";
import { SportsPerpsClient, Direction } from "@sportsperp/sdk";
import { BN } from "@coral-xyz/anchor";
// Connect to devnet
const connection = new Connection("https://api.devnet.solana.com");
const wallet = new Wallet(Keypair.generate());
const client = new SportsPerpsClient({ connection, wallet });
// Fetch all markets
const markets = await client.getAllMarkets();
console.log(`${markets.length} markets available`);
// Get a specific market (e.g. Liverpool, market ID 0)
const market = await client.getMarket(0);
console.log(`${market.teamName} — Oracle: ${market.oraclePrice.toNumber()}`);
// Open a long position (10 USDC collateral, 5x leverage)
await client.openPosition(0, {
direction: Direction.Long,
collateral: new BN(10_000_000), // 10 USDC (6 decimals)
leverage: new BN(5_000), // 5x (3 decimal places)
}, userTokenAccount);
// Check position
const position = await client.getPosition(0);
const pnl = client.calculatePnl(position, market.oraclePrice);
console.log(`PnL: ${pnl.toNumber() / 1e6} USDC`);
// Close position
await client.closePosition(0, userTokenAccount);API Reference
SportsPerpsClient
The main entry point. Wraps the program's instruction set with typed methods (27 instruction builders).
Constructor
new SportsPerpsClient({
connection: Connection, // Solana RPC connection
wallet: Wallet, // Anchor wallet (signing keypair)
programId?: PublicKey, // Override program ID (defaults to devnet)
confirmOptions?: ConfirmOptions,
})Admin Methods
| Method | Description |
|--------|-------------|
| initializeMarket(args) | Create a new perpetual market |
| initializePool(args, usdcMint) | Create the global liquidity pool |
| seedPool(amount, adminTokenAccount) | Deposit LP capital into the pool |
| withdrawPoolLp(amount, adminTokenAccount) | Withdraw LP capital above the risk floor |
| initializeInsurance(usdcMint) | Initialize the global insurance fund |
| updateOracle(marketId, args) | Update oracle price for a market |
| pauseMarket(marketId) | Emergency pause a market |
| unpauseMarket(marketId) | Resume a paused market |
| updateMarketParams(marketId, args) | Tune oracle weights / vAMM impact factor |
Trading Methods
| Method | Description |
|--------|-------------|
| openPosition(marketId, args, userTokenAccount) | Open a new position |
| closePosition(marketId, userTokenAccount) | Close position and settle P&L |
| partialClosePosition(marketId, args, userTokenAccount) | Close a fraction of a position |
| addCollateral(marketId, amount, userTokenAccount) | Add USDC collateral |
| withdrawCollateral(marketId, amount, userTokenAccount) | Withdraw collateral (margin check enforced) |
| placeTriggerOrder / cancelTriggerOrder | Place or cancel a SL / TP / Limit-Open order |
Permissionless Methods
| Method | Description |
|--------|-------------|
| applyFunding(marketId) | Crank the funding rate |
| partialLiquidate(marketId, positionOwner) | Layer 1: partial liquidation (5% reward) |
| backstopLiquidate(marketId, positionOwner) | Layer 2: insurance fund absorbs the position |
| unwindBackstop(marketId, ...) | Layer 2: gradually unwind an absorbed position |
| autoDeleverage(marketId, ...) | Layer 3: auto-deleverage an opposing profitable position |
| executeTriggerClose / executeTriggerOpen | Fire an eligible SL / TP / Limit-Open order |
| sunsetMarket(marketId) / settlePosition(...) | Settle a stale market and close residual positions |
| liquidate(marketId, positionOwner, liquidatorTokenAccount) | Legacy single-shot liquidation (kept for compatibility) |
Account Fetchers
| Method | Description |
|--------|-------------|
| getMarket(marketId) | Fetch market config |
| getAllMarkets() | Fetch all markets |
| getPosition(marketId, user?) | Fetch user position |
| getAllUserPositions(user?) | All positions for a user |
| getAllMarketPositions(marketId) | All positions in a market |
| getLiquidityPool() | Fetch global liquidity pool state |
| getInsuranceFund() | Fetch insurance fund state |
| hasPosition(marketId, user?) | Check if position exists |
Math Utilities
| Method | Description |
|--------|-------------|
| calculatePnl(position, currentPrice) | Unrealized P&L |
| marginRatioBps(position, currentPrice) | Margin ratio in basis points |
| isLiquidatable(position, currentPrice) | Liquidation check |
| liquidationPrice(position) | Price at which position liquidates |
Standalone Exports
All client methods are also available as standalone functions:
import {
// Instruction builders
buildOpenPositionIx,
buildClosePositionIx,
// Account fetchers
fetchMarketConfig,
fetchAllMarkets,
// Math
calculatePnl,
isLiquidatable,
// PDA helpers
getMarketConfigPda,
getPositionPda,
// Types
Direction,
MarketType,
PROGRAM_ID,
} from "@sportsperp/sdk";OBV Index
The OBV (On-Ball Value) Index is a composite performance metric:
| Component | Weight | Source | |-----------|--------|--------| | OBV Score | 50% | Proprietary on-ball-value model | | Form | 30% | Recent match results (rolling window) | | Results | 20% | Points per game |
Indices are blended with a 4-hour EMA and updated via on-chain oracles. Markets cover the English Premier League (20 teams + 48 players on devnet).
Network
- Devnet Program ID:
6d4fSCD7mNy7aDNS2mXUxYpZjFFQKBKwAsM5kojKQA6h - Collateral: USDC (SPL Token)
- Oracle: Crank-updated by the SportsPerp oracle service
Development
npm install
npm run build # Compile TypeScript
npm test # Run the test suiteLicense
MIT
