@provable-games/budokan-sdk 0.1.18 → 0.1.20

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.
@@ -100,6 +100,14 @@ interface TournamentListParams {
100
100
  sort?: "start_time" | "end_time" | "players" | "created_at";
101
101
  fromId?: string;
102
102
  excludeIds?: string[];
103
+ /**
104
+ * Restrict results to this set of tournament IDs. Used by the
105
+ * "My Tournaments" UX where the caller derives ids from currently-owned
106
+ * game tokens (denshokan-sdk) and asks Budokan only for those tournaments.
107
+ * Mutually exclusive with no-filter "show everything" semantics — an empty
108
+ * array yields zero results, not all tournaments.
109
+ */
110
+ tournamentIds?: string[];
103
111
  whitelistedExtensions?: string[];
104
112
  includePrizeSummary?: "summary" | boolean;
105
113
  }
@@ -114,11 +122,20 @@ interface LeaderboardEntry {
114
122
  tokenId: string;
115
123
  }
116
124
 
125
+ /**
126
+ * A registration row keyed by (tournamentId, gameTokenId).
127
+ *
128
+ * Note: there is intentionally no `playerAddress` field. The contract keys
129
+ * registrations by token id only — once the underlying NFT transfers, any
130
+ * stored "registrant" address is the wrong signal for current ownership.
131
+ * Callers that need the current owner of an entry should resolve it via
132
+ * `denshokan-sdk.useTokens` (filtering by minterAddress + contextId).
133
+ * See Provable-Games/budokan#241.
134
+ */
117
135
  interface Registration {
118
136
  tournamentId: string;
119
137
  gameTokenId: string;
120
138
  gameAddress: string;
121
- playerAddress: string;
122
139
  entryNumber: number;
123
140
  hasSubmitted: boolean;
124
141
  isBanned: boolean;
@@ -174,20 +191,6 @@ interface RewardClaimSummary {
174
191
  totalUnclaimed: number;
175
192
  }
176
193
 
177
- interface PlayerStats {
178
- totalTournaments: number;
179
- totalSubmissions: number;
180
- }
181
- interface PlayerTournament extends Tournament {
182
- registration: Registration;
183
- }
184
- interface PlayerTournamentParams {
185
- phase?: Phase;
186
- gameTokenIds?: string[];
187
- limit?: number;
188
- offset?: number;
189
- }
190
-
191
194
  interface ActivityEvent {
192
195
  id: string;
193
196
  eventType: string;
@@ -401,7 +404,6 @@ declare class BudokanClient {
401
404
  * are applied via on-chain viewer functions where supported.
402
405
  */
403
406
  getTournamentRegistrations(tournamentId: string, params?: {
404
- playerAddress?: string;
405
407
  gameTokenIds?: string[];
406
408
  hasSubmitted?: boolean;
407
409
  isBanned?: boolean;
@@ -413,16 +415,6 @@ declare class BudokanClient {
413
415
  * Supports RPC fallback when API is unavailable.
414
416
  */
415
417
  getTournamentPrizes(tournamentId: string): Promise<Prize[]>;
416
- /**
417
- * Fetch tournaments that a player has registered for.
418
- * Supports RPC fallback via viewer contract.
419
- */
420
- getPlayerTournaments(address: string, params?: PlayerTournamentParams): Promise<PaginatedResult<PlayerTournament>>;
421
- /**
422
- * Fetch stats for a player.
423
- * API-only — no RPC fallback available.
424
- */
425
- getPlayerStats(address: string): Promise<PlayerStats>;
426
418
  /**
427
419
  * Fetch tournaments for a specific game.
428
420
  * Supports RPC fallback when API is unavailable.
@@ -502,4 +494,4 @@ declare class BudokanClient {
502
494
  */
503
495
  declare function createBudokanClient(config: BudokanClientConfig): BudokanClient;
504
496
 
505
- export { type ActivityParams as A, BudokanClient as B, type ConnectionMode as C, type DataSource as D, type GameConfig as G, type LeaderboardConfig 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 LeaderboardEntry 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 };
497
+ export { type ActivityParams as A, BudokanClient as B, type ConnectionMode as C, type DataSource as D, type GameConfig as G, type LeaderboardConfig 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 PlatformStats as f, type ActivityEvent as g, type PrizeStats as h, type WSEventHandler as i, type BudokanClientConfig as j, ConnectionStatus as k, type ConnectionStatusState as l, type LeaderboardEntry as m, type Phase as n, type WSChannel as o, type WSEventMessage as p, type WSMessage as q, type WSSubscribeMessage as r, type WSUnsubscribeMessage as s, createBudokanClient as t };
@@ -100,6 +100,14 @@ interface TournamentListParams {
100
100
  sort?: "start_time" | "end_time" | "players" | "created_at";
101
101
  fromId?: string;
102
102
  excludeIds?: string[];
103
+ /**
104
+ * Restrict results to this set of tournament IDs. Used by the
105
+ * "My Tournaments" UX where the caller derives ids from currently-owned
106
+ * game tokens (denshokan-sdk) and asks Budokan only for those tournaments.
107
+ * Mutually exclusive with no-filter "show everything" semantics — an empty
108
+ * array yields zero results, not all tournaments.
109
+ */
110
+ tournamentIds?: string[];
103
111
  whitelistedExtensions?: string[];
104
112
  includePrizeSummary?: "summary" | boolean;
105
113
  }
@@ -114,11 +122,20 @@ interface LeaderboardEntry {
114
122
  tokenId: string;
115
123
  }
116
124
 
125
+ /**
126
+ * A registration row keyed by (tournamentId, gameTokenId).
127
+ *
128
+ * Note: there is intentionally no `playerAddress` field. The contract keys
129
+ * registrations by token id only — once the underlying NFT transfers, any
130
+ * stored "registrant" address is the wrong signal for current ownership.
131
+ * Callers that need the current owner of an entry should resolve it via
132
+ * `denshokan-sdk.useTokens` (filtering by minterAddress + contextId).
133
+ * See Provable-Games/budokan#241.
134
+ */
117
135
  interface Registration {
118
136
  tournamentId: string;
119
137
  gameTokenId: string;
120
138
  gameAddress: string;
121
- playerAddress: string;
122
139
  entryNumber: number;
123
140
  hasSubmitted: boolean;
124
141
  isBanned: boolean;
@@ -174,20 +191,6 @@ interface RewardClaimSummary {
174
191
  totalUnclaimed: number;
175
192
  }
176
193
 
177
- interface PlayerStats {
178
- totalTournaments: number;
179
- totalSubmissions: number;
180
- }
181
- interface PlayerTournament extends Tournament {
182
- registration: Registration;
183
- }
184
- interface PlayerTournamentParams {
185
- phase?: Phase;
186
- gameTokenIds?: string[];
187
- limit?: number;
188
- offset?: number;
189
- }
190
-
191
194
  interface ActivityEvent {
192
195
  id: string;
193
196
  eventType: string;
@@ -401,7 +404,6 @@ declare class BudokanClient {
401
404
  * are applied via on-chain viewer functions where supported.
402
405
  */
403
406
  getTournamentRegistrations(tournamentId: string, params?: {
404
- playerAddress?: string;
405
407
  gameTokenIds?: string[];
406
408
  hasSubmitted?: boolean;
407
409
  isBanned?: boolean;
@@ -413,16 +415,6 @@ declare class BudokanClient {
413
415
  * Supports RPC fallback when API is unavailable.
414
416
  */
415
417
  getTournamentPrizes(tournamentId: string): Promise<Prize[]>;
416
- /**
417
- * Fetch tournaments that a player has registered for.
418
- * Supports RPC fallback via viewer contract.
419
- */
420
- getPlayerTournaments(address: string, params?: PlayerTournamentParams): Promise<PaginatedResult<PlayerTournament>>;
421
- /**
422
- * Fetch stats for a player.
423
- * API-only — no RPC fallback available.
424
- */
425
- getPlayerStats(address: string): Promise<PlayerStats>;
426
418
  /**
427
419
  * Fetch tournaments for a specific game.
428
420
  * Supports RPC fallback when API is unavailable.
@@ -502,4 +494,4 @@ declare class BudokanClient {
502
494
  */
503
495
  declare function createBudokanClient(config: BudokanClientConfig): BudokanClient;
504
496
 
505
- export { type ActivityParams as A, BudokanClient as B, type ConnectionMode as C, type DataSource as D, type GameConfig as G, type LeaderboardConfig 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 LeaderboardEntry 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 };
497
+ export { type ActivityParams as A, BudokanClient as B, type ConnectionMode as C, type DataSource as D, type GameConfig as G, type LeaderboardConfig 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 PlatformStats as f, type ActivityEvent as g, type PrizeStats as h, type WSEventHandler as i, type BudokanClientConfig as j, ConnectionStatus as k, type ConnectionStatusState as l, type LeaderboardEntry as m, type Phase as n, type WSChannel as o, type WSEventMessage as p, type WSMessage as q, type WSSubscribeMessage as r, type WSUnsubscribeMessage as s, createBudokanClient as t };
package/dist/index.cjs CHANGED
@@ -233,6 +233,7 @@ async function getTournaments(baseUrl, params, ctx) {
233
233
  sort: params?.sort,
234
234
  from_id: params?.fromId,
235
235
  exclude_ids: params?.excludeIds?.join(","),
236
+ tournament_ids: params?.tournamentIds?.join(","),
236
237
  whitelisted_extensions: params?.whitelistedExtensions?.join(","),
237
238
  include_prizes: params?.includePrizeSummary
238
239
  });
@@ -254,7 +255,6 @@ async function getTournament(baseUrl, tournamentId, ctx) {
254
255
  }
255
256
  async function getTournamentRegistrations(baseUrl, tournamentId, params, ctx) {
256
257
  const qs = buildQueryString({
257
- player_address: params?.playerAddress,
258
258
  game_token_ids: params?.gameTokenIds?.length ? params.gameTokenIds.join(",") : void 0,
259
259
  has_submitted: params?.hasSubmitted,
260
260
  is_banned: params?.isBanned,
@@ -327,42 +327,8 @@ function normalizeAddress(address) {
327
327
  return ("0x" + stripped.padStart(64, "0")).toLowerCase();
328
328
  }
329
329
 
330
- // src/api/players.ts
331
- function fetchOpts2(ctx) {
332
- return {
333
- retryAttempts: ctx?.retryAttempts,
334
- retryDelay: ctx?.retryDelay,
335
- timeout: ctx?.timeout
336
- };
337
- }
338
- async function getPlayerTournaments(baseUrl, address, params, ctx) {
339
- const normalized = normalizeAddress(address);
340
- const qs = buildQueryString({
341
- limit: params?.limit,
342
- offset: params?.offset,
343
- phase: params?.phase,
344
- game_token_ids: params?.gameTokenIds?.join(",")
345
- });
346
- const result = await apiFetch(`${baseUrl}/players/${normalized}/tournaments${qs}`, fetchOpts2(ctx));
347
- const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
348
- return {
349
- data: result.data.map((item) => snakeToCamel(item)),
350
- total,
351
- limit: resLimit,
352
- offset: resOffset
353
- };
354
- }
355
- async function getPlayerStats(baseUrl, address, ctx) {
356
- const normalized = normalizeAddress(address);
357
- const result = await apiFetch(
358
- `${baseUrl}/players/${normalized}/stats`,
359
- fetchOpts2(ctx)
360
- );
361
- return snakeToCamel(result.data);
362
- }
363
-
364
330
  // src/api/games.ts
365
- function fetchOpts3(ctx) {
331
+ function fetchOpts2(ctx) {
366
332
  return {
367
333
  retryAttempts: ctx?.retryAttempts,
368
334
  retryDelay: ctx?.retryDelay,
@@ -377,7 +343,7 @@ async function getGameTournaments(baseUrl, gameAddress, params, ctx) {
377
343
  limit: params?.limit,
378
344
  offset: params?.offset
379
345
  });
380
- const result = await apiFetch(`${baseUrl}/games/${normalized}/tournaments${qs}`, fetchOpts3(ctx));
346
+ const result = await apiFetch(`${baseUrl}/games/${normalized}/tournaments${qs}`, fetchOpts2(ctx));
381
347
  const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
382
348
  return {
383
349
  data: result.data.map((item) => snakeToCamel(item)),
@@ -390,13 +356,13 @@ async function getGameStats(baseUrl, gameAddress, ctx) {
390
356
  const normalized = normalizeAddress(gameAddress);
391
357
  const result = await apiFetch(
392
358
  `${baseUrl}/games/${normalized}/stats`,
393
- fetchOpts3(ctx)
359
+ fetchOpts2(ctx)
394
360
  );
395
361
  return snakeToCamel(result.data);
396
362
  }
397
363
 
398
364
  // src/api/activity.ts
399
- function fetchOpts4(ctx) {
365
+ function fetchOpts3(ctx) {
400
366
  return {
401
367
  retryAttempts: ctx?.retryAttempts,
402
368
  retryDelay: ctx?.retryDelay,
@@ -411,7 +377,7 @@ async function getActivity(baseUrl, params, ctx) {
411
377
  limit: params?.limit,
412
378
  offset: params?.offset
413
379
  });
414
- const result = await apiFetch(`${baseUrl}/activity${qs}`, fetchOpts4(ctx));
380
+ const result = await apiFetch(`${baseUrl}/activity${qs}`, fetchOpts3(ctx));
415
381
  const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
416
382
  return {
417
383
  data: result.data.map((item) => snakeToCamel(item)),
@@ -423,14 +389,14 @@ async function getActivity(baseUrl, params, ctx) {
423
389
  async function getActivityStats(baseUrl, ctx) {
424
390
  const result = await apiFetch(
425
391
  `${baseUrl}/activity/stats`,
426
- fetchOpts4(ctx)
392
+ fetchOpts3(ctx)
427
393
  );
428
394
  return snakeToCamel(result.data);
429
395
  }
430
396
  async function getPrizeStats(baseUrl, ctx) {
431
397
  const result = await apiFetch(
432
398
  `${baseUrl}/activity/prize-stats`,
433
- fetchOpts4(ctx)
399
+ fetchOpts3(ctx)
434
400
  );
435
401
  return snakeToCamel(result.data);
436
402
  }
@@ -992,8 +958,6 @@ function parseRegistration(raw, tournamentId) {
992
958
  gameTokenId: starknet.num.toHex(obj.game_token_id),
993
959
  gameAddress: "",
994
960
  // Not in on-chain struct
995
- playerAddress: "",
996
- // Not in on-chain struct
997
961
  entryNumber: Number(obj.entry_id ?? 0),
998
962
  hasSubmitted: Boolean(obj.has_submitted),
999
963
  isBanned: Boolean(obj.is_banned)
@@ -1152,20 +1116,6 @@ async function viewerRegistrations(contract, tournamentId, offset, limit) {
1152
1116
  };
1153
1117
  }, contract.address);
1154
1118
  }
1155
- async function viewerRegistrationsByOwner(contract, tournamentId, owner, offset, limit) {
1156
- return wrapRpcCall(async () => {
1157
- const result = await contract.call("tournament_registrations_by_owner", [tournamentId, owner, offset, limit]);
1158
- const obj = result;
1159
- const entries = obj.entries ?? [];
1160
- const total = Number(obj.total ?? 0);
1161
- return {
1162
- data: entries.map((e) => parseRegistration(e, tournamentId)),
1163
- total,
1164
- limit,
1165
- offset
1166
- };
1167
- }, contract.address);
1168
- }
1169
1119
  async function viewerRegistrationsByTokenIds(contract, tournamentId, tokenIds, offset, limit) {
1170
1120
  return wrapRpcCall(async () => {
1171
1121
  const result = await contract.call("tournament_registrations_by_token_ids", [tournamentId, tokenIds, offset, limit]);
@@ -1211,12 +1161,6 @@ async function viewerRewardClaims(contract, tournamentId, offset, limit) {
1211
1161
  };
1212
1162
  }, contract.address);
1213
1163
  }
1214
- async function viewerPlayerTournaments(contract, playerAddress, offset, limit) {
1215
- return wrapRpcCall(async () => {
1216
- const result = await contract.call("player_tournaments", [playerAddress, offset, limit]);
1217
- return parseFilterResult(result);
1218
- }, contract.address);
1219
- }
1220
1164
 
1221
1165
  // src/rpc/abis/budokanViewer.json
1222
1166
  var budokanViewer_default = [
@@ -4524,9 +4468,6 @@ var BudokanClient = class {
4524
4468
  const contract = await this.getViewerContract();
4525
4469
  const offset = params?.offset ?? 0;
4526
4470
  const limit = params?.limit ?? 20;
4527
- if (params?.playerAddress) {
4528
- return viewerRegistrationsByOwner(contract, tournamentId, params.playerAddress, offset, limit);
4529
- }
4530
4471
  if (params?.gameTokenIds?.length) {
4531
4472
  return viewerRegistrationsByTokenIds(contract, tournamentId, params.gameTokenIds, offset, limit);
4532
4473
  }
@@ -4559,43 +4500,6 @@ var BudokanClient = class {
4559
4500
  this.connectionStatus
4560
4501
  );
4561
4502
  }
4562
- // ---- Player Queries (API-only, no on-chain equivalent) ----
4563
- /**
4564
- * Fetch tournaments that a player has registered for.
4565
- * Supports RPC fallback via viewer contract.
4566
- */
4567
- async getPlayerTournaments(address, params) {
4568
- const rpcFallback = async () => {
4569
- const contract = await this.getViewerContract();
4570
- const offset = params?.offset ?? 0;
4571
- const limit = params?.limit ?? 20;
4572
- const filterResult = await viewerPlayerTournaments(contract, address, offset, limit);
4573
- let data = [];
4574
- if (filterResult.tournamentIds.length > 0) {
4575
- const tournaments = await viewerTournamentsBatch(contract, filterResult.tournamentIds);
4576
- data = tournaments.map((t) => ({
4577
- ...t,
4578
- tournamentId: t.id
4579
- }));
4580
- }
4581
- return { data, total: filterResult.total, limit, offset };
4582
- };
4583
- if (this.resolvedConfig.primarySource === "rpc") {
4584
- return rpcFallback();
4585
- }
4586
- return withFallback(
4587
- () => getPlayerTournaments(this.resolvedConfig.apiBaseUrl, address, params, this.apiCtx),
4588
- rpcFallback,
4589
- this.connectionStatus
4590
- );
4591
- }
4592
- /**
4593
- * Fetch stats for a player.
4594
- * API-only — no RPC fallback available.
4595
- */
4596
- async getPlayerStats(address) {
4597
- return getPlayerStats(this.resolvedConfig.apiBaseUrl, address, this.apiCtx);
4598
- }
4599
4503
  // ---- Game Queries ----
4600
4504
  /**
4601
4505
  * Fetch tournaments for a specific game.
@@ -4772,8 +4676,6 @@ exports.getActivityStats = getActivityStats;
4772
4676
  exports.getChainConfig = getChainConfig;
4773
4677
  exports.getGameStats = getGameStats;
4774
4678
  exports.getGameTournaments = getGameTournaments;
4775
- exports.getPlayerStats = getPlayerStats;
4776
- exports.getPlayerTournaments = getPlayerTournaments;
4777
4679
  exports.getPrizeStats = getPrizeStats;
4778
4680
  exports.getTournament = getTournament;
4779
4681
  exports.getTournamentPrizeAggregation = getTournamentPrizeAggregation;