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:
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:
The topic being predicted (max 280 chars)
For (Yes) and Against (No)
User positions with USDC amounts
Resolution votes from participants
Lifecycle state from Draft to Distributed
Escrow account holding all wagered USDC
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:
Voting & Resolution
Bets resolve through consensus voting among participants:
- 1Any participant initiates voting via
initiateVoteV2() - 2Participants (or designated resolvers) cast votes via
placeVoteV2() - 3Once
minimumVoteCountreached with consensus, outcome is finalized - 4Settlement distributes winnings minus protocol fees via
settleBetBatchV2()
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 issuedMarket Status
Bets progress through defined states:
| Status | Description |
|---|---|
| Draft | Initial state, not yet active |
| Pending | Active, accepting wagers |
| Resolving | Voting in progress |
| Resolved | Outcome determined, awaiting settlement |
| Distributed | Payouts complete |
| Canceled | Bet canceled |
| Refunded | All wagers returned |
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:
// 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:
// 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 });