@provable-games/budokan-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +214 -0
  2. package/package.json +78 -0
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # @provable-games/budokan-sdk
2
+
3
+ TypeScript SDK for [Budokan](https://github.com/Provable-Games/budokan) — query and manage tournaments via REST API and Starknet RPC with automatic fallback.
4
+
5
+ ## Features
6
+
7
+ - **Dual data source** — API-first with automatic RPC fallback when the indexer is unavailable
8
+ - **Health monitoring** — Background `ConnectionStatus` service tracks API/RPC availability and auto-switches modes
9
+ - **React hooks** — Provider, data hooks, and WebSocket subscriptions out of the box
10
+ - **WebSocket subscriptions** — Real-time tournament updates with auto-reconnect
11
+ - **ESM + CJS** — Dual build with full TypeScript declarations
12
+ - **camelCase types** — All public types use camelCase field names
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install @provable-games/budokan-sdk
18
+ # or
19
+ pnpm add @provable-games/budokan-sdk
20
+ ```
21
+
22
+ **Peer dependencies** (install if you need their features):
23
+
24
+ ```bash
25
+ npm install starknet # Required for RPC calls
26
+ npm install react # Required for React hooks
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ ### Basic Client
32
+
33
+ ```ts
34
+ import { createBudokanClient } from "@provable-games/budokan-sdk";
35
+
36
+ const client = createBudokanClient({
37
+ chain: "mainnet",
38
+ });
39
+
40
+ // Fetch tournaments from API
41
+ const { data: tournaments } = await client.getTournaments();
42
+ console.log(tournaments[0].id, tournaments[0].name);
43
+
44
+ // Fetch a single tournament (API with automatic RPC fallback)
45
+ const tournament = await client.getTournament("42");
46
+ console.log(tournament.name, tournament.entryCount);
47
+
48
+ // Fetch leaderboard
49
+ const leaderboard = await client.getTournamentLeaderboard("42");
50
+ ```
51
+
52
+ ### React
53
+
54
+ ```tsx
55
+ import { BudokanProvider, useTournaments, useTournament } from "@provable-games/budokan-sdk/react";
56
+
57
+ function App() {
58
+ return (
59
+ <BudokanProvider
60
+ config={{
61
+ chain: "mainnet",
62
+ }}
63
+ >
64
+ <TournamentList />
65
+ </BudokanProvider>
66
+ );
67
+ }
68
+
69
+ function TournamentList() {
70
+ const { data, isLoading, error } = useTournaments();
71
+
72
+ if (isLoading) return <div>Loading...</div>;
73
+ if (error) return <div>Error: {error.message}</div>;
74
+
75
+ return (
76
+ <ul>
77
+ {data?.data.map((t) => (
78
+ <li key={t.id}>{t.name}</li>
79
+ ))}
80
+ </ul>
81
+ );
82
+ }
83
+ ```
84
+
85
+ ### WebSocket Subscriptions
86
+
87
+ ```tsx
88
+ import { useSubscription } from "@provable-games/budokan-sdk/react";
89
+
90
+ function TournamentFeed({ tournamentId }: { tournamentId: string }) {
91
+ useSubscription(
92
+ ["registration", "submission"],
93
+ (message) => {
94
+ console.log("Event:", message.channel, message.data);
95
+ },
96
+ [tournamentId],
97
+ );
98
+
99
+ return <div>Listening for tournament updates...</div>;
100
+ }
101
+ ```
102
+
103
+ ## Configuration
104
+
105
+ ```ts
106
+ interface BudokanClientConfig {
107
+ chain?: "mainnet" | "sepolia"; // Default: "mainnet"
108
+ apiBaseUrl?: string; // REST API base URL
109
+ wsUrl?: string; // WebSocket URL
110
+ rpcUrl?: string; // Custom Starknet RPC endpoint
111
+ provider?: RpcProvider; // starknet.js provider (takes precedence over rpcUrl)
112
+ viewerAddress?: string; // BudokanViewer contract address
113
+ budokanAddress?: string; // Budokan contract address
114
+ primarySource?: "api" | "rpc"; // Default: "api"
115
+ retryAttempts?: number; // Default: 3
116
+ retryDelay?: number; // Default: 1000ms
117
+ timeout?: number; // Default: 10000ms
118
+ }
119
+ ```
120
+
121
+ ## Data Source Fallback
122
+
123
+ The SDK monitors API and RPC health in the background. When the API goes down, methods with RPC fallback automatically switch to direct contract calls. When the API recovers, it switches back.
124
+
125
+ | Method | API | RPC | Fallback |
126
+ |--------|-----|-----|----------|
127
+ | `getTournaments(params?)` | Yes | Yes | Yes |
128
+ | `getTournament(id)` | Yes | Yes | Yes |
129
+ | `getTournamentLeaderboard(id)` | Yes | Yes | Yes |
130
+ | `getTournamentRegistrations(id)` | Yes | Yes | Yes |
131
+ | `getTournamentPrizes(id)` | Yes | Yes | Yes |
132
+ | `getGameTournaments(addr)` | Yes | Yes | Yes |
133
+ | `getTournamentRewardClaims(id)` | Yes | — | API only |
134
+ | `getTournamentRewardClaimsSummary(id)` | Yes | — | API only |
135
+ | `getTournamentQualifications(id)` | Yes | — | API only |
136
+ | `getTournamentPrizeAggregation(id)` | Yes | — | API only |
137
+ | `getPlayerTournaments(addr)` | Yes | — | API only |
138
+ | `getPlayerStats(addr)` | Yes | — | API only |
139
+ | `getGameStats(addr)` | Yes | — | API only |
140
+ | `getActivity(params?)` | Yes | — | API only |
141
+ | `getActivityStats()` | Yes | — | API only |
142
+ | `getPrizeStats()` | Yes | — | API only |
143
+
144
+ ## API Reference
145
+
146
+ ### Client Methods
147
+
148
+ **Tournaments** — `getTournaments(params?)`, `getTournament(id)`, `getTournamentLeaderboard(id)`, `getTournamentRegistrations(id, params?)`, `getTournamentPrizes(id)`
149
+
150
+ **Rewards & Qualifications** — `getTournamentRewardClaims(id, params?)`, `getTournamentRewardClaimsSummary(id)`, `getTournamentQualifications(id, params?)`, `getTournamentPrizeAggregation(id)`
151
+
152
+ **Players** — `getPlayerTournaments(address, params?)`, `getPlayerStats(address)`
153
+
154
+ **Games** — `getGameTournaments(gameAddress, params?)`, `getGameStats(gameAddress)`
155
+
156
+ **Activity** — `getActivity(params?)`, `getActivityStats()`, `getPrizeStats()`
157
+
158
+ **WebSocket** — `connect()`, `disconnect()`, `subscribe(channels, handler, tournamentIds?)`, `onWsConnectionChange(listener)`
159
+
160
+ **Utilities** — `getConnectionStatus()`, `onConnectionStatusChange(listener)`, `destroy()`
161
+
162
+ ### React Hooks
163
+
164
+ All data hooks return `{ data, isLoading, error, refetch }`.
165
+
166
+ **Data** — `useTournaments(params?)`, `useTournament(id)`, `useLeaderboard(tournamentId)`, `usePlayerTournaments(address, params?)`, `usePlayerStats(address)`, `usePlayer(address)`
167
+
168
+ **Rewards & Prizes** — `useRewardClaims(tournamentId)`, `useRewardClaimsSummary(tournamentId)`, `usePrizes(tournamentId)`, `usePrizeStats()`, `useQualifications(tournamentId)`
169
+
170
+ **WebSocket** — `useSubscription(channels, handler, tournamentIds?)`
171
+
172
+ **Context** — `useBudokanClient()`, `useConnectionStatus()`
173
+
174
+ ## Error Handling
175
+
176
+ ```ts
177
+ import { BudokanError, BudokanApiError, DataSourceError } from "@provable-games/budokan-sdk";
178
+
179
+ try {
180
+ const tournament = await client.getTournament("42");
181
+ } catch (error) {
182
+ if (error instanceof DataSourceError) {
183
+ console.log("Primary failed:", error.primaryError.message);
184
+ console.log("Fallback failed:", error.fallbackError.message);
185
+ } else if (error instanceof BudokanApiError) {
186
+ console.log("HTTP status:", error.statusCode);
187
+ }
188
+ }
189
+ ```
190
+
191
+ Error classes: `BudokanError`, `BudokanApiError`, `BudokanTimeoutError`, `BudokanConnectionError`, `TournamentNotFoundError`, `RpcError`, `DataSourceError`.
192
+
193
+ ## Development
194
+
195
+ ```bash
196
+ npm install
197
+ npm run build # ESM + CJS to dist/
198
+ npm run typecheck # TypeScript validation
199
+ npm run dev # Watch mode
200
+ ```
201
+
202
+ ## Publishing
203
+
204
+ Publishing is automated via GitHub Actions. To release:
205
+
206
+ 1. Bump the version in `package.json`
207
+ 2. Create a GitHub Release (e.g. `v0.1.0`)
208
+ 3. The `publish.yml` workflow runs typecheck, build, and publishes to npm
209
+
210
+ Requires an `NPM_TOKEN` secret configured in the repo settings.
211
+
212
+ ## License
213
+
214
+ MIT
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@provable-games/budokan-sdk",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for Budokan — tournament management platform on Starknet",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "./react": {
21
+ "import": {
22
+ "types": "./dist/react.d.ts",
23
+ "default": "./dist/react.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/react.d.cts",
27
+ "default": "./dist/react.cjs"
28
+ }
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "sideEffects": false,
35
+ "scripts": {
36
+ "build": "tsup",
37
+ "dev": "tsup --watch",
38
+ "typecheck": "tsc --noEmit",
39
+ "clean": "rm -rf dist"
40
+ },
41
+ "keywords": [
42
+ "starknet",
43
+ "budokan",
44
+ "tournaments",
45
+ "gaming",
46
+ "sdk"
47
+ ],
48
+ "author": "Provable Games",
49
+ "license": "MIT",
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "peerDependencies": {
54
+ "react": ">=18.0.0",
55
+ "starknet": ">=9.0.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "react": {
59
+ "optional": true
60
+ },
61
+ "starknet": {
62
+ "optional": true
63
+ }
64
+ },
65
+ "devDependencies": {
66
+ "@types/react": "^19.0.0",
67
+ "react": "^19.0.0",
68
+ "starknet": "^9.2.1",
69
+ "tsup": "^8.4.0",
70
+ "typescript": "^5.7.0"
71
+ },
72
+ "engines": {
73
+ "node": ">=22.0.0"
74
+ },
75
+ "dependencies": {
76
+ "@rollup/rollup-linux-arm64-gnu": "^4.59.0"
77
+ }
78
+ }