Skip to content

@pokertools/types ​

The shared contract layer of the monorepo. Every package imports its domain types from here, and Zod schemas validate data at the API boundary.

Installation ​

bash
npm install @pokertools/types
bash
pnpm add @pokertools/types

Actions ​

Every state transition is an Action — a discriminated union on type.

ActionType table ​

TypeCategoryPayloadDescription
SITManagementseat, stack, name, idSit at a seat with chips
STANDManagement—Leave the table
SIT_INManagement—Return from sit-out; dealt in from the next hand
ADD_CHIPSManagementamountTop up chips
RESERVE_SEATManagementseatHold a seat for late join
DEALDealing—Shuffle, deal, post blinds/antes
FOLDBetting—Fold current hand
CHECKBetting—Check
CALLBetting—Call the current wager
BETBettingamountOpen bet (or CALL alias when matching the wager)
RAISEBettingamountRaise to amount
SHOWShowdown—Reveal hand at showdown
MUCKShowdown—Muck losing hand
TIMEOUTSpecial—Auto fold/check (workers)
TIME_BANKSpecial—Activate the time bank
UNCALLED_BET_RETURNEDSpecial—Internal: uncalled bet refund
NEXT_BLIND_LEVELTournament—Advance blind level
ts
import { ActionType } from "@pokertools/types";

// Full raise to 60
const raise: Action = {
  type: ActionType.RAISE,
  playerId: "p0",
  amount: 60,
  timestamp: Date.now(),
};

The client action whitelist (CLIENT_ACTION_TYPES) restricts what the API accepts from sockets: management and internal actions are never reachable by clients.

Game state ​

GameState is the immutable snapshot of a table:

FieldTypeDescription
handIdstringStable hand identifier
streetStreetPREFLOP | FLOP | TURN | RIVER | SHOWDOWN
players(Player | null)[]Seat-indexed player slots
decknumber[]Card codes (masked in public views)
currentBetsMap<number, number>Live wagers per seat
potsPot[]Collected pots (main + side)
minRaisenumberMinimum raise-to total
lastRaiseAmountnumberLast full raise increment
lastAggressorSeatnumber | nullSeat of the last aggressor
actionTonumber | nullSeat to act
activePlayersnumber[]Seats still live
winnersWinner[] | nullShowdown awards
bigBlindSeatnumber | nullCurrent or most recent big-blind seat
rakeThisHandnumberRake taken this hand
actionHistoryActionRecord[]Every action with pot/stack effects
previousStatesGameState[]Undo snapshots (stripped from public views)
timeBankActiveSeatnumber | nullSeat with a running time bank
configTableConfigImmutable table configuration
handNumbernumberHand counter
timestampnumberLast update (engine clock)

Player ​

FieldDescription
id / nameIdentity
seatSeat index
stackCurrent chip count
handCard[] | null — private until shown
shownCardsCards revealed at showdown
statusSee PlayerStatus below
betThisStreetWager on the current street
totalInvestedThisHandChips invested this hand (for settlement)
isSittingOutAway flag — timeouts use this
isDealerButton position

Resident enums ​

ts
export const enum PlayerStatus {
  ACTIVE = "ACTIVE",
  FOLDED = "FOLDED",
  ALL_IN = "ALL_IN",
  SITTING_OUT = "SITTING_OUT",
  WAITING = "WAITING",
  BUSTED = "BUSTED",
  RESERVED = "RESERVED",
}

export const enum Street {
  PREFLOP = "PREFLOP",
  FLOP = "FLOP",
  TURN = "TURN",
  RIVER = "RIVER",
  SHOWDOWN = "SHOWDOWN",
}

Configuration ​

ts
interface TableConfig {
  maxPlayers: number; // 2..10
  smallBlind: number;
  bigBlind: number;
  ante?: number; // dead money, not part of live wagers
  initialStack?: number; // tournament-style bench
  rakePercent?: number; // 0..100
  rakeCap?: number;
  noFlopNoDrop?: boolean; // rake applies to flop+ pots only
  minBuyIn?: number; // cash tables
  maxBuyIn?: number;
  blindStructure?: BlindLevel[]; // tournament mode
  allowRebuy?: boolean;
  timeBankSeconds?: number; // default 10s deduction
  clientMode?: boolean; // strict mode for optimistic clients
}

API DTOs ​

PublicState, TournamentDetails, HandHistory, TableListItem and friends model what the API returns. All are Zod-validated:

ts
import { publicStateSchema } from "@pokertools/types";

const parsed = publicStateSchema.safeParse(response.body);
if (!parsed.success) {
  // handle invalid server response
}

Error codes ​

CodeMeaning
INVALID_AMOUNTNon-finite, fractional, negative or unsafe chip amounts
INVALID_SEATSeat outside 0..maxPlayers-1 or non-integer
CANNOT_RERAISEBetting not reopened (TDA rule 47)
RAISE_TOO_SMALLRaise below the minimum raise-to
NOT_YOUR_TURNAction received out of turn
INSUFFICIENT_CHIPSStack too small for the wager
TABLE_FULL / SEAT_TAKENSeat management conflicts
ILLEGAL_ACTIONEverything else the state machine rejects

WebSocket messages ​

The API pushes STATE_UPDATE frames over pubsub:table:{tableId} carrying { tableId, version, timestamp }; the SDK fetches the new state over HTTP and keeps a local version cache.

Released under the MIT License.