PNP Markets

April 11, 2026 · View on GitHub

Complete reference for all program IDs, token mints, and Program Derived Addresses (PDAs) used by the PNP Protocol on Solana.


Program IDs

NetworkProgram IDUsage
Mainnet8PyE2dizL52ga7ytqLtqRyjwWp4yXEx8M5Z4BAHgHuTbProduction prediction market program
Devnetpnpkv2qnh4bfpGvTugGDSEhvZC7DP4pVxTuDykV3BGzTesting & development

The SDK auto-detects the network from the RPC URL:

  • URLs containing devnet, dev., or :8899 → Devnet program ID
  • All other URLs → Mainnet program ID

Collateral Token Mints

TokenMint AddressDecimalsNotes
USDCEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v6Common stablecoin collateral
USDTEs9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB6Alternative stablecoin
WSOLSo111111111111111111111111111111111111111129Wrapped SOL

Any SPL token (including Token-2022) can be used as collateral. Decision tokens (YES/NO) are always standard SPL Token.


PDA Derivation Functions

All PDA functions are exported from pnp-sdk under the pdas namespace:

import { pdas } from 'pnp-sdk';
import { PublicKey } from '@solana/web3.js';

const PROGRAM_ID = new PublicKey('8PyE2dizL52ga7ytqLtqRyjwWp4yXEx8M5Z4BAHgHuTb');

Global Config PDA

Singleton account storing protocol-wide settings (fees, admin, metadata URIs).

const [globalConfigPda, bump] = pdas.deriveGlobalConfigPda(PROGRAM_ID);
// Seeds: ["global_config"]

Market PDA (from mints)

Derives the market account address from its YES and NO token mints.

const [marketPda, bump] = pdas.deriveMarketPdaFromMints(
  yesMint,   // PublicKey — YES token mint
  noMint,    // PublicKey — NO token mint
  PROGRAM_ID
);
// Seeds: ["market", yesMint, noMint]

Market PDA (from base/quote mints)

Alternative derivation using base and quote mint addresses.

const [marketPda, bump] = pdas.deriveMarketPda(
  baseMint,   // PublicKey — Base token mint
  quoteMint,  // PublicKey — Quote token mint
  PROGRAM_ID
);
// Seeds: ["market", baseMint, quoteMint]

Position PDA

Derives a user's position account for a specific market.

const [positionPda, bump] = pdas.derivePositionPda(
  marketPubkey,  // PublicKey — Market address
  ownerPubkey,   // PublicKey — User's wallet
  PROGRAM_ID
);
// Seeds: ["position", market, owner]

YES Token Mint PDA

Derives the YES decision token mint from the global market ID.

const [yesTokenMint, bump] = pdas.deriveYesTokenMint(
  globalId,   // bigint — Global incrementing market ID (from GlobalConfig.global_id)
  PROGRAM_ID
);
// Seeds: ["yes_token", globalId (u64 LE)]

NO Token Mint PDA

Derives the NO decision token mint from the global market ID.

const [noTokenMint, bump] = pdas.deriveNoTokenMint(
  globalId,   // bigint — Global incrementing market ID
  PROGRAM_ID
);
// Seeds: ["no_token", globalId (u64 LE)]

Creator Fee Treasury PDA

Derives the creator's fee treasury for collecting market creator fees.

// Current format (multi-collateral — use for all new markets)
const [treasuryPda, bump] = pdas.deriveCreatorFeeTreasuryPda(
  creatorPubkey,     // PublicKey — Market creator's wallet
  PROGRAM_ID,
  collateralMint     // PublicKey — Collateral token mint
);
// Seeds: ["creator_fee_treasury", creator, collateralMint]

// Legacy format (pre-multi-collateral — USDC-only markets created before update)
const [legacyTreasuryPda, bump] = pdas.deriveCreatorFeeTreasuryPdaLegacy(
  creatorPubkey,     // PublicKey — Market creator's wallet
  PROGRAM_ID
);
// Seeds: ["creator_fee_treasury", creator]

Token Metadata PDA (Metaplex)

Derives the Metaplex token metadata account for a mint.

const METAPLEX_METADATA_PROGRAM = new PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s');

const [metadataPda, bump] = pdas.deriveTokenMetadataPda(
  mintPubkey,                  // PublicKey — Token mint
  METAPLEX_METADATA_PROGRAM
);
// Seeds: ["metadata", metadataProgramId, mint]

Associated Token Account (ATA)

Derives the ATA for a given owner and mint. Used for all token balance lookups and transfers.

const ata = pdas.deriveAta(
  ownerPubkey,      // PublicKey — Wallet address
  mintPubkey,       // PublicKey — Token mint
  allowOwnerOffCurve,  // boolean (default: false) — True for PDAs
  tokenProgramId,      // PublicKey (default: TOKEN_PROGRAM_ID)
  ataProgramId         // PublicKey (default: ASSOCIATED_TOKEN_PROGRAM_ID)
);
// Standard ATA derivation using @solana/spl-token

PDA Seed Summary

PDASeedsNotes
Global Config["global_config"]Singleton — one per program
Market (from mints)["market", yesMint, noMint]Primary market lookup
Market (alt)["market", baseMint, quoteMint]Alternative derivation
Position["position", market, owner]Per-user, per-market
YES Token Mint["yes_token", globalId(u64 LE)]One per market
NO Token Mint["no_token", globalId(u64 LE)]One per market
Creator Fee Treasury["creator_fee_treasury", creator, collateralMint]Current format (multi-collateral)
Creator Fee Treasury (Legacy)["creator_fee_treasury", creator]Legacy format (USDC-only, pre-update)
Token Metadata["metadata", metadataProgramId, mint]Metaplex standard

External Programs

ProgramAddressUsage
SPL TokenTokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DAStandard token operations
SPL Associated Token AccountATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knLATA derivation
Token-2022TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEbExtended token standard (collateral support)
Metaplex Token MetadatametaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1sToken metadata
System Program11111111111111111111111111111111Account creation

Deriving Addresses in Practice

Full Example: Find a Market's Token Accounts

import { PNPClient, pdas } from 'pnp-sdk';
import { PublicKey } from '@solana/web3.js';

const client = new PNPClient('https://api.mainnet-beta.solana.com');
const PROGRAM_ID = new PublicKey('8PyE2dizL52ga7ytqLtqRyjwWp4yXEx8M5Z4BAHgHuTb');

// Fetch a market
const marketAddress = new PublicKey('HxnpHygK1v7TqodWqAv6RvcEiK9zxAgw5jPZ6rskgj2E');
const { account } = await client.fetchMarket(marketAddress);

// Derive the user's token accounts
const userWallet = new PublicKey('YourWalletAddress');
const yesAta = pdas.deriveAta(userWallet, new PublicKey(account.yes_token_mint));
const noAta = pdas.deriveAta(userWallet, new PublicKey(account.no_token_mint));
const collateralAta = pdas.deriveAta(userWallet, new PublicKey(account.collateral_token));

console.log('YES token ATA:', yesAta.toBase58());
console.log('NO token ATA:', noAta.toBase58());
console.log('Collateral ATA:', collateralAta.toBase58());

Verify Market from Global ID

// If you know the global market ID, derive the mints
const globalId = 42n;
const [yesMint] = pdas.deriveYesTokenMint(globalId, PROGRAM_ID);
const [noMint] = pdas.deriveNoTokenMint(globalId, PROGRAM_ID);
const [marketPda] = pdas.deriveMarketPdaFromMints(yesMint, noMint, PROGRAM_ID);

console.log('Market #42:', marketPda.toBase58());