═══════════════════════════════════════════════════════════════════════════════ ARCADIA GAME SDK - DEVELOPER DOCUMENTATION ═══════════════════════════════════════════════════════════════════════════════ Document: Wallet Integration Generated: 2/13/2026, 7:45:04 PM Version: 1.0.0 ═══════════════════════════════════════════════════════════════════════════════ Wallet Integration Guide ══════════════════════════════════════════════════════════════════════ This guide covers everything you need to know about integrating wallet functionality into your game using the Arcadia Game SDK. Overview ════════════════════════════════════════════════════════════ The Arcadia Game SDK provides seamless access to the player's connected Solana wallet. The wallet address serves as a universal user identifier, allowing you to: • Link save data to specific players • Track player progress across sessions • Identify returning players • Enable wallet-based features Why Use Wallet Address as User ID? ════════════════════════════════════════════════════════════ Using the wallet address as your primary user identifier offers several advantages: 1. Universal Identity - Works across all games and platforms 2. No Authentication Required - Players don't need to create accounts 3. Persistent - Wallet addresses don't change 4. Secure - Cryptographically secure identifiers 5. Web3 Native - Aligns with blockchain gaming standards Getting the Wallet Address ════════════════════════════════════════════════════════════ Basic Usage ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { ArcadiaSDK } from '@arcadiasol/sdk'; const arcadia = new ArcadiaSDK({ gameId: 'your-game-id', }); await arcadia.init(); // Get wallet address const walletAddress = await arcadia.getWalletAddress(); if (!walletAddress) { // Wallet not connected showMessage('Please connect your wallet in Arcadia to play'); return; } // Use wallet address as user ID console.log('Player wallet:', walletAddress); ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Handling No Wallet ══════════════════════════════════════════════════ Always check if the wallet address is [null] before using it: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ const walletAddress = await arcadia.getWalletAddress(); if (!walletAddress) { // Handle no wallet scenario showWalletConnectionPrompt(); return; } // Proceed with wallet address loadPlayerData(walletAddress); ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Checking Wallet Connection Status ════════════════════════════════════════════════════════════ Simple Check ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ const isConnected = await arcadia.isWalletConnected(); if (!isConnected) { showMessage('Please connect your wallet'); return; } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Combined Check ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ const walletAddress = await arcadia.getWalletAddress(); const isConnected = walletAddress !== null; if (!isConnected) { // Show connection prompt return; } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Listening for Wallet Changes ════════════════════════════════════════════════════════════ The SDK allows you to listen for wallet connection/disconnection events in real-time. Basic Listener ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ arcadia.onWalletChange((connected, address) => { if (connected && address) { console.log('Wallet connected:', address); // Resume game or load player data loadPlayerData(address); } else { console.log('Wallet disconnected'); // Pause game or show connection prompt pauseGame(); showWalletConnectionPrompt(); } }); ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Game State Management ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ let currentWalletAddress: string | null = null; arcadia.onWalletChange((connected, address) => { if (connected && address) { // Wallet connected or changed if (currentWalletAddress && currentWalletAddress !== address) { // Different wallet connected - save current game and load new player saveGameData(currentWalletAddress); currentWalletAddress = address; loadPlayerData(address); } else { // Same wallet or first connection currentWalletAddress = address; if (!isGameLoaded()) { loadPlayerData(address); } } } else { // Wallet disconnected if (currentWalletAddress) { // Save current game state saveGameData(currentWalletAddress); currentWalletAddress = null; } pauseGame(); showMessage('Wallet disconnected. Please reconnect to continue.'); } }); ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Removing Listeners ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ const handleWalletChange = (connected: boolean, address: string | null) => { // Your handler logic }; // Add listener arcadia.onWalletChange(handleWalletChange); // Later, remove listener arcadia.offWalletChange(handleWalletChange); ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Account Linking Patterns ════════════════════════════════════════════════════════════ Pattern 1: Simple Save Data Linking ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // Save game data async function saveGameData(walletAddress: string, gameData: any) { // Store in your database using wallet address as key await fetch('/api/save-game', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ walletAddress, gameData, }), }); } // Load game data async function loadGameData(walletAddress: string) { const response = await fetch([/api/load-game?wallet=${walletAddress}]); const data = await response.json(); return data.gameData; } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Pattern 2: First-Time Player Detection ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ async function initializePlayer(walletAddress: string) { // Check if player exists const existingData = await loadGameData(walletAddress); if (existingData) { // Returning player - load their data return existingData; } else { // First-time player - create new save const newPlayerData = { walletAddress, level: 1, score: 0, inventory: [], createdAt: new Date().toISOString(), }; await saveGameData(walletAddress, newPlayerData); return newPlayerData; } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Pattern 3: Multi-Game Account Linking ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // Use wallet address to link accounts across multiple games async function getPlayerProfile(walletAddress: string) { const response = await fetch([/api/player-profile?wallet=${walletAddress}]); return response.json(); } // Profile might include: // - Games played // - Total achievements // - Cross-game statistics // - Friends list ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Complete Example ════════════════════════════════════════════════════════════ Here's a complete example showing wallet integration: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { ArcadiaSDK, WalletNotConnectedError } from '@arcadiasol/sdk'; class GameManager { private arcadia: ArcadiaSDK; private walletAddress: string | null = null; private playerData: any = null; constructor(gameId: string) { this.arcadia = new ArcadiaSDK({ gameId }); } async initialize() { try { // Initialize SDK await this.arcadia.init(); // Get wallet address this.walletAddress = await this.arcadia.getWalletAddress(); if (!this.walletAddress) { throw new WalletNotConnectedError(); } // Load or create player data this.playerData = await this.loadOrCreatePlayerData(this.walletAddress); // Set up wallet change listener this.arcadia.onWalletChange((connected, address) => { this.handleWalletChange(connected, address); }); // Start game this.startGame(); } catch (error) { if (error instanceof WalletNotConnectedError) { this.showWalletConnectionPrompt(); } else { console.error('Initialization error:', error); this.showError('Failed to initialize game'); } } } private async loadOrCreatePlayerData(walletAddress: string) { // Try to load existing data const existing = await this.loadPlayerData(walletAddress); if (existing) { return existing; } // Create new player data const newData = { walletAddress, level: 1, score: 0, inventory: [], lastPlayed: new Date().toISOString(), }; await this.savePlayerData(walletAddress, newData); return newData; } private async loadPlayerData(walletAddress: string) { // Implement your data loading logic const response = await fetch([/api/player-data?wallet=${walletAddress}]); if (response.ok) { return response.json(); } return null; } private async savePlayerData(walletAddress: string, data: any) { // Implement your data saving logic await fetch('/api/player-data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ walletAddress, data }), }); } private handleWalletChange(connected: boolean, address: string | null) { if (connected && address) { if (this.walletAddress && this.walletAddress !== address) { // Different wallet - save current and load new this.savePlayerData(this.walletAddress, this.playerData); this.walletAddress = address; this.loadOrCreatePlayerData(address).then(data => { this.playerData = data; }); } else { // Same wallet or first connection this.walletAddress = address; } } else { // Wallet disconnected if (this.walletAddress) { this.savePlayerData(this.walletAddress, this.playerData); this.pauseGame(); this.showMessage('Wallet disconnected. Please reconnect.'); } } } private startGame() { // Start your game with loaded player data console.log('Game started for player:', this.walletAddress); } private pauseGame() { // Pause game logic console.log('Game paused'); } private showWalletConnectionPrompt() { // Show UI prompt for wallet connection console.log('Please connect your wallet'); } private showMessage(message: string) { // Show message to user console.log(message); } private showError(message: string) { // Show error to user console.error(message); } } // Usage const gameManager = new GameManager('your-game-id'); gameManager.initialize(); ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Best Practices ════════════════════════════════════════════════════════════ 1. Always Check for Null - Wallet address can be [null] if not connected 2. Handle Disconnections - Save game state when wallet disconnects 3. Listen for Changes - Use [onWalletChange] to react to connection changes 4. Save Frequently - Save player data regularly, not just on disconnect 5. Validate Wallet Address - Ensure wallet address is valid before using it 6. Handle Wallet Switching - Players may switch wallets during gameplay Common Patterns ════════════════════════════════════════════════════════════ Auto-Save on Wallet Disconnect ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ arcadia.onWalletChange((connected, address) => { if (!connected && this.walletAddress) { // Auto-save when wallet disconnects this.autoSave(); } }); ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Prevent Gameplay Without Wallet ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ function canPlay(): boolean { return this.walletAddress !== null; } function attemptAction() { if (!canPlay()) { showMessage('Please connect your wallet to play'); return; } // Proceed with action } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Next Steps ════════════════════════════════════════════════════════════ • Learn about Payments to enable in-game purchases • Check Examples for more wallet integration patterns • Review API Reference for complete method documentation ═══════════════════════════════════════════════════════════════════════════════ For the latest documentation, visit: https://arcadia.obeliskprotocol.io/developer For support, email: support@arcadia.com ═══════════════════════════════════════════════════════════════════════════════