@provable-games/budokan-sdk 0.1.3 → 0.1.5

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 CHANGED
@@ -120,26 +120,46 @@ interface BudokanClientConfig {
120
120
 
121
121
  ## Data Source Fallback
122
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 |
123
+ The SDK supports two data sources: **API** (REST indexer) and **RPC** (direct Starknet contract calls via BudokanViewer). Set `primarySource: "api"` (default) or `primarySource: "rpc"` in config. When the API goes down, methods with RPC support automatically fall back to direct contract calls.
124
+
125
+ ### Feature Support
126
+
127
+ | Method | API | RPC | Notes |
128
+ |--------|:---:|:---:|-------|
129
+ | **Tournaments** | | | |
130
+ | `getTournaments(params?)` | | | RPC groups phases: `scheduled` includes Scheduled+Registration+Staging, `live` includes Live+Submission |
131
+ | `getTournament(id)` | | | |
132
+ | `getTournamentLeaderboard(id)` | | | |
133
+ | `getTournamentRegistrations(id)` | | | RPC: `playerAddress` and `gameAddress` fields will be empty |
134
+ | `getTournamentPrizes(id)` | | | |
135
+ | `getGameTournaments(addr)` | | | |
136
+ | **Prize Aggregation** | | | |
137
+ | `getTournamentPrizeAggregation(id)` | | | API only |
138
+ | `includePrizeSummary` param | | | RPC fetches prizes per tournament and builds aggregation client-side |
139
+ | **Rewards** | | | |
140
+ | `getTournamentRewardClaims(id)` | | | RPC checks `is_prize_claimed` per prize via viewer |
141
+ | `getTournamentRewardClaimsSummary(id)` | | | RPC returns totals from viewer |
142
+ | `getTournamentQualifications(id)` | | ⚠️ | On-chain via `get_qualification_entries` — requires proof input, not yet wired |
143
+ | **Players** | | | |
144
+ | `getPlayerTournaments(addr)` | ✅ | ✅ | RPC iterates tournaments and checks entry ownership via ERC721 |
145
+ | `getPlayerStats(addr)` | ✅ | ❌ | API only — requires aggregated stats |
146
+ | **Games** | | | |
147
+ | `getGameStats(addr)` | ✅ | ❌ | API only — requires aggregated stats |
148
+ | **Activity** | | | |
149
+ | `getActivity(params?)` | ✅ | ❌ | API only — activity is indexed from events |
150
+ | `getActivityStats()` | ✅ | ❌ | API only — requires aggregated stats |
151
+ | `getPrizeStats()` | ✅ | ❌ | API only — requires aggregated stats |
152
+ | **WebSocket** | | | |
153
+ | `subscribe(channels, handler)` | ✅ | ❌ | Requires API WebSocket server |
154
+
155
+ ### RPC Behaviour
156
+
157
+ When `primarySource: "rpc"`:
158
+ - All tournament queries go directly to the **BudokanViewer** contract — no API calls
159
+ - Phase filtering uses `tournaments_by_phases` for grouped queries (e.g., "scheduled" queries 3 phases in 1 RPC call)
160
+ - Prize aggregation for tournament cards is built client-side from per-tournament prize data
161
+ - API-only methods will throw an error — they require the indexed API
162
+ - Stale data is automatically cleared when switching networks
143
163
 
144
164
  ## API Reference
145
165
 
@@ -193,10 +213,10 @@ Error classes: `BudokanError`, `BudokanApiError`, `BudokanTimeoutError`, `Budoka
193
213
  ## Development
194
214
 
195
215
  ```bash
196
- npm install
197
- npm run build # ESM + CJS to dist/
198
- npm run typecheck # TypeScript validation
199
- npm run dev # Watch mode
216
+ bun install
217
+ bun run build # ESM + CJS to dist/
218
+ bun run typecheck # TypeScript validation
219
+ bun run dev # Watch mode
200
220
  ```
201
221
 
202
222
  ## Publishing
@@ -1,10 +1,13 @@
1
+ import { RpcProvider } from 'starknet';
2
+ import { EntryFee, EntryRequirement, QualificationProof } from '@provable-games/metagame-sdk';
3
+
1
4
  type DataSource = "api" | "rpc";
2
5
  interface BudokanClientConfig {
3
6
  apiBaseUrl: string;
4
7
  wsUrl?: string;
5
8
  rpcUrl?: string;
6
9
  chain?: "mainnet" | "sepolia";
7
- provider?: unknown;
10
+ provider?: RpcProvider;
8
11
  viewerAddress?: string;
9
12
  budokanAddress?: string;
10
13
  primarySource?: DataSource;
@@ -52,7 +55,7 @@ interface Tournament {
52
55
  schedule: Schedule | null;
53
56
  gameConfig: GameConfig | null;
54
57
  entryFee: EntryFee | null;
55
- entryRequirement: unknown | null;
58
+ entryRequirement: EntryRequirement | null;
56
59
  leaderboardConfig: LeaderboardConfig | null;
57
60
  entryCount: number;
58
61
  prizeCount: number;
@@ -64,7 +67,7 @@ interface Tournament {
64
67
  totalAmount: string;
65
68
  nftCount: number;
66
69
  }>;
67
- metadata: unknown | null;
70
+ metadata: Record<string, unknown> | null;
68
71
  }
69
72
  interface Schedule {
70
73
  registrationStartDelay: number;
@@ -81,15 +84,6 @@ interface GameConfig {
81
84
  clientUrl: string | null;
82
85
  renderer: string | null;
83
86
  }
84
- interface EntryFee {
85
- tokenAddress: string;
86
- amount: string;
87
- tournamentCreatorShare: number;
88
- gameCreatorShare: number;
89
- refundShare: number;
90
- distribution: unknown;
91
- distributionCount: number;
92
- }
93
87
  interface LeaderboardConfig {
94
88
  ascending: boolean;
95
89
  gameMustBeOver: boolean;
@@ -109,7 +103,7 @@ interface TournamentListParams {
109
103
  }
110
104
  interface QualificationEntry {
111
105
  tournamentId: string;
112
- qualificationProof: unknown;
106
+ qualificationProof: QualificationProof | null;
113
107
  entryCount: number;
114
108
  }
115
109
 
@@ -128,6 +122,23 @@ interface Registration {
128
122
  isBanned: boolean;
129
123
  }
130
124
 
125
+ type RewardType = {
126
+ Prize: {
127
+ tokenAddress: string;
128
+ tokenType: string;
129
+ };
130
+ } | {
131
+ EntryFee: EntryFeeRewardType;
132
+ };
133
+ type EntryFeeRewardType = {
134
+ Position: number;
135
+ } | {
136
+ TournamentCreator: Record<string, never>;
137
+ } | {
138
+ GameCreator: Record<string, never>;
139
+ } | {
140
+ Refund: string;
141
+ };
131
142
  interface Prize {
132
143
  prizeId: string;
133
144
  tournamentId: string;
@@ -143,7 +154,7 @@ interface Prize {
143
154
  }
144
155
  interface RewardClaim {
145
156
  tournamentId: string;
146
- rewardType: unknown;
157
+ rewardType: RewardType;
147
158
  claimed: boolean;
148
159
  }
149
160
  interface PrizeAggregation {
@@ -177,7 +188,7 @@ interface ActivityEvent {
177
188
  eventType: string;
178
189
  tournamentId: string | null;
179
190
  playerAddress: string | null;
180
- data: unknown;
191
+ data: Record<string, unknown>;
181
192
  blockNumber: string;
182
193
  txHash: string;
183
194
  eventIndex: number;
@@ -224,7 +235,7 @@ interface WSUnsubscribeMessage {
224
235
  interface WSEventMessage {
225
236
  type: "event";
226
237
  channel: WSChannel;
227
- data: unknown;
238
+ data: Record<string, unknown>;
228
239
  timestamp: string;
229
240
  }
230
241
  type WSMessage = WSSubscribeMessage | WSUnsubscribeMessage | WSEventMessage;
@@ -358,7 +369,7 @@ declare class BudokanClient {
358
369
  getTournamentPrizes(tournamentId: string): Promise<Prize[]>;
359
370
  /**
360
371
  * Fetch tournaments that a player has registered for.
361
- * API-only — no RPC fallback available.
372
+ * Supports RPC fallback via viewer contract.
362
373
  */
363
374
  getPlayerTournaments(address: string, params?: PlayerTournamentParams): Promise<PaginatedResult<PlayerTournament>>;
364
375
  /**
@@ -378,7 +389,7 @@ declare class BudokanClient {
378
389
  getGameStats(gameAddress: string): Promise<PlatformStats>;
379
390
  /**
380
391
  * Fetch reward claims for a tournament.
381
- * API-only -- no RPC fallback available.
392
+ * Supports RPC fallback via viewer contract.
382
393
  */
383
394
  getTournamentRewardClaims(tournamentId: string, params?: {
384
395
  limit?: number;
@@ -386,7 +397,7 @@ declare class BudokanClient {
386
397
  }): Promise<PaginatedResult<RewardClaim>>;
387
398
  /**
388
399
  * Fetch reward claims summary for a tournament.
389
- * API-only -- no RPC fallback available.
400
+ * Supports RPC fallback via viewer contract.
390
401
  */
391
402
  getTournamentRewardClaimsSummary(tournamentId: string): Promise<RewardClaimSummary>;
392
403
  /**
@@ -445,4 +456,4 @@ declare class BudokanClient {
445
456
  */
446
457
  declare function createBudokanClient(config: BudokanClientConfig): BudokanClient;
447
458
 
448
- export { type ActivityParams as A, BudokanClient as B, type ConnectionMode as C, type DataSource as D, type EntryFee as E, type GameConfig as G, type LeaderboardEntry as L, type PrizeAggregation as P, type QualificationEntry as Q, type Registration as R, type Schedule as S, type Tournament as T, type WSSubscribeOptions as W, type Prize as a, type PaginatedResult as b, type RewardClaim as c, type RewardClaimSummary as d, type TournamentListParams as e, type PlayerStats as f, type PlayerTournamentParams as g, type PlayerTournament as h, type PlatformStats as i, type ActivityEvent as j, type PrizeStats as k, type WSEventHandler as l, type BudokanClientConfig as m, ConnectionStatus as n, type ConnectionStatusState as o, type LeaderboardConfig as p, type Phase as q, type WSChannel as r, type WSEventMessage as s, type WSMessage as t, type WSSubscribeMessage as u, type WSUnsubscribeMessage as v, createBudokanClient as w };
459
+ export { type ActivityParams as A, BudokanClient as B, type ConnectionMode as C, type DataSource as D, type GameConfig as G, type LeaderboardEntry as L, type PrizeAggregation as P, type QualificationEntry as Q, type Registration as R, type Schedule as S, type Tournament as T, type WSSubscribeOptions as W, type Prize as a, type PaginatedResult as b, type RewardClaim as c, type RewardClaimSummary as d, type TournamentListParams as e, type PlayerStats as f, type PlayerTournamentParams as g, type PlayerTournament as h, type PlatformStats as i, type ActivityEvent as j, type PrizeStats as k, type WSEventHandler as l, type BudokanClientConfig as m, ConnectionStatus as n, type ConnectionStatusState as o, type LeaderboardConfig as p, type Phase as q, type WSChannel as r, type WSEventMessage as s, type WSMessage as t, type WSSubscribeMessage as u, type WSUnsubscribeMessage as v, createBudokanClient as w };
@@ -1,10 +1,13 @@
1
+ import { RpcProvider } from 'starknet';
2
+ import { EntryFee, EntryRequirement, QualificationProof } from '@provable-games/metagame-sdk';
3
+
1
4
  type DataSource = "api" | "rpc";
2
5
  interface BudokanClientConfig {
3
6
  apiBaseUrl: string;
4
7
  wsUrl?: string;
5
8
  rpcUrl?: string;
6
9
  chain?: "mainnet" | "sepolia";
7
- provider?: unknown;
10
+ provider?: RpcProvider;
8
11
  viewerAddress?: string;
9
12
  budokanAddress?: string;
10
13
  primarySource?: DataSource;
@@ -52,7 +55,7 @@ interface Tournament {
52
55
  schedule: Schedule | null;
53
56
  gameConfig: GameConfig | null;
54
57
  entryFee: EntryFee | null;
55
- entryRequirement: unknown | null;
58
+ entryRequirement: EntryRequirement | null;
56
59
  leaderboardConfig: LeaderboardConfig | null;
57
60
  entryCount: number;
58
61
  prizeCount: number;
@@ -64,7 +67,7 @@ interface Tournament {
64
67
  totalAmount: string;
65
68
  nftCount: number;
66
69
  }>;
67
- metadata: unknown | null;
70
+ metadata: Record<string, unknown> | null;
68
71
  }
69
72
  interface Schedule {
70
73
  registrationStartDelay: number;
@@ -81,15 +84,6 @@ interface GameConfig {
81
84
  clientUrl: string | null;
82
85
  renderer: string | null;
83
86
  }
84
- interface EntryFee {
85
- tokenAddress: string;
86
- amount: string;
87
- tournamentCreatorShare: number;
88
- gameCreatorShare: number;
89
- refundShare: number;
90
- distribution: unknown;
91
- distributionCount: number;
92
- }
93
87
  interface LeaderboardConfig {
94
88
  ascending: boolean;
95
89
  gameMustBeOver: boolean;
@@ -109,7 +103,7 @@ interface TournamentListParams {
109
103
  }
110
104
  interface QualificationEntry {
111
105
  tournamentId: string;
112
- qualificationProof: unknown;
106
+ qualificationProof: QualificationProof | null;
113
107
  entryCount: number;
114
108
  }
115
109
 
@@ -128,6 +122,23 @@ interface Registration {
128
122
  isBanned: boolean;
129
123
  }
130
124
 
125
+ type RewardType = {
126
+ Prize: {
127
+ tokenAddress: string;
128
+ tokenType: string;
129
+ };
130
+ } | {
131
+ EntryFee: EntryFeeRewardType;
132
+ };
133
+ type EntryFeeRewardType = {
134
+ Position: number;
135
+ } | {
136
+ TournamentCreator: Record<string, never>;
137
+ } | {
138
+ GameCreator: Record<string, never>;
139
+ } | {
140
+ Refund: string;
141
+ };
131
142
  interface Prize {
132
143
  prizeId: string;
133
144
  tournamentId: string;
@@ -143,7 +154,7 @@ interface Prize {
143
154
  }
144
155
  interface RewardClaim {
145
156
  tournamentId: string;
146
- rewardType: unknown;
157
+ rewardType: RewardType;
147
158
  claimed: boolean;
148
159
  }
149
160
  interface PrizeAggregation {
@@ -177,7 +188,7 @@ interface ActivityEvent {
177
188
  eventType: string;
178
189
  tournamentId: string | null;
179
190
  playerAddress: string | null;
180
- data: unknown;
191
+ data: Record<string, unknown>;
181
192
  blockNumber: string;
182
193
  txHash: string;
183
194
  eventIndex: number;
@@ -224,7 +235,7 @@ interface WSUnsubscribeMessage {
224
235
  interface WSEventMessage {
225
236
  type: "event";
226
237
  channel: WSChannel;
227
- data: unknown;
238
+ data: Record<string, unknown>;
228
239
  timestamp: string;
229
240
  }
230
241
  type WSMessage = WSSubscribeMessage | WSUnsubscribeMessage | WSEventMessage;
@@ -358,7 +369,7 @@ declare class BudokanClient {
358
369
  getTournamentPrizes(tournamentId: string): Promise<Prize[]>;
359
370
  /**
360
371
  * Fetch tournaments that a player has registered for.
361
- * API-only — no RPC fallback available.
372
+ * Supports RPC fallback via viewer contract.
362
373
  */
363
374
  getPlayerTournaments(address: string, params?: PlayerTournamentParams): Promise<PaginatedResult<PlayerTournament>>;
364
375
  /**
@@ -378,7 +389,7 @@ declare class BudokanClient {
378
389
  getGameStats(gameAddress: string): Promise<PlatformStats>;
379
390
  /**
380
391
  * Fetch reward claims for a tournament.
381
- * API-only -- no RPC fallback available.
392
+ * Supports RPC fallback via viewer contract.
382
393
  */
383
394
  getTournamentRewardClaims(tournamentId: string, params?: {
384
395
  limit?: number;
@@ -386,7 +397,7 @@ declare class BudokanClient {
386
397
  }): Promise<PaginatedResult<RewardClaim>>;
387
398
  /**
388
399
  * Fetch reward claims summary for a tournament.
389
- * API-only -- no RPC fallback available.
400
+ * Supports RPC fallback via viewer contract.
390
401
  */
391
402
  getTournamentRewardClaimsSummary(tournamentId: string): Promise<RewardClaimSummary>;
392
403
  /**
@@ -445,4 +456,4 @@ declare class BudokanClient {
445
456
  */
446
457
  declare function createBudokanClient(config: BudokanClientConfig): BudokanClient;
447
458
 
448
- export { type ActivityParams as A, BudokanClient as B, type ConnectionMode as C, type DataSource as D, type EntryFee as E, type GameConfig as G, type LeaderboardEntry as L, type PrizeAggregation as P, type QualificationEntry as Q, type Registration as R, type Schedule as S, type Tournament as T, type WSSubscribeOptions as W, type Prize as a, type PaginatedResult as b, type RewardClaim as c, type RewardClaimSummary as d, type TournamentListParams as e, type PlayerStats as f, type PlayerTournamentParams as g, type PlayerTournament as h, type PlatformStats as i, type ActivityEvent as j, type PrizeStats as k, type WSEventHandler as l, type BudokanClientConfig as m, ConnectionStatus as n, type ConnectionStatusState as o, type LeaderboardConfig as p, type Phase as q, type WSChannel as r, type WSEventMessage as s, type WSMessage as t, type WSSubscribeMessage as u, type WSUnsubscribeMessage as v, createBudokanClient as w };
459
+ export { type ActivityParams as A, BudokanClient as B, type ConnectionMode as C, type DataSource as D, type GameConfig as G, type LeaderboardEntry as L, type PrizeAggregation as P, type QualificationEntry as Q, type Registration as R, type Schedule as S, type Tournament as T, type WSSubscribeOptions as W, type Prize as a, type PaginatedResult as b, type RewardClaim as c, type RewardClaimSummary as d, type TournamentListParams as e, type PlayerStats as f, type PlayerTournamentParams as g, type PlayerTournament as h, type PlatformStats as i, type ActivityEvent as j, type PrizeStats as k, type WSEventHandler as l, type BudokanClientConfig as m, ConnectionStatus as n, type ConnectionStatusState as o, type LeaderboardConfig as p, type Phase as q, type WSChannel as r, type WSEventMessage as s, type WSMessage as t, type WSSubscribeMessage as u, type WSUnsubscribeMessage as v, createBudokanClient as w };