PnP SDK Documentation
Table of Contents
- Overview
- How to Create a Market
- How to Get Refund Initial Liquidity
- How to Fetch Market Addresses
- How to Trade
- How to Redeem Winnings
- API Reference
- Usage Examples
- CLI Usage
- Best Practices
- FAQ
- Contributing
- Changelog
Overview
The PnP SDK is a TypeScript library for interacting with Solana-based prediction markets. It provides a clean, type-safe interface for creating markets, trading positions, and managing market operations on the Solana blockchain.Features
- Create and manage prediction markets on Solana
- Trade YES/NO tokens
- Redeem positions for resolved markets
- Claim creator refunds for unresolved markets
- Interact with on-chain market data
- Fetch settlement criteria from proxy server
- TypeScript-first development experience
- Comprehensive error handling
- Built on top of
@solana/web3.jsand supports both SPL Token and Token-2022 programs
Prerequisites
- Node.js 16+
- npm or yarn
- Solana CLI (for local development)
- Basic understanding of Solana and blockchain concepts
Installation
Quick Start
-
Install the package:
-
Import the SDK - Two methods are supported:
Method 1: ESM Direct Import (Recommended)
Method 2: CommonJS Require (For compatibility)
-
Initialize the client:
-
Example operation - fetching market info:
How to Create a Market
This section provides complete working scripts for creating prediction markets using the PNP SDK. There are two types of markets you can create:- V2 AMM Markets: Traditional automated market maker (AMM) pools where liquidity is provided upfront
- P2P Markets: Peer-to-peer markets where the creator takes a position on one side
Creating a V2 AMM Market
V2 markets use an AMM model where you provide initial liquidity that gets split between YES and NO tokens. This script demonstrates how to create a V2 market with USDC as collateral.- Initial liquidity is split equally between YES and NO tokens in the AMM pool
- The creator doesn’t take a position; they provide liquidity for others to trade against
- Use
client.market.createMarket()for V2 markets
Creating a P2P Market
P2P markets are peer-to-peer markets where the creator takes a position on one side (YES or NO) with a specified cap. This script demonstrates how to create a P2P market.- The creator takes a position on one side (YES or NO) with an initial amount
creatorSideCapdefines the maximum amount the creator is willing to bet on their chosen side- Other users can take the opposite position
- Use
client.createP2PMarketGeneral()for P2P markets
| Feature | V2 AMM Market | P2P Market |
|---|---|---|
| Market Type | Automated Market Maker | Peer-to-Peer |
| Creator Position | No position (provides liquidity) | Takes YES or NO position |
| Initial Liquidity | Split equally between YES/NO | Goes to creator’s chosen side |
| SDK Method | client.market.createMarket() | client.createP2PMarketGeneral() |
| Side Selection | N/A | Required (yes/no) |
| Creator Cap | N/A | Required (creatorSideCap) |
| Use Case | Traditional prediction markets | Targeted position markets |
Creating a Twitter Market
Twitter markets are linked to specific tweets. The SDK can automatically detect tweet IDs from URLs and fetch settlement criteria.Creating a V2 Twitter Market
This script demonstrates how to create a V2 AMM market linked to a Twitter post.Creating a P2P Twitter Market
This script demonstrates how to create a P2P market linked to a Twitter post.Creating a YouTube Market
YouTube markets are linked to specific videos. The SDK handles YouTube URL parsing and settlement integration.Creating a V2 YouTube Market
This script demonstrates how to create a V2 AMM market linked to a YouTube video.Creating a P2P YouTube Market
This script demonstrates how to create a P2P market linked to a YouTube video.How to Get Refund Initial Liquidity
If a market cannot be resolved or becomes unresolvable, the market creator can claim a refund of their initial liquidity. This section provides complete working scripts for claiming refunds from both V2 AMM markets and P2P markets.[!IMPORTANT] Only the market creator can claim refunds, and the market must meet specific conditions (such as being unresolvable or past a buffer period).
Claiming Refund for V2 AMM Market
For V2 AMM markets, the creator who provided the initial liquidity can claim a refund if the market is deemed unresolvable. This script demonstrates the refund process for V2 markets.- Only the market creator can claim a refund
- The market must be unresolvable
- Uses
client.claimMarketRefund()method
Claiming Refund for P2P Market
For P2P markets, creators can claim refunds with additional checks including buffer period validation. This script demonstrates the complete refund process for P2P markets with detailed error handling.- Only the market creator can claim a refund
- Must wait for the buffer period to pass before claiming
- Uses
client.claimP2PMarketRefund()for simplified refund claiming - SDK handles creator validation and token program detection automatically
| Error | Description | Solution |
|---|---|---|
BufferPeriodNotPassed | The required waiting period hasn’t elapsed | Wait until the buffer period passes before retrying |
Signer is not the creator | The wallet attempting the refund is not the market creator | Use the creator’s wallet to claim the refund |
Market account not found | Invalid market address provided | Verify the market address is correct |
Redemption module not available | No wallet/signer configured in the client | Initialize PNPClient with a valid private key |
| Feature | V2 AMM Market Refund | P2P Market Refund |
|---|---|---|
| SDK Method | client.claimMarketRefund() | client.claimP2PMarketRefund() |
| Buffer Period | May apply | Required waiting period |
| Creator Validation | Automatic | Explicit check in script |
| Token Program Support | Standard SPL Token | Both SPL Token and Token-2022 |
| Error Details | Basic error messages | Advanced error parsing with codes |
| Complexity | Simple, single method call | More complex, requires PDA derivation |
How to Fetch Market Addresses
Before trading, you may want to fetch the addresses of available markets. This section provides scripts to fetch both V2 AMM and P2P market addresses.Fetching V2 Market Addresses
This script demonstrates how to fetch V2 market addresses from the proxy server.Fetching P2P Market Addresses
This script demonstrates how to fetch the list of available P2P market addresses.How to Trade
Once markets are created, users can trade by buying or selling outcome tokens (YES/NO). This section provides simple examples for trading on both V2 AMM and P2P markets.Trading on V2 AMM Markets
V2 AMM markets allow you to buy YES or NO tokens using USDC as collateral. The AMM automatically determines the price based on the current liquidity pools.- Use
client.trading.buyTokensUsdc()to buy outcome tokens - Set
buyYesToken: truefor YES tokens,falsefor NO tokens - Amount is specified in USDC (e.g.,
1= 1 USDC) - The AMM automatically calculates token price based on liquidity
Trading on P2P Markets
P2P markets work differently - you can fetch available markets and trade directly with the market creator or other participants.Fetching Available P2P Markets
Trading on P2P Markets
- Use
client.fetchV3MarketAddresses()to get all available P2P markets (no auth required) - Use
client.tradeP2PMarket()to execute trades - Specify
sideas'yes'or'no' - Amount is in base units (for USDC: 1_000_000 = 1 USDC)
| Feature | V2 AMM Market | P2P Market |
|---|---|---|
| Trading Method | client.trading.buyTokensUsdc() | client.tradeP2PMarket() |
| Price Discovery | Automated via AMM | Direct peer-to-peer |
| Liquidity | Pool-based | Creator/participant-based |
| Amount Format | USDC amount (e.g., 1 for 1 USDC) | Base units (e.g., 1_000_000n for 1 USDC) |
| Market Discovery | Via client.fetchMarkets() | Via client.fetchV3MarketAddresses() |
How to Redeem Winnings
After a market has been resolved, users holding winning positions (YES or NO tokens) can redeem them for the collateral asset (e.g., USDC).Redeeming from Resolved Markets
This script demonstrates how to check if a market is resolved and redeem winning positions.- Market must be resolved (
marketAccount.resolved === true) - You must hold the winning token (YES or NO)
client.redeemPosition()handles the complexity of burning tokens and transferring collateral- Works for both V2 AMM and P2P markets
API Reference
Core Client
PNPClient
Main client class for interacting with the PNP protocol. This is the primary entry point for all SDK operations.
rpcUrl: The URL of the Solana RPC endpoint (e.g., ‘https://api.mainnet-beta.solana.com’)privateKey: (Optional) Private key for signing transactions, provided as:- Base58-encoded string
- Uint8Array containing raw bytes
- Object with secretKey property containing Uint8Array
- Without a private key, only read-only methods will be available
- With a valid private key, all modules (market, trading, redemption) are initialized
- The client automatically detects and supports both SPL Token and Token-2022 programs
SDK Module Structure
The PNP SDK is organized into modules for different functionality areas:-
Core Client Methods - Available directly on the
PNPClientinstance:redeemPosition- Redeem winning positions after market resolutionclaimMarketRefund- Claim refund for unresolvable marketsfetchMarket,fetchMarkets,fetchGlobalConfig- Read-only data methodsfetchSettlementCriteria,getSettlementCriteria- Proxy server integrationfetchSettlementData,getSettlementData- Get market settlement detailsfetchMarketAddresses- Get all market addresses from proxy
-
Market Module - Available via
client.market(requires signer):createMarket- Create new prediction markets
-
Trading Module - Available via
client.trading(requires signer):buyOutcome- Buy YES/NO tokens with collateralsellOutcome- Sell YES/NO tokens for collateralgetMarketInfo- Get detailed market information
-
Redemption Module - Available via
client.redemption(requires signer):redeemPositionV2- Low-level position redemption (used by coreredeemPosition)creatorRefund,creatorRefundV2- Low-level refund methods
-
Anchor-based Modules - Available via
client.anchorMarketandclient.anchorClient(optional):- Provides Anchor program interfaces for advanced use cases
Main SDK Methods
redeemPosition(market: PublicKey, options?: RedeemPositionOptions): Promise<{ signature: string }>
Redeems a winning position in a resolved market. This is used to claim your winnings after a market has been resolved.
Parameters:
market: PublicKey - The market where the position was createdoptions: (Optional) Configuration objectadmin: PublicKey - Override the admin account from global configmarketCreator: PublicKey - Override the market creator from market accountcreatorFeeTreasury: PublicKey - Override the creator fee treasury account
claimMarketRefund(market: PublicKey): Promise<{ signature: string }>
Claims a refund for a market creator if the market is not resolvable. This method allows creators to retrieve their initial liquidity if the market cannot be resolved.
Parameters:
market: PublicKey - The market to claim the refund for
- Market must not be resolvable (checked via on-chain flag or proxy server)
- The caller (signer) must be the market creator
Read-Only Helpers
These methods are available even without providing a private key to the client constructor.fetchMarket(market: PublicKey): Promise<{ publicKey: PublicKey; account: MarketType }>
Fetches detailed information about a specific market.
Parameters:
market: PublicKey - The market to fetch information for
publicKey: PublicKey - The market’s public keyaccount: MarketType - The market account data
fetchMarkets(): Promise<MarketsResponse>
Fetches all available markets.
Returns: Promise that resolves to an object containing:
count: number - The number of markets founddata: Array of market objects with:publicKey: string - The market’s public key as a base58 stringaccount: MarketType - The market account data
fetchGlobalConfig(): Promise<{ publicKey: PublicKey; account: GlobalConfigType }>
Fetches the global configuration account for the PNP program.
Returns: Promise that resolves to an object containing:
publicKey: PublicKey - The global config account’s public keyaccount: GlobalConfigType - The global config account data
Proxy Server Integration
The SDK provides methods to interact with the PNP proxy server for fetching market data and settlement information.fetchSettlementCriteria(market: string | PublicKey, baseUrl?: string): Promise<SettlementCriteria>
Fetches settlement criteria for a market from the proxy server.
Parameters:
market: string | PublicKey - Market address (as string or PublicKey)baseUrl: string (Optional) - Base URL for the proxy server. Defaults to environment variable or hardcoded value.
getSettlementCriteria(market: string | PublicKey, baseUrl?: string, options?: { retryDelayMs?: number; maxRetryTimeMs?: number }): Promise<SettlementCriteria>
Gets settlement criteria with automatic retry logic. This is useful for waiting for criteria to become available.
Parameters:
market: string | PublicKey - Market address (as string or PublicKey)baseUrl: string (Optional) - Base URL for the proxy serveroptions: (Optional) Retry configurationretryDelayMs: number - Milliseconds to wait between retries (default: 2000)maxRetryTimeMs: number - Maximum time to retry in milliseconds (default: 15 minutes)
fetchSettlementData(market: string | PublicKey, baseUrl?: string): Promise<SettlementData>
Fetches settlement data for a market from the proxy server.
Parameters:
market: string | PublicKey - Market address (as string or PublicKey)baseUrl: string (Optional) - Base URL for the proxy server
getSettlementData(market: string | PublicKey, baseUrl?: string): Promise<SettlementData>
Alias for fetchSettlementData.
fetchMarketAddresses(baseUrl?: string): Promise<string[]>
Fetches all market addresses from the proxy server.
Parameters:
baseUrl: string (Optional) - Base URL for the proxy server
Types
Core Types
Function Parameters
Usage Examples
Creating a Market
This example demonstrates how to create a new prediction market using the SDK.- You must initialize the client with a valid private key to create markets
- The
baseMintparameter specifies the collateral token (e.g., USDC) - Initial liquidity should be specified in the base units of the collateral token
- End time is a Unix timestamp in seconds
Trading Tokens
Buying and Selling Tokens
The trading module allows you to buy and sell YES/NO outcome tokens in a market.Fetching Settlement Criteria
You can fetch settlement criteria from the proxy server to check if a market is resolvable.Getting Comprehensive Market Information
This example shows how to gather all available information about a market from both on-chain data and the proxy server, similar to what’s used in themarket-info.ts script.
CLI Usage
The PNP CLI provides a convenient way to interact with prediction markets. Below are the available commands and their usage.Environment Variables
Commands
Create a New Market
Trading
Market Information
settlementCriteria command prints only the settlement criteria JSON returned by the proxy for the provided <marketId>.
Examples:
Best Practices
Error Handling
Always wrap SDK calls in try-catch blocks and check for specific error conditions:SDK Initialization
-
Read-only operations: Initialize without a private key
-
Write operations: Initialize with a private key
-
Always verify that required modules are available
Performance Optimization
- Batch transactions when possible
- Use commitment levels appropriately
- Cache frequently accessed accounts
- Use connection commitment level ‘confirmed’ for better performance
Security Considerations
- Never expose private keys in client-side code
- Validate all user inputs
- Use the latest version of the SDK
- Verify transaction details before signing
Frequently Asked Questions
How do I get started with the SDK?
See the Quick Start section for installation and basic usage.What networks are supported?
The SDK supports all Solana networks: mainnet-beta, devnet, and testnet.How do I handle transaction timeouts?
Implement retry logic with exponential backoff:How can I monitor market events?
Use Solana’s websocket API to subscribe to program accounts and logs.What’s the difference between market and limit orders?
- Market orders execute immediately at the best available price
- Limit orders only execute at the specified price or better
Contributing
We welcome contributions! Please follow these steps:- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Open a pull request
Development Setup
- Clone the repository
- Install dependencies:
- Build the project:
- Run tests:
Code Style
- Follow TypeScript best practices
- Use ESLint and Prettier for consistent formatting
- Write tests for new features
- Document public APIs with JSDoc
Changelog
v0.1.0 (2025-02-15)
- Initial release
- Basic market creation and trading functionality
- TypeScript type definitions
- Comprehensive documentation
License
Apache-2.0Support
For support, please open an issue on GitHub.Acknowledgments
- PNP team
- Solana Team
- Anchor Framework
- All contributors
