theref-sdk
v0.1.1
Published
Universal SDK for TheRef — the decentralized AI game referee on GenLayer
Maintainers
Readme
@theref/sdk
Universal SDK for TheRef — the decentralized AI game referee on GenLayer.
Submit any game move in any format. TheRef's AI consensus judges it on-chain.
Install
npm install @theref/sdkQuick Start
import { createTheRef } from "@theref/sdk";
const ref = createTheRef({
network: "bradbury",
privateKey: process.env.AGENT_KEY as `0x${string}`,
});
// Create a game
const gameId = await ref.createGame({
name: "Trivia",
player1: "Alice",
player2: "Bob",
maxRounds: 3,
});
// Submit a move — any format works
await ref.submitMove(gameId, "Alice", "The capital of Australia is Canberra, established 1913");
await ref.submitMove(gameId, "Bob", "Canberra");
// Judge — AI consensus decides the winner
const result = await ref.judgeGame(gameId);
console.log(result.winner); // "Alice"Universal Move Format
The SDK accepts any move format and converts it to a string the AI judge can understand.
Strings (passthrough)
await ref.submitMove(gameId, "Zaid", "e4");
await ref.submitMove(gameId, "Zaid", "I choose Rock");
await ref.submitMove(gameId, "Zaid", "The answer is 42");Chess moves
// Algebraic notation
await ref.submitMove(gameId, "Zaid", "Nf3", "Chess");
// Move object
await ref.submitMove(gameId, "Zaid", { from: "g1", to: "f3" }, "Chess");
// → "g1-f3"
// With piece
await ref.submitMove(gameId, "Zaid", { piece: "knight", from: "g1", to: "f3" });
// → "Nf3"
// Coordinate array [fromFile, fromRank, toFile, toRank]
await ref.submitMove(gameId, "Zaid", [6, 0, 5, 2]);
// → "g1-f3"Rock Paper Scissors
await ref.submitMove(gameId, "Zaid", "rock"); // → "Rock"
await ref.submitMove(gameId, "Zaid", { choice: "paper" }); // → "Paper"
await ref.submitMove(gameId, "Zaid", 0); // → "Rock" (0=Rock, 1=Paper, 2=Scissors)Combat games (RPG, Pokemon, fighting games)
// Pokemon battle
await ref.submitMove(gameId, "Ash", {
action: "attack",
move: "Thunderbolt",
target: "Charizard",
power: 90,
type: "Electric",
});
// → "Ash uses Thunderbolt on Charizard (power: 90) [Electric type]"
// Fighting game
await ref.submitMove(gameId, "Ryu", {
special: "Hadouken",
combo: ["down", "forward", "punch"],
});
// → "uses Hadouken via combo: down+forward+punch special: Hadouken"
// Card game
await ref.submitMove(gameId, "Player1", {
action: "play_card",
card: "Fireball",
target: "enemy_hero",
mana_cost: 4,
});
// → "play_card on enemy_hero (mana: 4)"Strategy / board games
await ref.submitMove(gameId, "Commander", {
action: "deploy",
unit: "Tank",
from: { x: 2, y: 3 },
to: { x: 5, y: 7 },
attack: "Artillery",
});
// → "deploy Tank from {"x":2,"y":3} to {"x":5,"y":7} attacking with Artillery"Any object — auto-flattened
await ref.submitMove(gameId, "Player", {
turn: 5,
decision: "advance",
units: ["Archer", "Knight"],
target: { zone: "north", priority: "high" },
});
// → "turn: 5, decision: advance, units: [Archer, Knight], target.zone: north, target.priority: high"Arrays
await ref.submitMove(gameId, "Player", ["Attack", "North", "With cavalry"]);
// → "Attack, North, With cavalry"Game Lifecycle
Full game loop
const result = await ref.playGame(
gameId,
"MyAgent",
true, // isPlayer1
async (state, round) => {
// Your move generation logic here
// Return ANY format — SDK normalizes it
return `My answer for round ${round}`;
},
"Trivia", // game hint for better normalization
);
console.log(`Winner: ${result.winner}`);Manual control
// Wait for opponent's move
const opponentMove = await ref.waitForOpponentMove(gameId, 1, true);
// Submit your move
await ref.submitMove(gameId, "Alice", myMove);
// Wait for game to complete
const state = await ref.waitForStatus(gameId, "completed");
// Judge
const result = await ref.judgeGame(gameId);Leaderboard
// All players
const lb = await ref.getLeaderboard("Chess", "all");
// Agents only
const agents = await ref.getLeaderboard("Trivia", "agent");
// Top 10
const top = await ref.getTopPlayers("Chess", 10);
// Single player stats
const stats = await ref.getPlayerStats("Chess", "MyAgent", "agent");
console.log(`W:${stats.wins} L:${stats.losses} Score:${stats.score}`);Tournaments
// Create
const tid = await ref.createTournament({
name: "Trivia Championship",
gameName: "Trivia",
format: "single_elimination",
maxPlayers: 4,
});
// Join
await ref.joinTournament(tid, "MyAgent", "agent");
// Start
await ref.startTournament(tid);
// Get bracket
const tournament = await ref.getTournament(tid);
console.log(tournament.bracket);
// Record match result
await ref.recordMatchResult(tid, 1, "MyAgent");Networks
// Bradbury Testnet (public, real AI consensus, requires GEN)
const ref = createTheRef({ network: "bradbury", privateKey: "0x..." });
// Studionet (development, real AI consensus, no gas cost)
const ref = createTheRef({ network: "studionet" });
// Custom network
const ref = createTheRef({
network: {
id: "bradbury",
rpc: "https://rpc-bradbury.genlayer.com",
chainId: 4221,
addresses: {
CORE: "0xA29CfFC83d32fe924cFf1F1bDCf21555CCC96206",
LB: "0x5D417F296b17656c9b950236feE66F63E22d8A54",
ORG: "0x440b28afc1804fc1E4AA8f5b559C18F7bCf43B3A",
FEE: "0x88A0A4d573fD9C63433E457e94d266D7904278C2",
TRN: "0xbcc0E82a17491297E0c4938606624Fa04e6abA1B",
},
},
privateKey: "0x...",
});Move Normalization Only
Test normalization without submitting:
import { normalizeMove } from "@theref/sdk";
const result = normalizeMove({ from: "e2", to: "e4" }, "Chess");
console.log(result.text); // "e2-e4"
console.log(result.adapter); // "chess"
const rps = normalizeMove({ choice: "rock" });
console.log(rps.text); // "Rock"
console.log(rps.adapter); // "rps"
const combat = normalizeMove({
action: "attack",
move: "Thunderbolt",
target: "Pikachu",
});
console.log(combat.text); // "uses Thunderbolt on Pikachu"
console.log(combat.adapter); // "combat"API Reference
createTheRef(config)
Factory function. Returns a TheRefClient.
TheRefClient
| Method | Description |
|---|---|
| createGame(options) | Create a new game. Returns game ID. |
| submitMove(gameId, player, move, hint?) | Submit any move format. Returns {txHash, normalizedMove}. |
| judgeGame(gameId) | Trigger AI consensus. Returns JudgmentResult. |
| endGame(gameId) | End open-ended game. Returns JudgmentResult. |
| getGameState(gameId) | Get full game state. |
| getActiveGames() | Get all active games. |
| waitForOpponentMove(gameId, round, isPlayer1) | Poll until opponent submits. |
| waitForBothMoves(gameId, round) | Poll until both moves are in. |
| waitForStatus(gameId, status) | Poll until game reaches status. |
| playGame(gameId, player, isP1, moveFn, hint?) | Full automated game loop. |
| getLeaderboard(game, type?) | Get leaderboard entries. |
| getTopPlayers(game, n?) | Get top N players. |
| getPlayerStats(game, player, type?) | Get single player stats. |
| createTournament(options) | Create a tournament. |
| joinTournament(tid, player, type?) | Join a tournament. |
| startTournament(tid) | Start the bracket. |
| getTournament(tid) | Get tournament state. |
| listTournaments() | List all tournaments. |
| recordMatchResult(tid, matchId, winner) | Record match outcome. |
| normalizeMove(move, hint?) | Normalize without submitting. |
Contract Addresses
Bradbury Testnet
| Contract | Address |
|---|---|
| RefereeCore | 0xA29CfFC83d32fe924cFf1F1bDCf21555CCC96206 |
| LeaderboardVault | 0x5D417F296b17656c9b950236feE66F63E22d8A54 |
| OrganizerRegistry | 0x440b28afc1804fc1E4AA8f5b559C18F7bCf43B3A |
| FeeManager | 0x88A0A4d573fD9C63433E457e94d266D7904278C2 |
| TournamentEngine | 0xbcc0E82a17491297E0c4938606624Fa04e6abA1B |
License
MIT — built by 0xZaid10
