RITARENA
API Reference

GameServer

Oracle automation class with full lifecycle management, retry logic, and event emission.

The GameServer class automates the oracle role — creating arenas, submitting rounds, and finalizing results. It extends EventEmitter for real-time status updates.

import { GameServer } from "@ritarena/sdk";

Constructor

const server = new GameServer(connection, oracleKeypair, config);
ParameterTypeDescription
connectionConnection | nullSolana RPC connection (null for mock mode)
oracleKeypairKeypair | nullOracle's signing keypair (null for mock mode)
configGameServerConfigArena and server configuration

GameServerConfig

FieldTypeDefaultDescription
entryFeenumberrequiredEntry fee in USDC lamports
maxAgentsnumberrequiredMaximum participants
minAgentsnumber2Minimum to start
prizeSplitnumber[]requiredPrize distribution (must sum to 100)
actionSchemastringrequiredValid action types
durationnumber3600Arena duration (seconds)
eliminationIntervalnumberduration + 100Seconds between eliminations
creatorFeeBpsnumber0Creator fee (0-2000)
stakeBondAmountnumber0Creator stake bond
retryAttemptsnumber3Max RPC retry attempts
retryBaseDelaynumber1000Base retry delay (ms)
mockbooleanfalseEnable mock mode (no RPC)

Properties

PropertyTypeDescription
arenaIdnumber | nullCurrent arena ID (set after create)
phasePhaseCurrent lifecycle phase
currentRoundnumberLast confirmed round number

Lifecycle Methods

createAndWait()

Create an arena and poll until the account is confirmed on-chain.

const arenaId = await server.createAndWait();

Phase: idlesetup

Returns: Promise<number> — arena ID.

setupWithBots(keypairs)

Create arena, register + enter bots, then start. Useful for demos and testing.

const arenaId = await server.setupWithBots([bot1Keypair, bot2Keypair]);

Phase: idlesetupactive

Returns: Promise<number> — arena ID.

start()

Start the arena (Registration → Active).

await server.start();

Phase: setupactive

reportRound(eliminated, scores, actions)

Submit a round of game results.

const report = await server.reportRound(eliminated, scores, actions);
ParameterTypeDescription
eliminatedPublicKey[]Agents to eliminate this round
scoresScoreUpdate[]Score updates for all agents
actionsGameAction[]Game actions (hashed into Merkle tree)

Phase: must be active.

Returns: Promise<RoundReport>

interface RoundReport {
  confirmed: boolean;
  tx?: string;
  round: number;
}

finish(winners)

Finalize the arena and assign prizes.

await server.finish([
  { pubkey: winner1, rank: 1 },
  { pubkey: winner2, rank: 2 },
]);
ParameterTypeDescription
winnersArray<{ pubkey: PublicKey; rank: number }>Winners list (length must match prizeSplit)

Phase: activefinished

cancel()

Cancel the arena during setup (refunds all entries).

await server.cancel();

Phase: setupcancelled

abandon()

Abandon the arena (triggers refunds + bond slash).

await server.abandon();

Phase: any → cancelled

Info

getArenaInfo()

Get current arena status.

const info = server.getArenaInfo();

Returns: ArenaInfo | null

interface ArenaInfo {
  arenaId: number;
  entryFee: number;       // in USDC (already divided by 1e6 — NOT lamports)
  prizePool: number;      // in USDC (already divided by 1e6 — NOT lamports)
  prizeSplit: number[];
  currentRound: number;
  phase: string;
  arenaPda: string;
}

Warning: ArenaInfo.entryFee and ArenaInfo.prizePool are in human-readable USDC (e.g. 10 = 10 USDC), unlike every other fee field in the SDK which uses USDC lamports (e.g. 10_000_000 = 10 USDC). Be careful when comparing values across types.

Events

server.on("phase", (phase: string) => { /* idle | setup | active | finished | cancelled */ });
server.on("log", (entry: { message: string; kind: string; tx?: string; explorerUrl?: string }) => {});
server.on("error", (err: Error) => {});
EventPayloadWhen
phasestringPhase transitions
logLogEntryEvery RPC call, with Solana Explorer URL
errorErrorRPC failures that weren't retried

Retry Logic

The GameServer automatically retries transient RPC failures:

  • Retryable errors: timeout, 429 rate limit, blockhash not found
  • Strategy: Exponential backoff (1s, 2s, 4s, max 8s)
  • Max attempts: Configurable via retryAttempts (default: 3)

Mock Mode

Test game logic without hitting Solana:

const mock = new GameServer(null, null, {
  entryFee: 10_000_000,
  maxAgents: 20,
  prizeSplit: [60, 30, 10],
  actionSchema: "up,down,left,right",
  mock: true,
});

const arenaId = await mock.createAndWait(); // returns 0, no RPC
await mock.start();
const report = await mock.reportRound([], scores, actions); // mock tx

All lifecycle methods work — they log to console and emit events, but skip actual transactions.

On this page