Quick Start
Create your first chess game in 5 minutes
1. Setup
import { ChessGameSDK } from "@sendarcade/checkmate";
import { createSolanaRpc } from "@solana/kit";
// Standard Solana RPC
const rpc = createSolanaRpc("https://api.devnet.solana.com");
// Ephemeral Rollup RPC (for game state)
const erRpc = createSolanaRpc("https://devnet.magicblock.app");
const chessMateSDK = new ChessGameSDK();
// Your wallet signer
const signer = /* your wallet signer */;2. Initialize an Integrator
To integrate the ChessMate SDK into your platform, you must first initialize the integrator configuration as an administrator.
const params = {
integrator: signer, // Admin
// A unique identifier for your platform.
// This must be a valid Solana public key,
// but it does not need to be the address of an existing Solana account.
integratorId: address("YourIntegratorId"),
// The fee percentage charged to players, expressed in basis points.
// For example, a value of 500 equals a 5% fee.
feeBasisPoints: 500,
// The Solana wallet address that will receive all collected fees.
feeVault: address("YourFeeVaultAddress"), // Address
};
const { instruction, integratorConfigPDA } =
await chessMateSDK.initializeIntegratorIx(params);
// Send transaction
const signature = await sendTransaction(rpc, [instruction], signer);
console.log(`Integrator config created at: ${integratorConfigPDA}`);Note: Only run this ONCE per integrator setup.
3. Create a Game
const createParams = {
rpc,
creator: signer,
integratorId: address("YourIntegratorId"),
tokenMint: address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), // USDC
entryFee: BigInt(1_000_000), // 1 USDC
timeControl: {
initialTime: 600, // 10 minutes
increment: 5, // 5 seconds per move
moveTimeLimit: null,
},
ratedGame: true,
allowDrawOffers: true,
};
const { instruction, gameId, gameAccountAddress } =
await chessMateSDK.createGameIx(createParams);
// Send transaction
const signature = await sendTransaction(rpc, [instruction], signer);
console.log(`Game created with ID: ${gameId}`);4. Cancel a Game
If no other player joins the game, the creator can cancel it and reclaim the full wager, with no fee charged.
const cancelGameParams = {
creator: this.signer,
gameId: BigInt(1),
integratorId: address("YourIntegratorId"),
tokenMint: address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), // USDC
};
const { instruction, gameAccountAddress } = await chessMateSDK.cancelGameIx(
cancelGameParams
);
// Send transaction
const signature = await sendTransaction(rpc, [instruction], signer);
console.log(`Game canceled with address: ${gameAccountAddress}`);5. Join a Game
const joinParams = {
player: signer,
gameId: BigInt(1),
integratorId: address("YourIntegratorId"),
tokenMint: address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), // USDC
};
const { instruction } = await chessMateSDK.joinGameIx(joinParams);
const signature = await sendTransaction(rpc, [instruction], signer);
console.log("Joined game as black player");6. Make a Move
Once the second player joins, the game will begin. The game's status updates to InProgress and the GameAccount is delegated to the Ephemeral Rollup environment. All subsequent interactions with the game account, such as making a move or canceling the game, must be performed via the Ephemeral Rollup RPC.
const moveParams = {
player: signer,
gameId: BigInt(1),
integratorId: address("YourIntegratorId"),
fromSquare: "e2", // or square index: 12
toSquare: "e4", // or square index: 28
promotionPiece: undefined, // Only for pawn promotion
};
const { instruction } = await chessMateSDK.makeMoveIx(moveParams);
const signature = await sendTransaction(erRpc, [instruction], signer);
console.log("Move made: e2 to e4");7. Offer Draw
const offerDrawParams = {
player: signer, // TransactionSigner
gameId: BigInt(1), // bigint
integratorId: address("YourIntegratorId"), // Address
};
const { instruction } = await chessMateSDK.offerDrawIx(offerDrawParams);
const signature = await sendTransaction(erRpc, [instruction], signer);
console.log("Sent offer draw");8. Accept Draw
const acceptDrawParams = {
player: signer, // TransactionSigner
gameId: BigInt(1), // bigint
integratorId: address("YourIntegratorId"), // Address
};
const { instruction } = await chessMateSDK.acceptDrawIx(acceptDrawParams);
const signature = await sendTransaction(erRpc, [instruction], signer);
console.log("Offer accepted");9. Reject Draw
const rejectDrawParams = {
player: signer, // TransactionSigner
gameId: BigInt(1), // bigint
integratorId: address("YourIntegratorId"), // Address
};
const { instruction } = await chessMateSDK.rejectDrawIx(rejectDrawParams);
const signature = await sendTransaction(erRpc, [instruction], signer);
console.log("Offer rejected");10. Claim Winnings
When the game ends, the winner can claim the prize pool:
const claimWinningParams = {
rpc,
player: signer,
gameId: BigInt(1),
integratorId: address("YourIntegratorId"),
tokenMint: address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),
};
const { instruction } = await chessMateSDK.claimWinningsIx(claimWinningParams);
const signature = await sendTransaction(rpc, [instruction], signer);
console.log("Winnings claimed!");11. Get Game State & Display
Fetch state to show the board:
import { getGameAccountPDA, fetchGameAccount } from "@sendarcade/checkmate";
// Get the game account PDA
const [gameAccountPDA] = await getGameAccountPDA(
address("YourIntegratorId"),
BigInt(1) // Game ID
);
// Fetch the game account data
// Use the appropriate RPC based on game status (see Magicblock Note section)
const gameAccount = await fetchGameAccount(rpc, gameAccountPDA);
// Access the game data
const gameData = gameAccount.data;
console.log("Game status:", gameData.gameStatus);
console.log("Current turn:", gameData.currentTurn);
console.log("Board state:", gameData.board);Combine this with your frontend chess engine to render the current position.
12. Use Utilities
Use built-in ChessUtils:
import { ChessUtils } from "@sendarcade/checkmate";
const utils = new ChessUtils();
// Convert between square notation and indices
const index = utils.squareToIndex("e4"); // 28
const notation = utils.indexToSquare(28); // "e4"
// Get piece information
const piece = utils.getPieceAt(gameData.board, index);
console.log(`Piece at e4: ${piece?.type} (${piece?.color})`);
// Display board in console
utils.displayBoard(gameData.board, "Current Position");
// Validate Legal Moves
const legalMoves = utils.getLegalMoves(gameData.board, gameData.currentTurn);
// Get legal moves for a specific piece (e2 square)
const e2Index = utils.squareToIndex("e2");
const legalMovesFromE2 = legalMoves.filter((move) => move.from === e2Index);
console.log(
"Legal moves from e2:",
legalMovesFromE2.map((m) => utils.indexToSquare(m.to))
);13. Handle Errors
Wrap calls in try/catch and use the improved error handling in @solana/kit:
import { ChessGameError, GameNotFoundError } from "@sendarcade/checkmate";
try {
const { instruction } = await chessSDK.makeMoveIx({
player: signer,
gameId: BigInt(1),
integratorId: address("YourIntegratorId"),
fromSquare: "e2",
toSquare: "e5", // Invalid move
});
// Build and send transaction...
} catch (error) {
if (error instanceof GameNotFoundError) {
console.error("Game not found:", error.message);
} else if (error instanceof ChessGameError) {
console.error("Chess game error:", error.message);
} else {
console.error("Unknown error:", error);
}
}Next Steps
- Basic Concepts - Understand core concepts
- SDK API Reference - Complete API documentation
- Game Mechanics - Learn chess rules implementation
- Integration Guide - Build a complete chess app