Skip to main content

Trading & Redemption

This guide covers the full trading lifecycle: finding markets, checking prices, executing trades, and redeeming winnings.

How to Fetch Market Addresses

Before trading, you may want to fetch the addresses of available markets.

Fetching V2 Market Addresses

import { PNPClient } from 'pnp-sdk';

// Configuration
const RPC_URL = 'https://api.mainnet-beta.solana.com';

async function main() {
  // Initialize the client
  const client = new PNPClient(RPC_URL);

  // Fetch market addresses from proxy
  const addresses = await client.fetchMarketAddresses();

  console.log(`Found ${addresses.length} V2 markets:`);
  addresses.forEach((addr) => console.log(addr));
}

main().catch(console.error);

Fetching P2P Market Addresses

import { PNPClient } from 'pnp-sdk';

// Configuration
const RPC_URL = 'https://api.mainnet-beta.solana.com';

async function main() {
  // Initialize client
  const client = new PNPClient(RPC_URL);

  // Fetch P2P market addresses
  const marketAddresses = await client.fetchV3MarketAddresses();

  console.log(`Found ${marketAddresses.length} P2P markets:`);
  marketAddresses.forEach((address) => console.log(address));
}

main().catch(console.error);

How to Get Market Prices & Multipliers

For V2 AMM markets, you can fetch real-time prices and multipliers without needing a wallet or private key. This is useful for displaying market data in UIs, calculating potential returns, or building analytics tools.

Getting V2 Market Price Data

import { PNPClient } from 'pnp-sdk';

// No private key needed - just RPC URL!
const client = new PNPClient("https://api.devnet.solana.com");

async function main() {
  const marketAddress = "7AENtBCWx8..."; // Your V2 market address

  const priceData = await client.getMarketPriceV2(marketAddress);

  console.log(`YES: $${priceData.yesPrice.toFixed(4)} (${priceData.yesMultiplier}x)`);
  console.log(`NO:  $${priceData.noPrice.toFixed(4)} (${priceData.noMultiplier}x)`);
}

main().catch(console.error);
Sample Output:
{
  "marketReserves": 1.0,
  "yesTokenSupply": 0.707106,
  "noTokenSupply": 0.707106,
  "yesPrice": 0.7071,
  "noPrice": 0.7071,
  "yesMultiplier": 2.0,
  "noMultiplier": 2.0,
  "marketReservesRaw": "1000000",
  "yesTokenSupplyRaw": "707106",
  "noTokenSupplyRaw": "707106"
}
Understanding the Response:
FieldDescription
yesPriceCurrent price of YES tokens (0-1 range, where 1 = $1)
noPriceCurrent price of NO tokens (0-1 range, where 1 = $1)
yesMultiplierPotential return multiplier if YES wins (e.g., 2x = double your money)
noMultiplierPotential return multiplier if NO wins
marketReservesTotal collateral in the market (human-readable units)
yesTokenSupplyTotal YES tokens in circulation (human-readable units)
noTokenSupplyTotal NO tokens in circulation (human-readable units)
marketReservesRawTotal collateral in raw base units (e.g., lamports)
yesTokenSupplyRawTotal YES tokens in raw base units
noTokenSupplyRawTotal NO tokens in raw base units
Key Points:
  • No private key or wallet required - purely read-only operation
  • Prices are calculated from the AMM’s constant product formula
  • Multipliers show the potential payout ratio (e.g., 2x means 1betwins1 bet wins 2)
  • Raw values are provided for precision when working with on-chain amounts
  • Works with any V2 AMM market address

Use Cases

Displaying Market Cards:
const priceData = await client.getMarketPriceV2(marketAddress);

// Show implied probability (price = probability in prediction markets)
const yesProb = (priceData.yesPrice * 100).toFixed(1);
const noProb = (priceData.noPrice * 100).toFixed(1);

console.log(`Market: Will BTC hit $200k?`);
console.log(`YES: ${yesProb}% chance (${priceData.yesMultiplier.toFixed(2)}x payout)`);
console.log(`NO:  ${noProb}% chance (${priceData.noMultiplier.toFixed(2)}x payout)`);
Calculating Potential Returns:
const priceData = await client.getMarketPriceV2(marketAddress);
const betAmount = 100; // $100 USDC

const potentialYesWin = betAmount * priceData.yesMultiplier;
const potentialNoWin = betAmount * priceData.noMultiplier;

console.log(`If you bet $${betAmount} on YES and win: $${potentialYesWin.toFixed(2)}`);
console.log(`If you bet $${betAmount} on NO and win: $${potentialNoWin.toFixed(2)}`);

How to Trade

Once markets are created, users can trade by buying or selling outcome tokens (YES/NO).

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.
import { PublicKey } from '@solana/web3.js';
import { PNPClient } from 'pnp-sdk';

// Configuration
const RPC_URL = 'https://api.mainnet-beta.solana.com';
const WALLET_SECRET_ARRAY = [/* Your 64-byte private key array goes here */];
const MARKET_ADDRESS = 'YourMarketAddressHere';

async function main() {
  // Initialize client with private key
  const client = new PNPClient(RPC_URL, Uint8Array.from(WALLET_SECRET_ARRAY));
  const marketPublicKey = new PublicKey(MARKET_ADDRESS);

  // Buy YES tokens with 1 USDC
  const buyResult = await client.trading.buyTokensUsdc({
    market: marketPublicKey,
    buyYesToken: true,  // true for YES, false for NO
    amountUsdc: 1,      // Amount in USDC
  });

  console.log('Trade successful!');
  console.log('Signature:', buyResult.signature);
  console.log('Tokens received:', buyResult.tokensReceived);
}

main().catch(console.error);
Key Points for V2 AMM Trading:
  • Use client.trading.buyTokensUsdc() to buy outcome tokens
  • Set buyYesToken: true for YES tokens, false for 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

import { PNPClient } from 'pnp-sdk';

// Configuration
const RPC_URL = 'https://api.mainnet-beta.solana.com';

async function main() {
  // Initialize read-only client (no private key needed)
  const client = new PNPClient(RPC_URL);

  // Fetch all P2P market addresses
  const marketAddresses = await client.fetchV3MarketAddresses();

  console.log(`Found ${marketAddresses.length} P2P markets:`);
  marketAddresses.forEach((address, index) => {
    console.log(`${index + 1}. ${address}`);
  });
}

main().catch(console.error);

Trading on P2P Markets

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

// Configuration
const RPC_URL = 'https://api.mainnet-beta.solana.com';
const WALLET_SECRET_ARRAY = [/* Your 64-byte private key array goes here */];
const MARKET_ADDRESS = 'YourP2PMarketAddressHere';

async function main() {
  // Initialize client with private key
  const client = new PNPClient(RPC_URL, Uint8Array.from(WALLET_SECRET_ARRAY));
  const market = new PublicKey(MARKET_ADDRESS);

  // Buy tokens on P2P market
  const result = await client.tradeP2PMarket({
    market,
    side: 'yes',  // 'yes' or 'no'
    amount: 1_000_000n,  // Amount in base units (e.g., 1 USDC with 6 decimals)
  });

  console.log('P2P trade successful!');
  console.log('Signature:', result.signature);
}

main().catch(console.error);
Key Points for P2P Market Trading:
  • Use client.fetchV3MarketAddresses() to get all available P2P markets (no auth required)
  • Use client.tradeP2PMarket() to execute trades
  • Specify side as 'yes' or 'no'
  • Amount is in base units (for USDC: 1_000_000 = 1 USDC)
Comparison: V2 AMM vs P2P Trading
FeatureV2 AMM MarketP2P Market
Trading Methodclient.trading.buyTokensUsdc()client.tradeP2PMarket()
Price DiscoveryAutomated via AMMDirect peer-to-peer
LiquidityPool-basedCreator/participant-based
Amount FormatUSDC amount (e.g., 1 for 1 USDC)Base units (e.g., 1_000_000n for 1 USDC)
Market DiscoveryVia 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.
import { PublicKey } from '@solana/web3.js';
import { PNPClient } from 'pnp-sdk';

// Configuration
const RPC_URL = 'https://api.mainnet-beta.solana.com';
const WALLET_SECRET_ARRAY = [/* Your 64-byte private key array goes here */];
const MARKET_ADDRESS = 'YourMarketAddressHere';

async function main() {
  // Initialize client with private key
  const client = new PNPClient(RPC_URL, Uint8Array.from(WALLET_SECRET_ARRAY));
  const market = new PublicKey(MARKET_ADDRESS);

  // Check market status
  const { account: marketAccount } = await client.fetchMarket(market);

  if (!marketAccount.resolved) {
    console.log('Market is not yet resolved. Cannot redeem position.');
    return;
  }

  console.log('Market is resolved!');
  console.log('Winning Token ID:', marketAccount.winning_token_id);

  // Redeem winning position
  // This works for both V2 AMM and P2P markets
  const result = await client.redeemPosition(market);

  console.log('Position redeemed successfully!');
  console.log('Signature:', result.signature);
}

main().catch(console.error);
Key Points for Redemption:
  • 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