@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.
- package/README.md +214 -0
- 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
|
+
}
|