Core Concepts

Understand the fundamental building blocks of the Poll protocol.

Overview

The Poll SDK wraps the Poll Anchor program on Solana. Every action — creating a bet, placing a wager, voting, settling — corresponds to a Solana transaction. This guide explains the key on-chain concepts you need to understand before building.

Program User

Every wallet interacting with the protocol must first create a Program User account. This account tracks statistics and links your wallet to on-chain activity:

typescript
const userAddress = sdk.addresses.user.get(wallet.publicKey);
const user = await sdk.accounts.user.single(userAddress);

console.log("Total wagers:", user.totalWagersCount);
console.log("Total wagered:", user.totalWageredAmount);

Bet

A Bet is a prediction market. It has a question, collects wagers, and resolves through a voting mechanism:

Question

The topic being predicted (max 280 chars)

Options

For (Yes) and Against (No)

Wagers

User positions with USDC amounts

Votes

Resolution votes from participants

Status

Lifecycle state from Draft to Distributed

Pool

Escrow account holding all wagered USDC

typescript
const bet = await sdk.accounts.betV2.single(betAddress);

console.log("Question:", bet.question);
console.log("Total For:", bet.totalOiFor);
console.log("Total Against:", bet.totalOiAgainst);

Wager

A Wager is a user position on a specific bet outcome. The pool of all wagers determines payout ratios — winners split the total pot proportionally:

amountUSDC locked in escrow
sideOutcome.For or Outcome.Against
statusOpen → SettledWin or SettledLoss

Voting & Resolution

Bets resolve through consensus voting among participants:

  1. 1Any participant initiates voting via initiateVoteV2()
  2. 2Participants (or designated resolvers) cast votes via placeVoteV2()
  3. 3Once minimumVoteCount reached with consensus, outcome is finalized
  4. 4Settlement distributes winnings minus protocol fees via settleBetBatchV2()
typescript
import { Outcome } from "@solworks/poll-sdk";

// Outcome options
Outcome.NotResolvedYet; // 0 - Default state
Outcome.For;            // 1 - "Yes" wins
Outcome.Against;        // 2 - "No" wins
Outcome.Tied;           // 3 - Push, refunds issued

Market Status

Bets progress through defined states:

StatusDescription
DraftInitial state, not yet active
PendingActive, accepting wagers
ResolvingVoting in progress
ResolvedOutcome determined, awaiting settlement
DistributedPayouts complete
CanceledBet canceled
RefundedAll wagers returned
typescript
import { MarketStatus } from "@solworks/poll-sdk";

if (bet.status === MarketStatus.Pending) {
  console.log("Bet is accepting wagers");
}

Program Derived Addresses

The SDK provides helpers to derive all on-chain account addresses deterministically:

typescript
// Protocol config
const protocolAddress = sdk.addresses.protocol.get();

// User account
const userAddress = sdk.addresses.user.get(wallet.publicKey);

// Bet account
const betAddress = sdk.addresses.betV2.get(wagerId, creator);

// Pool (escrow) address
const poolAddress = sdk.addresses.poolAuthority.get(wagerId, creator);

USDC & Tokens

All wagers use USDC (an SPL token). The SDK handles token account lookups automatically. Amounts are expressed in human-readable USDC (e.g. 10 = 10 USDC) unless you pass rawAmount:

typescript
// Human-readable — 10 USDC
await sdk.placeWagerV2({ bet, amount: 10, side: Outcome.For, signers });

// Raw — 10,000,000 units (same as 10 USDC)
await sdk.placeWagerV2({ bet, rawAmount: 10_000_000, side: Outcome.For, signers });