### Install and Build Denshokan SDK Dependencies Source: https://github.com/provable-games/denshokan-sdk/blob/main/CLAUDE.md Standard npm commands for managing dependencies, building the project, running type checks, and executing tests for the Denshokan SDK. ```bash npm install # Install dependencies npm run build # Build ESM + CJS to dist/ npm run typecheck # TypeScript type checking (tsc --noEmit) npm test # Run unit tests (vitest run) npm run test:watch # Run tests in watch mode npm run dev # Build in watch mode npm run clean # Remove dist/ ``` -------------------------------- ### Install @provable-games/denshokan-sdk Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Installs the Denshokan SDK using npm or pnpm. Also lists peer dependencies like 'starknet' for RPC calls and 'react' for React hooks, which should be installed if their respective features are needed. ```bash npm install @provable-games/denshokan-sdk # or pnpm add @provable-games/denshokan-sdk npm install starknet # Required for RPC calls npm install react # Required for React hooks ``` -------------------------------- ### Development Commands for Denshokan SDK Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Provides essential npm commands for managing the Denshokan SDK during development. Includes installation, building, type checking, testing, and watch mode. ```bash npm install npm run build # ESM + CJS to dist/ npm run typecheck # TypeScript validation npm test # Unit tests npm run dev # Watch mode ``` -------------------------------- ### Denshokan SDK Directory Structure Source: https://github.com/provable-games/denshokan-sdk/blob/main/CLAUDE.md Overview of the Denshokan SDK's project structure, highlighting key directories like src/, api/, rpc/, and react/ for different functionalities. ```tree src/ ├── index.ts # Main entry — re-exports everything ├── client.ts # DenshokanClient class (wires all layers together) ├── types/ # All TypeScript interfaces (camelCase fields) │ ├── config.ts # DenshokanClientConfig, DataSource │ ├── token.ts # Token, DecodedTokenId, TokenMetadata │ ├── game.ts # Game, GameStats, LeaderboardEntry, GameDetail │ ├── player.ts # PlayerStats │ ├── minter.ts # Minter │ ├── activity.ts # ActivityEvent │ ├── websocket.ts # WSChannel, WSMessage │ └── rpc.ts # RoyaltyInfo, GameMetadata, MintParams ├── api/ # REST API layer │ ├── base.ts # apiFetch with retry/timeout/abort │ ├── games.ts # Game endpoints │ ├── tokens.ts # Token endpoints │ ├── players.ts # Player endpoints │ ├── minters.ts # Minter endpoints │ └── activity.ts # Activity endpoints ├── rpc/ # Starknet RPC layer │ ├── provider.ts # createProvider, createContract helpers │ ├── denshokan.ts # Denshokan contract (ERC721 + batch metadata) │ ├── registry.ts # MinigameRegistry contract │ ├── game.ts # Game contract (score, details, objectives, settings) │ └── abis/ │ └── denshokan.json # Contract ABI ├── datasource/ │ ├── health.ts # ConnectionStatus — API/RPC health monitoring │ └── resolver.ts # withFallback() smart data source switching ├── ws/ │ └── manager.ts # WebSocketManager — subscriptions + auto-reconnect ├── utils/ │ ├── retry.ts # withRetry, calculateBackoff, sleep │ ├── token-id.ts # decodePackedTokenId (felt252 bit unpacking) │ ├── address.ts # normalizeAddress │ └── mappers.ts # snake_case ↔ camelCase transformers ├── errors/ │ └── index.ts # DenshokanError hierarchy ├── chains/ │ └── constants.ts # Chain configs, default RPC URLs └── react/ ├── index.ts # React entry point (separate build output) ├── context.tsx # DenshokanProvider, useDenshokanClient ├── useGames.ts # useGames hook ├── useTokens.ts # useTokens, useToken hooks ├── useLeaderboard.ts # useLeaderboard hook ├── usePlayer.ts # usePlayerStats, usePlayerTokens hooks ├── useMinters.ts # useMinters hook ├── useActivity.ts # useActivity hook ├── useSubscription.ts # WebSocket subscription hook └── useRpc.ts # useBalanceOf, useOwnerOf, useTokenUri, batch hooks ``` -------------------------------- ### React Provider Setup for Denshokan SDK Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Demonstrates setting up the `DenshokanProvider` component in a React application to provide Denshokan client context to child components. It shows two methods: providing a configuration object for internal client creation or passing an existing client instance. It also illustrates how to access the client within components using the `useDenshokanClient` hook. ```tsx import { DenshokanProvider, createDenshokanClient } from "@provable-games/denshokan-sdk/react"; // Option 1: Provide config (client created internally) function App() { return ( ); } // Option 2: Provide existing client const client = createDenshokanClient({ chain: "mainnet" }); function AppWithClient() { return ( ); } // Access client directly in components import { useDenshokanClient } from "@provable-games/denshokan-sdk/react"; function CustomComponent() { const client = useDenshokanClient(); const handleCustomAction = async () => { const games = await client.getGames(); console.log(games); }; return ; } ``` -------------------------------- ### TypeScript Error Handling Example Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Demonstrates how to handle errors when using the Denshokan SDK, specifically catching `DataSourceError` which indicates a fallback scenario between API and RPC. It also shows how to catch general `ApiError`. ```typescript import { DenshokanError, ApiError, DataSourceError } from "@provable-games/denshokan-sdk"; try { const token = await client.getToken("12345"); } catch (error) { if (error instanceof DataSourceError) { console.log("Primary failed:", error.primaryError.message); console.log("Fallback failed:", error.fallbackError.message); } else if (error instanceof ApiError) { console.log("HTTP status:", error.statusCode); } } ``` -------------------------------- ### Batch vs. Single RPC Method Implementation (TypeScript) Source: https://github.com/provable-games/denshokan-sdk/blob/main/CLAUDE.md Demonstrates the pattern where batch RPC methods serve as the primary implementation, with single-item methods delegating to their batch counterparts by wrapping the input in an array. This optimizes for batch operations while maintaining a convenient interface for single calls. ```typescript // Batch is the real implementation export async function rpcTokenMetadataBatch(contract, tokenIds) { ... } // Single delegates to batch export async function rpcTokenMetadata(contract, tokenId) { const [result] = await rpcTokenMetadataBatch(contract, [tokenId]); return result; } ``` -------------------------------- ### Denshokan RPC Hooks for Balance and Scores (TypeScript) Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Provides examples of using React hooks like useBalanceOf to fetch a player's token balance and useScoreBatch to retrieve scores for multiple tokens via RPC calls. ```typescript import { useBalanceOf, useScoreBatch } from "@provable-games/denshokan-sdk/react"; function PlayerBalance({ address }: { address: string }) { const { data: balance } = useBalanceOf(address); return
Tokens owned: {balance?.toString()}
; } function Scores({ tokenIds, gameAddress }: { tokenIds: string[]; gameAddress: string }) { const { data: scores } = useScoreBatch(tokenIds, gameAddress); return ( ); } ``` -------------------------------- ### Smart Fallback with Health Monitoring (TypeScript) Source: https://github.com/provable-games/denshokan-sdk/blob/main/CLAUDE.md Illustrates a `withFallback` function designed for resilient data fetching. It incorporates health monitoring to intelligently switch between primary and fallback data sources, prioritizing the primary unless it's known to be unhealthy. This pattern enhances reliability by avoiding unnecessary calls to failing endpoints. ```typescript // In rpc-fallback mode, goes straight to RPC without wasting time on API async function withFallback(primary, fallback, health?) { ... } ``` -------------------------------- ### Use Denshokan SDK Connection Status Hook in React Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Provides an example of using the `useConnectionStatus` hook from the Denshokan SDK's React integration to display the connection mode and health status of API and RPC endpoints within a React component. ```typescript import { useConnectionStatus } from "@provable-games/denshokan-sdk/react"; function ConnectionIndicator() { const { mode, api, rpc } = useConnectionStatus(); return (

Mode: {mode}

API: {api.status} (last check: {api.lastCheck?.toISOString()})

RPC: {rpc.status} (last check: {rpc.lastCheck?.toISOString()})

); } ``` -------------------------------- ### React Data Hooks for Denshokan SDK Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Showcases various React data hooks provided by the Denshokan SDK for simplified data fetching, including loading states, error handling, and refetch capabilities. Examples cover fetching lists of games, individual game details, token information, player statistics, and more, demonstrating their usage within functional components. ```tsx import { useGames, useGame, useGameStats, useTokens, useToken, useTokenScores, usePlayerStats, usePlayerTokens, } from "@provable-games/denshokan-sdk/react"; function GameList() { const { data, isLoading, error, refetch } = useGames({ limit: 20, offset: 0 }); if (isLoading) return
Loading games...
; if (error) return
Error: {error.message}
; return (

Total: {data?.total}

{data?.data.map((game) => (

{game.name}

{game.description}

))}
); } function TokenGallery({ owner }: { owner: string }) { const { data, isLoading, isLoadingUri, error } = useTokens({ owner, playable: true, limit: 50, includeUri: true, }); if (isLoading) return
Loading tokens...
; return (
{isLoadingUri && Loading images...} {data?.data.map((token) => (

{token.playerName} - Score: {token.score}

{token.tokenUri && {token.playerName}}
))}
); } function PlayerProfile({ address }: { address: string }) { const { data: stats } = usePlayerStats(address); const { data: tokens } = usePlayerTokens(address, { limit: 10 }); return (

Player Stats

Total Tokens: {stats?.totalTokens}

Games Played: {stats?.gamesPlayed}

Total Score: {stats?.totalScore}

Recent Tokens

{tokens?.data.map((token) => (
{token.playerName}
))}
); } ``` -------------------------------- ### SDK Type Definitions (TypeScript) Source: https://github.com/provable-games/denshokan-sdk/blob/main/CLAUDE.md Defines the structure for `Token` and `Game` objects used within the SDK. It emphasizes the use of camelCase for all field names, adhering to the SDK's naming convention for consumer-facing types. Optional fields are indicated with a '?'. ```typescript interface Token { tokenId: string; // not token_id gameId: number; // not game_id playerName: string; // not player_name isPlayable: boolean; // not is_playable // ... } interface Game { gameId: number; // not id contractAddress: string; // not contract_address imageUrl?: string; // not image_url createdAt: string; // not created_at // ... } ``` -------------------------------- ### Create Denshokan Client and Fetch Data (TypeScript) Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Demonstrates how to create a Denshokan client instance with configuration and then use it to fetch games, a single token (with API-first and RPC fallback), perform batch RPC calls for token metadata, and decode packed token IDs. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet", denshokanAddress: "0x...", registryAddress: "0x...", apiUrl: "https://your-api.example.com", }); // Fetch games from API const games = await client.getGames(); console.log(games[0].gameId, games[0].name); // Fetch a token (API with automatic RPC fallback) const token = await client.getToken("12345"); console.log(token.tokenId, token.playerName, token.isPlayable); // Batch RPC call const metadata = await client.tokenMetadataBatch(["123", "456", "789"]); // Decode a packed token ID const decoded = client.decodeTokenId("98765"); console.log(decoded.gameId, decoded.settingsId, decoded.soulbound); ``` -------------------------------- ### Initialize Denshokan Client (TypeScript) Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Creates a configured Denshokan client instance for interacting with Denshokan contracts and API. Supports mainnet and sepolia chains with automatic defaults and allows for full configuration of endpoints and operational parameters. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; // Basic initialization with defaults const client = createDenshokanClient({ chain: "mainnet", // or "sepolia" }); // Full configuration with custom endpoints const client = createDenshokanClient({ chain: "mainnet", apiUrl: "https://api.denshokan.example.com", wsUrl: "wss://api.denshokan.example.com/ws", rpcUrl: "https://starknet-mainnet.example.com", denshokanAddress: "0x1234...", registryAddress: "0x5678...", viewerAddress: "0x9abc...", primarySource: "api", // "api" or "rpc" fetch: { timeout: 10000, maxRetries: 3, baseBackoff: 1000, maxBackoff: 5000, tokenUriConcurrency: 10, }, ws: { maxReconnectAttempts: 10, reconnectBaseDelay: 1000, }, health: { initialCheckDelay: 1000, checkInterval: 30000, checkTimeout: 5000, }, }); ``` -------------------------------- ### Denshokan React Provider and Data Hooks (TypeScript) Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Shows how to set up the Denshokan SDK within a React application using the DenshokanProvider and demonstrates fetching a list of games using the useGames hook, including loading and error states. ```typescript import { DenshokanProvider, useGames, useToken } from "@provable-games/denshokan-sdk/react"; function App() { return ( ); } function GameList() { const { data: games, isLoading, error } = useGames(); if (isLoading) return
Loading...
; if (error) return
Error: {error.message}
; return ( ); } ``` -------------------------------- ### Real-time WebSocket Subscriptions with Denshokan SDK Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Establishes real-time event subscriptions for game events like score updates, game completions, and new mints using the Denshokan SDK. It demonstrates connecting to the WebSocket, subscribing to multiple channels with optional game ID filtering, handling incoming messages, monitoring connection status, and cleaning up subscriptions. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); // Connect WebSocket client.connect(); // Subscribe to multiple channels const unsubscribe = client.subscribe( { channels: ["scores", "game_over", "mints", "tokens"], gameIds: [1, 2], // Optional: filter by game IDs }, (message) => { switch (message.channel) { case "scores": const score = message.data as { tokenId: string; score: number; playerName: string }; console.log(`Score update: ${score.playerName} scored ${score.score}`); break; case "game_over": const gameOver = message.data as { tokenId: string; score: number; completedAllObjectives: boolean }; console.log(`Game over: Token ${gameOver.tokenId}, final score ${gameOver.score}`); break; case "mints": const mint = message.data as { tokenId: string; gameId: number; ownerAddress: string }; console.log(`New mint: Token ${mint.tokenId} for game ${mint.gameId}`); break; } } ); // Monitor connection status const removeListener = client.onWsConnectionChange((connected) => { console.log(`WebSocket ${connected ? "connected" : "disconnected"}`); }); // Cleanup unsubscribe(); removeListener(); client.disconnect(); ``` -------------------------------- ### React WebSocket Hooks for Real-time Subscriptions Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Offers React hooks for real-time WebSocket subscriptions, managing connections and buffering events automatically. Includes a low-level `useSubscription` hook and higher-level hooks for specific events like score updates, game over notifications, and mint events. ```tsx import { useSubscription, useScoreUpdates, useGameOverEvents, useMintEvents, useTokenUpdates, useNewGames, useConnectionStatus, } from "@provable-games/denshokan-sdk/react"; // Low-level subscription hook function ScoreFeed({ gameIds }: { gameIds: number[] }) { useSubscription( ["scores", "game_over"], (message) => { console.log(`${message.channel}:`, message.data); }, gameIds ); return
Listening for score updates...
; } // High-level channel hooks with event buffering function LiveScoreboard({ gameIds }: { gameIds?: number[] }) { const { lastEvent, events, isConnected, clear } = useScoreUpdates({ gameIds, bufferSize: 100, onEvent: (event) => { console.log(`New score: ${event.playerName} - ${event.score}`); }, }); return (

Status: {isConnected ? "Connected" : "Disconnected"}

Latest Score

{lastEvent && (

{lastEvent.playerName}: {lastEvent.score}

)}

Recent Scores ({events.length})

    {events.map((event, i) => (
  • {event.playerName}: {event.score}
  • ))}
); } function GameOverFeed() { const { events } = useGameOverEvents({ bufferSize: 50 }); return (

Completed Games

{events.map((event, i) => (
Token {event.tokenId}: Final score {event.score} {event.completedAllObjectives && " - All objectives complete!"}
))}
); } function MintTracker() { const { lastEvent, events } = useMintEvents(); return (

Recent Mints

{events.map((event, i) => (
Game {event.gameId}: Token {event.tokenId} minted to {event.ownerAddress}
))}
); } ``` -------------------------------- ### Monitor Denshokan SDK Connection Status in TypeScript Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Shows how to access and monitor the connection status of the Denshokan SDK, including checking the current operational mode (API primary, RPC fallback, or both down) and retrieving detailed health status for API and RPC endpoints. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); // Get connection status instance const status = client.getConnectionStatus(); // Check current mode console.log(`Current mode: ${status.mode}`); // Modes: "api-primary" | "rpc-fallback" | "both-down" // Get detailed state const state = status.getState(); console.log(`API status: ${state.api.status}`); // "healthy" | "unhealthy" | "unknown" console.log(`API last check: ${state.api.lastCheck}`); console.log(`RPC status: ${state.rpc.status}`); console.log(`RPC last check: ${state.rpc.lastCheck}`); ``` -------------------------------- ### Real-time WebSocket Subscriptions in React (TypeScript) Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Illustrates how to use the useSubscription hook from the Denshokan SDK's React module to listen for real-time updates on specific channels like 'scores' and 'game_over', logging received messages. ```typescript import { useSubscription } from "@provable-games/denshokan-sdk/react"; function ScoreFeed({ gameId }: { gameId: number }) { useSubscription( ["scores", "game_over"], (message) => { console.log("Event:", message.channel, message.data); }, [gameId], ); return
Listening for score updates...
; } ``` -------------------------------- ### Query Game Contract Data with Denshokan SDK (TypeScript) Source: https://context7.com/provable-games/denshokan-sdk/llms.txt This snippet demonstrates how to query game-specific contract data, including token details, game objectives, and settings, using the Denshokan SDK. It requires the `@provable-games/denshokan-sdk` package and a configured client. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); const gameAddress = "0x1234abcd..."; const tokenId = "12345"; // Token details from game contract const tokenName = await client.tokenName(tokenId, gameAddress); const tokenDesc = await client.tokenDescription(tokenId, gameAddress); console.log(`${tokenName}: ${tokenDesc}`); // Game details (key-value pairs) const details = await client.gameDetails(tokenId, gameAddress); for (const detail of details) { console.log(`${detail.key}: ${detail.value}`); } // Objectives const objectivesCount = await client.objectivesCount(gameAddress); console.log(`Total objectives: ${objectivesCount}`); const objectiveExists = await client.objectiveExists(1, gameAddress); if (objectiveExists) { const objective = await client.objectivesDetails(1, gameAddress); console.log(`Objective: ${objective.name} - ${objective.description}`); } const completed = await client.completedObjective(tokenId, 1, gameAddress); console.log(`Objective 1 completed: ${completed}`); // Settings const settingsCount = await client.settingsCount(gameAddress); console.log(`Total settings: ${settingsCount}`); const settings = await client.settingsDetails(1, gameAddress); console.log(`Settings: ${settings.name} - ${settings.description}`); ``` -------------------------------- ### Efficient Batch RPC Operations with Denshokan SDK Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Utilizes batch methods for efficient multi-token queries, with single-item methods delegating internally. Supports batch operations for token metadata, mutable state, scores, game over status, token URIs, and player names. Requires the Denshokan SDK and token IDs. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); const tokenIds = ["12345", "67890", "11111"]; const gameAddress = "0x1234abcd..."; // Batch token metadata const metadataList = await client.tokenMetadataBatch(tokenIds); for (const meta of metadataList) { console.log(`Game ${meta.gameId}: ${meta.playerName}`); console.log(` Settings: ${meta.settingsId}, Objective: ${meta.objectiveId}`); console.log(` Playable: ${meta.isPlayable}, Soulbound: ${meta.isSoulbound}`); } // Batch mutable state const states = await client.tokenMutableStateBatch(tokenIds); for (let i = 0; i < tokenIds.length; i++) { console.log(`Token ${tokenIds[i]}: gameOver=${states[i].gameOver}`); } // Batch scores and game over status const scores = await client.scoreBatch(tokenIds, gameAddress); const gameOverStatus = await client.gameOverBatch(tokenIds, gameAddress); for (let i = 0; i < tokenIds.length; i++) { console.log(`Token ${tokenIds[i]}: score=${scores[i]}, finished=${gameOverStatus[i]}`); } // Batch token URIs const uris = await client.tokenUriBatch(tokenIds); for (let i = 0; i < tokenIds.length; i++) { console.log(`Token ${tokenIds[i]} URI: ${uris[i]}`); } // Batch player names const names = await client.playerNameBatch(tokenIds); console.log("Player names:", names); ``` -------------------------------- ### Perform Write Operations with Denshokan SDK (TypeScript) Source: https://context7.com/provable-games/denshokan-sdk/llms.txt This snippet illustrates how to perform write operations using the Denshokan SDK, including minting single tokens, batch minting, updating game states, and updating player names. These operations require a connected account with signing capabilities and the `@provable-games/denshokan-sdk` package. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); // Mint a single token const tokenId = await client.mint({ gameId: 1, settingsId: 0, objectiveId: 0, playerName: "Player1", soulbound: false, to: "0xrecipient...", salt: 12345, // Optional, auto-generated if omitted metadata: 0, // Optional }); console.log(`Minted token: ${tokenId}`); // Batch mint (salts auto-assigned) const tokenIds = await client.mintBatch([ { gameId: 1, settingsId: 0, objectiveId: 0, playerName: "P1", soulbound: false, to: "0xabc..." }, { gameId: 1, settingsId: 0, objectiveId: 0, playerName: "P2", soulbound: false, to: "0xdef..." }, { gameId: 1, settingsId: 1, objectiveId: 0, playerName: "P3", soulbound: true, to: "0x123..." }, ]); console.log(`Minted tokens: ${tokenIds.join(", ")}`); // Update game state (sync token with on-chain game state) await client.updateGame("12345"); await client.updateGameBatch(["12345", "67890", "11111"]); // Update player name await client.updatePlayerName("12345", "NewPlayerName"); await client.updatePlayerNameBatch([ { tokenId: "12345", name: "Player1" }, { tokenId: "67890", name: "Player2" }, ]); ``` -------------------------------- ### Batch RPC Operations Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Utilize batch methods for efficient multi-token queries, including metadata, mutable state, scores, game over status, URIs, and player names. ```APIDOC ## Batch RPC Operations ### Description Efficiently query multiple tokens using batch methods for metadata, state, scores, and more. ### Methods - `tokenMetadataBatch(tokenIds: string[])`: Retrieves metadata for a batch of token IDs. - `tokenMutableStateBatch(tokenIds: string[])`: Retrieves mutable state for a batch of token IDs. - `scoreBatch(tokenIds: string[], gameAddress: string)`: Retrieves scores for a batch of token IDs in a specific game. - `gameOverBatch(tokenIds: string[], gameAddress: string)`: Retrieves game over status for a batch of token IDs in a specific game. - `tokenUriBatch(tokenIds: string[])`: Retrieves URIs for a batch of token IDs. - `playerNameBatch(tokenIds: string[])`: Retrieves player names for a batch of token IDs. ### Request Example (tokenMetadataBatch) ```typescript const tokenIds = ["12345", "67890"]; const metadataList = await client.tokenMetadataBatch(tokenIds); console.log(metadataList); ``` ### Request Example (scoreBatch) ```typescript const tokenIds = ["12345", "67890"]; const gameAddress = "0x1234abcd..."; const scores = await client.scoreBatch(tokenIds, gameAddress); console.log(scores); ``` ### Response Example (tokenMetadataBatch) ```json [ { "gameId": 1, "playerName": "Player1", "settingsId": 10, "objectiveId": 20, "isPlayable": true, "isSoulbound": false } ] ``` ### Response Example (scoreBatch) ```json [100, 200] ``` ``` -------------------------------- ### Fetch Token Data (TypeScript) Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Retrieves token data using the Denshokan SDK. Supports fetching multiple tokens with extensive filtering options via `getTokens` and a single token with automatic API/RPC fallback via `getToken`. Also includes functionality to retrieve token score history. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); // Get tokens with filters const tokensResult = await client.getTokens({ gameId: 1, owner: "0xabc123...", playable: true, soulbound: false, limit: 50, offset: 0, includeUri: true, // Fetch token URIs via batch RPC }); for (const token of tokensResult.data) { console.log(`Token ${token.tokenId}`); console.log(` Owner: ${token.owner}`); console.log(` Player: ${token.playerName}`); console.log(` Score: ${token.score}`); console.log(` Game Over: ${token.gameOver}`); console.log(` Playable: ${token.isPlayable}`); console.log(` URI: ${token.tokenUri}`); } // Get single token (with automatic fallback) const token = await client.getToken("12345"); console.log(`Token ${token.tokenId} owned by ${token.owner}`); // Get token score history const scores = await client.getTokenScores("12345", 10); for (const entry of scores) { console.log(`Score: ${entry.score} at ${entry.timestamp}`); } ``` -------------------------------- ### Handle Denshokan SDK Errors in TypeScript Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Demonstrates how to handle various specific errors thrown by the Denshokan SDK, including network issues, data source failures, and token/game not found errors. It uses instanceof checks to differentiate between error types. ```typescript import { createDenshokanClient, DenshokanError, ApiError, RpcError, RateLimitError, TimeoutError, AbortError, TokenNotFoundError, GameNotFoundError, InvalidChainError, DataSourceError, } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); try { const token = await client.getToken("12345"); } catch (error) { if (error instanceof TokenNotFoundError) { console.log(`Token ${error.tokenId} does not exist`); } else if (error instanceof GameNotFoundError) { console.log(`Game ${error.gameId} not found`); } else if (error instanceof DataSourceError) { console.log("Both API and RPC failed:"); console.log(` API error: ${error.primaryError.message}`); console.log(` RPC error: ${error.fallbackError.message}`); } else if (error instanceof ApiError) { console.log(`API error ${error.statusCode}: ${error.message}`); } else if (error instanceof RpcError) { console.log(`RPC error for ${error.contractAddress}: ${error.message}`); } else if (error instanceof RateLimitError) { console.log(`Rate limited. Retry after: ${error.retryAfter}ms`); } else if (error instanceof TimeoutError) { console.log("Request timed out"); } else if (error instanceof AbortError) { console.log("Request was aborted"); } else if (error instanceof InvalidChainError) { console.log(`Invalid chain: ${error.chain}`); } else if (error instanceof DenshokanError) { console.log(`Denshokan error: ${error.message}`); } else { throw error; } } ``` -------------------------------- ### Fetch Games Data (TypeScript) Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Retrieves game data using the Denshokan SDK. Supports fetching all games with pagination via `getGames` and a single game by address with automatic RPC fallback via `getGame`. Also provides a method to fetch game statistics. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); // Get all games with pagination const gamesResult = await client.getGames({ limit: 20, offset: 0 }); console.log(`Total games: ${gamesResult.total}`); for (const game of gamesResult.data) { console.log(`Game ${game.gameId}: ${game.name}`); console.log(` Contract: ${game.contractAddress}`); console.log(` Developer: ${game.developer}`); console.log(` Created: ${game.createdAt}`); } // Get single game (with automatic RPC fallback) const game = await client.getGame("0x1234abcd..."); console.log(`${game.name}: ${game.description}`); // Get game statistics const stats = await client.getGameStats("0x1234abcd..."); console.log(`Total tokens: ${stats.totalTokens}`); console.log(`Active games: ${stats.activeGames}`); console.log(`Unique players: ${stats.uniquePlayers}`); ``` -------------------------------- ### Retrieve Player Data with Denshokan SDK Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Fetches player-specific data, including owned tokens and aggregated statistics, using the `getPlayerTokens` and `getPlayerStats` methods. Requires the Denshokan SDK and player address as input. Outputs player stats and token details. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); const playerAddress = "0xabc123..."; // Get player statistics const stats = await client.getPlayerStats(playerAddress); console.log(`Player: ${stats.address}`); console.log(`Total tokens: ${stats.totalTokens}`); console.log(`Games played: ${stats.gamesPlayed}`); console.log(`Completed: ${stats.completedGames}`); console.log(`Active: ${stats.activeGames}`); console.log(`Total score: ${stats.totalScore}`); // Get player's tokens with filtering const tokens = await client.getPlayerTokens(playerAddress, { gameId: 1, limit: 20, offset: 0, includeUri: true, }); console.log(`Found ${tokens.total} tokens`); for (const token of tokens.data) { console.log(`${token.tokenId}: ${token.playerName} - Score: ${token.score}`); } ``` -------------------------------- ### DenshokanClientConfig Interface Definition (TypeScript) Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Defines the TypeScript interface for configuring the Denshokan client. It includes options for chain, API/WebSocket/RPC URLs, Starknet provider, contract addresses, primary data source, and fetch/WebSocket retry configurations. ```typescript interface DenshokanClientConfig { chain?: "mainnet" | "sepolia"; // Default: "mainnet" apiUrl?: string; // REST API base URL wsUrl?: string; // WebSocket URL rpcUrl?: string; // Custom Starknet RPC endpoint provider?: RpcProvider; // starknet.js provider (takes precedence over rpcUrl) denshokanAddress: string; // Denshokan contract address (required) registryAddress: string; // MinigameRegistry contract address (required) primarySource?: "api" | "rpc"; // Default: "api" fetch?: { timeout?: number; // Default: 10000ms maxRetries?: number; // Default: 3 baseBackoff?: number; // Default: 1000ms maxBackoff?: number; // Default: 5000ms }; ws?: { maxReconnectAttempts?: number; // Default: 10 reconnectBaseDelay?: number; // Default: 1000ms }; } ``` -------------------------------- ### Direct RPC Calls for ERC721 with Denshokan SDK Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Performs direct RPC calls to the Denshokan contract for standard ERC721 operations, bypassing the API. Supports methods like `balanceOf`, `ownerOf`, `tokenUri`, `name`, `symbol`, `royaltyInfo`, `totalSupply`, `tokenByIndex`, and `tokenOfOwnerByIndex`. Requires the Denshokan SDK. ```typescript import { createDenshokanClient } from "@provable-games/denshokan-sdk"; const client = createDenshokanClient({ chain: "mainnet" }); // ERC721 standard methods const balance = await client.balanceOf("0xabc123..."); console.log(`Balance: ${balance}`); const owner = await client.ownerOf("12345"); console.log(`Owner: ${owner}`); const uri = await client.tokenUri("12345"); console.log(`Token URI: ${uri}`); const name = await client.name(); const symbol = await client.symbol(); console.log(`Collection: ${name} (${symbol})`); // Royalty info (ERC2981) const royalty = await client.royaltyInfo("12345", 1000000n); console.log(`Royalty receiver: ${royalty.receiver}`); console.log(`Royalty amount: ${royalty.amount}`); // ERC721Enumerable const totalSupply = await client.totalSupply(); console.log(`Total supply: ${totalSupply}`); const tokenAtIndex = await client.tokenByIndex(0n); console.log(`First token: ${tokenAtIndex}`); const ownerTokenAtIndex = await client.tokenOfOwnerByIndex("0xabc...", 0n); console.log(`Owner's first token: ${ownerTokenAtIndex}`); ``` -------------------------------- ### TypeScript Interface Definitions for Token and Game Source: https://github.com/provable-games/denshokan-sdk/blob/main/README.md Defines the structure for 'Token' and 'Game' objects used within the SDK. These interfaces specify the expected properties and their types, ensuring data consistency. ```typescript interface Token { tokenId: string; gameId: number; owner: string; score: number; gameOver: boolean; playerName: string; mintedBy: string; mintedAt: string; settingsId: number; objectiveId: number; soulbound: boolean; isPlayable: boolean; gameAddress: string; } interface Game { gameId: number; name: string; description: string; contractAddress: string; imageUrl?: string; createdAt: string; } ``` -------------------------------- ### React RPC Hooks for Blockchain Data Querying Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Provides React hooks to query blockchain data such as token ownership, URIs, metadata, scores, and game status. These hooks manage state automatically, including loading and error states. They are designed to work with the Denshokan SDK. ```tsx import { useBalanceOf, useOwnerOf, useTokenUri, useTokenUriBatch, useTokenMetadataBatch, useScoreBatch, useGameOverBatch, useObjectivesCount, useSettingsCount, } from "@provable-games/denshokan-sdk/react"; function TokenOwnership({ tokenId }: { tokenId: string }) { const { data: owner, isLoading, error } = useOwnerOf(tokenId); const { data: uri } = useTokenUri(tokenId); if (isLoading) return
Loading...
; if (error) return
Error: {error.message}
; return (

Owner: {owner}

{uri && Token}
); } function PlayerBalance({ address }: { address: string }) { const { data: balance, isLoading, refetch } = useBalanceOf(address); return (

Balance: {isLoading ? "Loading..." : balance?.toString()}

); } function BatchScores({ tokenIds, gameAddress }: { tokenIds: string[]; gameAddress: string }) { const { data: scores } = useScoreBatch(tokenIds, gameAddress); const { data: gameOverStatus } = useGameOverBatch(tokenIds, gameAddress); return ( ); } function GameConfig({ gameAddress }: { gameAddress: string }) { const { data: objectivesCount } = useObjectivesCount(gameAddress); const { data: settingsCount } = useSettingsCount(gameAddress); return (

Objectives: {objectivesCount ?? "Loading..."}

Settings: {settingsCount ?? "Loading..."}

); } ``` -------------------------------- ### Player Data API Source: https://context7.com/provable-games/denshokan-sdk/llms.txt Retrieve player-specific data, including owned tokens and aggregated statistics, using `getPlayerTokens` and `getPlayerStats` methods. ```APIDOC ## Player Data API ### Description Retrieves player-specific data, including owned tokens and aggregated statistics. ### Methods - `getPlayerStats(playerAddress: string)`: Fetches aggregated statistics for a given player address. - `getPlayerTokens(playerAddress: string, options?: { gameId?: number, limit?: number, offset?: number, includeUri?: boolean })`: Fetches a list of tokens owned by a player, with optional filtering and URI inclusion. ### Request Example (getPlayerStats) ```typescript const stats = await client.getPlayerStats("0xabc123..."); console.log(stats); ``` ### Request Example (getPlayerTokens) ```typescript const tokens = await client.getPlayerTokens("0xabc123...", { gameId: 1, limit: 20, offset: 0, includeUri: true }); console.log(tokens); ``` ### Response Example (getPlayerStats) ```json { "address": "0xabc123...", "totalTokens": 10, "gamesPlayed": 5, "completedGames": 3, "activeGames": 2, "totalScore": 1500 } ``` ### Response Example (getPlayerTokens) ```json { "total": 5, "data": [ { "tokenId": "1", "playerName": "Player1", "score": 100, "uri": "ipfs://..." } ] } ``` ```