Skip to content

Latest commit

 

History

History
231 lines (171 loc) · 7.43 KB

File metadata and controls

231 lines (171 loc) · 7.43 KB

PNP Markets — Program Addresses & PDA Derivations

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


Program IDs

Network Program ID Usage
Mainnet 8PyE2dizL52ga7ytqLtqRyjwWp4yXEx8M5Z4BAHgHuTb Production prediction market program
Devnet pnpkv2qnh4bfpGvTugGDSEhvZC7DP4pVxTuDykV3BGz Testing & 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

Token Mint Address Decimals Notes
USDC EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v 6 Common stablecoin collateral
USDT Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB 6 Alternative stablecoin
WSOL So11111111111111111111111111111111111111112 9 Wrapped 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

PDA Seeds Notes
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

Program Address Usage
SPL Token TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA Standard token operations
SPL Associated Token Account ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL ATA derivation
Token-2022 TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb Extended token standard (collateral support)
Metaplex Token Metadata metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s Token metadata
System Program 11111111111111111111111111111111 Account 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());