@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.
package/dist/react.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createContext, useMemo, useRef, useEffect, useContext, useState, useCallback } from 'react';
2
2
  import { num, CairoCustomEnum } from 'starknet';
3
3
  import { jsx } from 'react/jsx-runtime';
4
+ import { useTokens } from '@provable-games/denshokan-sdk/react';
4
5
 
5
6
  // src/react/context.tsx
6
7
 
@@ -219,6 +220,7 @@ async function getTournaments(baseUrl, params, ctx) {
219
220
  sort: params?.sort,
220
221
  from_id: params?.fromId,
221
222
  exclude_ids: params?.excludeIds?.join(","),
223
+ tournament_ids: params?.tournamentIds?.join(","),
222
224
  whitelisted_extensions: params?.whitelistedExtensions?.join(","),
223
225
  include_prizes: params?.includePrizeSummary
224
226
  });
@@ -240,7 +242,6 @@ async function getTournament(baseUrl, tournamentId, ctx) {
240
242
  }
241
243
  async function getTournamentRegistrations(baseUrl, tournamentId, params, ctx) {
242
244
  const qs = buildQueryString({
243
- player_address: params?.playerAddress,
244
245
  game_token_ids: params?.gameTokenIds?.length ? params.gameTokenIds.join(",") : void 0,
245
246
  has_submitted: params?.hasSubmitted,
246
247
  is_banned: params?.isBanned,
@@ -313,42 +314,8 @@ function normalizeAddress(address) {
313
314
  return ("0x" + stripped.padStart(64, "0")).toLowerCase();
314
315
  }
315
316
 
316
- // src/api/players.ts
317
- function fetchOpts2(ctx) {
318
- return {
319
- retryAttempts: ctx?.retryAttempts,
320
- retryDelay: ctx?.retryDelay,
321
- timeout: ctx?.timeout
322
- };
323
- }
324
- async function getPlayerTournaments(baseUrl, address, params, ctx) {
325
- const normalized = normalizeAddress(address);
326
- const qs = buildQueryString({
327
- limit: params?.limit,
328
- offset: params?.offset,
329
- phase: params?.phase,
330
- game_token_ids: params?.gameTokenIds?.join(",")
331
- });
332
- const result = await apiFetch(`${baseUrl}/players/${normalized}/tournaments${qs}`, fetchOpts2(ctx));
333
- const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
334
- return {
335
- data: result.data.map((item) => snakeToCamel(item)),
336
- total,
337
- limit: resLimit,
338
- offset: resOffset
339
- };
340
- }
341
- async function getPlayerStats(baseUrl, address, ctx) {
342
- const normalized = normalizeAddress(address);
343
- const result = await apiFetch(
344
- `${baseUrl}/players/${normalized}/stats`,
345
- fetchOpts2(ctx)
346
- );
347
- return snakeToCamel(result.data);
348
- }
349
-
350
317
  // src/api/games.ts
351
- function fetchOpts3(ctx) {
318
+ function fetchOpts2(ctx) {
352
319
  return {
353
320
  retryAttempts: ctx?.retryAttempts,
354
321
  retryDelay: ctx?.retryDelay,
@@ -363,7 +330,7 @@ async function getGameTournaments(baseUrl, gameAddress, params, ctx) {
363
330
  limit: params?.limit,
364
331
  offset: params?.offset
365
332
  });
366
- const result = await apiFetch(`${baseUrl}/games/${normalized}/tournaments${qs}`, fetchOpts3(ctx));
333
+ const result = await apiFetch(`${baseUrl}/games/${normalized}/tournaments${qs}`, fetchOpts2(ctx));
367
334
  const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
368
335
  return {
369
336
  data: result.data.map((item) => snakeToCamel(item)),
@@ -376,13 +343,13 @@ async function getGameStats(baseUrl, gameAddress, ctx) {
376
343
  const normalized = normalizeAddress(gameAddress);
377
344
  const result = await apiFetch(
378
345
  `${baseUrl}/games/${normalized}/stats`,
379
- fetchOpts3(ctx)
346
+ fetchOpts2(ctx)
380
347
  );
381
348
  return snakeToCamel(result.data);
382
349
  }
383
350
 
384
351
  // src/api/activity.ts
385
- function fetchOpts4(ctx) {
352
+ function fetchOpts3(ctx) {
386
353
  return {
387
354
  retryAttempts: ctx?.retryAttempts,
388
355
  retryDelay: ctx?.retryDelay,
@@ -397,7 +364,7 @@ async function getActivity(baseUrl, params, ctx) {
397
364
  limit: params?.limit,
398
365
  offset: params?.offset
399
366
  });
400
- const result = await apiFetch(`${baseUrl}/activity${qs}`, fetchOpts4(ctx));
367
+ const result = await apiFetch(`${baseUrl}/activity${qs}`, fetchOpts3(ctx));
401
368
  const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
402
369
  return {
403
370
  data: result.data.map((item) => snakeToCamel(item)),
@@ -409,14 +376,14 @@ async function getActivity(baseUrl, params, ctx) {
409
376
  async function getActivityStats(baseUrl, ctx) {
410
377
  const result = await apiFetch(
411
378
  `${baseUrl}/activity/stats`,
412
- fetchOpts4(ctx)
379
+ fetchOpts3(ctx)
413
380
  );
414
381
  return snakeToCamel(result.data);
415
382
  }
416
383
  async function getPrizeStats(baseUrl, ctx) {
417
384
  const result = await apiFetch(
418
385
  `${baseUrl}/activity/prize-stats`,
419
- fetchOpts4(ctx)
386
+ fetchOpts3(ctx)
420
387
  );
421
388
  return snakeToCamel(result.data);
422
389
  }
@@ -978,8 +945,6 @@ function parseRegistration(raw, tournamentId) {
978
945
  gameTokenId: num.toHex(obj.game_token_id),
979
946
  gameAddress: "",
980
947
  // Not in on-chain struct
981
- playerAddress: "",
982
- // Not in on-chain struct
983
948
  entryNumber: Number(obj.entry_id ?? 0),
984
949
  hasSubmitted: Boolean(obj.has_submitted),
985
950
  isBanned: Boolean(obj.is_banned)
@@ -1138,20 +1103,6 @@ async function viewerRegistrations(contract, tournamentId, offset, limit) {
1138
1103
  };
1139
1104
  }, contract.address);
1140
1105
  }
1141
- async function viewerRegistrationsByOwner(contract, tournamentId, owner, offset, limit) {
1142
- return wrapRpcCall(async () => {
1143
- const result = await contract.call("tournament_registrations_by_owner", [tournamentId, owner, offset, limit]);
1144
- const obj = result;
1145
- const entries = obj.entries ?? [];
1146
- const total = Number(obj.total ?? 0);
1147
- return {
1148
- data: entries.map((e) => parseRegistration(e, tournamentId)),
1149
- total,
1150
- limit,
1151
- offset
1152
- };
1153
- }, contract.address);
1154
- }
1155
1106
  async function viewerRegistrationsByTokenIds(contract, tournamentId, tokenIds, offset, limit) {
1156
1107
  return wrapRpcCall(async () => {
1157
1108
  const result = await contract.call("tournament_registrations_by_token_ids", [tournamentId, tokenIds, offset, limit]);
@@ -1197,12 +1148,6 @@ async function viewerRewardClaims(contract, tournamentId, offset, limit) {
1197
1148
  };
1198
1149
  }, contract.address);
1199
1150
  }
1200
- async function viewerPlayerTournaments(contract, playerAddress, offset, limit) {
1201
- return wrapRpcCall(async () => {
1202
- const result = await contract.call("player_tournaments", [playerAddress, offset, limit]);
1203
- return parseFilterResult(result);
1204
- }, contract.address);
1205
- }
1206
1151
 
1207
1152
  // src/rpc/abis/budokanViewer.json
1208
1153
  var budokanViewer_default = [
@@ -4510,9 +4455,6 @@ var BudokanClient = class {
4510
4455
  const contract = await this.getViewerContract();
4511
4456
  const offset = params?.offset ?? 0;
4512
4457
  const limit = params?.limit ?? 20;
4513
- if (params?.playerAddress) {
4514
- return viewerRegistrationsByOwner(contract, tournamentId, params.playerAddress, offset, limit);
4515
- }
4516
4458
  if (params?.gameTokenIds?.length) {
4517
4459
  return viewerRegistrationsByTokenIds(contract, tournamentId, params.gameTokenIds, offset, limit);
4518
4460
  }
@@ -4545,43 +4487,6 @@ var BudokanClient = class {
4545
4487
  this.connectionStatus
4546
4488
  );
4547
4489
  }
4548
- // ---- Player Queries (API-only, no on-chain equivalent) ----
4549
- /**
4550
- * Fetch tournaments that a player has registered for.
4551
- * Supports RPC fallback via viewer contract.
4552
- */
4553
- async getPlayerTournaments(address, params) {
4554
- const rpcFallback = async () => {
4555
- const contract = await this.getViewerContract();
4556
- const offset = params?.offset ?? 0;
4557
- const limit = params?.limit ?? 20;
4558
- const filterResult = await viewerPlayerTournaments(contract, address, offset, limit);
4559
- let data = [];
4560
- if (filterResult.tournamentIds.length > 0) {
4561
- const tournaments = await viewerTournamentsBatch(contract, filterResult.tournamentIds);
4562
- data = tournaments.map((t) => ({
4563
- ...t,
4564
- tournamentId: t.id
4565
- }));
4566
- }
4567
- return { data, total: filterResult.total, limit, offset };
4568
- };
4569
- if (this.resolvedConfig.primarySource === "rpc") {
4570
- return rpcFallback();
4571
- }
4572
- return withFallback(
4573
- () => getPlayerTournaments(this.resolvedConfig.apiBaseUrl, address, params, this.apiCtx),
4574
- rpcFallback,
4575
- this.connectionStatus
4576
- );
4577
- }
4578
- /**
4579
- * Fetch stats for a player.
4580
- * API-only — no RPC fallback available.
4581
- */
4582
- async getPlayerStats(address) {
4583
- return getPlayerStats(this.resolvedConfig.apiBaseUrl, address, this.apiCtx);
4584
- }
4585
4490
  // ---- Game Queries ----
4586
4491
  /**
4587
4492
  * Fetch tournaments for a specific game.
@@ -4847,30 +4752,6 @@ function useTournamentCount(phase) {
4847
4752
  }, [fetch2]);
4848
4753
  return { count, loading, error, refetch: fetch2 };
4849
4754
  }
4850
- function usePlayerTournamentCount(address, phase) {
4851
- const client = useBudokanClient();
4852
- const [count, setCount] = useState(null);
4853
- const [loading, setLoading] = useState(!!address);
4854
- const [error, setError] = useState(null);
4855
- useResetOnClient(client, setCount, setError);
4856
- const fetch2 = useCallback(async () => {
4857
- if (!address) return;
4858
- setLoading(true);
4859
- setError(null);
4860
- try {
4861
- const result = await client.getPlayerTournaments(address, { phase, limit: 1 });
4862
- setCount(result.total ?? 0);
4863
- } catch (e) {
4864
- setError(e);
4865
- } finally {
4866
- setLoading(false);
4867
- }
4868
- }, [client, address, phase]);
4869
- useEffect(() => {
4870
- fetch2();
4871
- }, [fetch2]);
4872
- return { count, loading, error, refetch: fetch2 };
4873
- }
4874
4755
  function useLeaderboard(tournamentId) {
4875
4756
  const client = useBudokanClient();
4876
4757
  const [leaderboard, setLeaderboard] = useState(null);
@@ -4920,84 +4801,157 @@ function useRegistrations(tournamentId, params) {
4920
4801
  }, [fetch2]);
4921
4802
  return { registrations, loading, error, refetch: fetch2 };
4922
4803
  }
4923
- function usePlayer(address, params) {
4804
+ var MAX_OWNED_TOKENS = 1e3;
4805
+ var emptyPage = (limit, offset) => ({
4806
+ data: [],
4807
+ total: 0,
4808
+ limit,
4809
+ offset
4810
+ });
4811
+ function useOwnedTournamentIds(owner, contextId) {
4924
4812
  const client = useBudokanClient();
4925
- const [tournaments, setTournaments] = useState(null);
4926
- const [stats, setStats] = useState(null);
4927
- const [loading, setLoading] = useState(!!address);
4928
- const [error, setError] = useState(null);
4929
- useResetOnClient(client, setTournaments, setStats, setError);
4930
- const paramsKey = JSON.stringify(params);
4931
- const fetch2 = useCallback(async () => {
4932
- if (!address) return;
4933
- setLoading(true);
4934
- setError(null);
4935
- try {
4936
- const [tournamentsResult, statsResult] = await Promise.all([
4937
- client.getPlayerTournaments(address, params),
4938
- client.getPlayerStats(address)
4939
- ]);
4940
- setTournaments(tournamentsResult);
4941
- setStats(statsResult);
4942
- } catch (e) {
4943
- setError(e);
4944
- } finally {
4945
- setLoading(false);
4813
+ const budokanAddress = client.clientConfig.budokanAddress;
4814
+ const enabled = !!owner && !!budokanAddress;
4815
+ const { data, isLoading } = useTokens(
4816
+ enabled ? {
4817
+ owner,
4818
+ minterAddress: budokanAddress,
4819
+ hasContext: true,
4820
+ ...{},
4821
+ limit: MAX_OWNED_TOKENS
4822
+ } : void 0
4823
+ );
4824
+ const tournamentIds = useMemo(() => {
4825
+ if (!enabled) return null;
4826
+ if (!data?.data) return null;
4827
+ const ids = /* @__PURE__ */ new Set();
4828
+ for (const t of data.data) {
4829
+ if (t.contextId) ids.add(String(t.contextId));
4946
4830
  }
4947
- }, [client, address, paramsKey]);
4948
- useEffect(() => {
4949
- fetch2();
4950
- }, [fetch2]);
4951
- return { tournaments, stats, loading, error };
4831
+ return [...ids];
4832
+ }, [enabled, data]);
4833
+ return { tournamentIds, loading: isLoading };
4952
4834
  }
4953
- function usePlayerStats(address) {
4954
- const client = useBudokanClient();
4955
- const [stats, setStats] = useState(null);
4956
- const [loading, setLoading] = useState(!!address);
4957
- const [error, setError] = useState(null);
4958
- useResetOnClient(client, setStats, setError);
4959
- const fetch2 = useCallback(async () => {
4960
- if (!address) return;
4961
- setLoading(true);
4962
- setError(null);
4963
- try {
4964
- const result = await client.getPlayerStats(address);
4965
- setStats(result);
4966
- } catch (e) {
4967
- setError(e);
4968
- } finally {
4969
- setLoading(false);
4835
+ function useTournamentsByOwner(owner, params) {
4836
+ const { tournamentIds, loading: tokensLoading } = useOwnedTournamentIds(owner);
4837
+ const inner = useTournaments(
4838
+ tournamentIds && tournamentIds.length > 0 ? {
4839
+ tournamentIds,
4840
+ phase: params?.phase,
4841
+ limit: params?.limit,
4842
+ offset: params?.offset,
4843
+ sort: params?.sort,
4844
+ includePrizeSummary: params?.includePrizeSummary
4845
+ } : void 0
4846
+ );
4847
+ if (tournamentIds !== null && tournamentIds.length === 0) {
4848
+ return {
4849
+ tournaments: emptyPage(
4850
+ params?.limit ?? 50,
4851
+ params?.offset ?? 0
4852
+ ),
4853
+ loading: false,
4854
+ error: null,
4855
+ refetch: async () => {
4856
+ }
4857
+ };
4858
+ }
4859
+ return {
4860
+ tournaments: inner.tournaments,
4861
+ loading: tokensLoading || inner.loading,
4862
+ error: inner.error,
4863
+ refetch: inner.refetch
4864
+ };
4865
+ }
4866
+ function useTournamentsByOwnerCount(owner, params) {
4867
+ const { tournamentIds, loading: tokensLoading } = useOwnedTournamentIds(owner);
4868
+ const phaseFilter = params?.phase;
4869
+ const filtered = useTournaments(
4870
+ phaseFilter && tournamentIds && tournamentIds.length > 0 ? { tournamentIds, phase: phaseFilter, limit: 1 } : void 0
4871
+ );
4872
+ if (tournamentIds === null) {
4873
+ return {
4874
+ count: null,
4875
+ loading: tokensLoading,
4876
+ error: null,
4877
+ refetch: async () => {
4878
+ }
4879
+ };
4880
+ }
4881
+ if (tournamentIds.length === 0) {
4882
+ return {
4883
+ count: 0,
4884
+ loading: false,
4885
+ error: null,
4886
+ refetch: async () => {
4887
+ }
4888
+ };
4889
+ }
4890
+ if (!phaseFilter) {
4891
+ return {
4892
+ count: tournamentIds.length,
4893
+ loading: false,
4894
+ error: null,
4895
+ refetch: async () => {
4896
+ }
4897
+ };
4898
+ }
4899
+ return {
4900
+ count: filtered.tournaments?.total ?? null,
4901
+ loading: filtered.loading,
4902
+ error: filtered.error,
4903
+ refetch: async () => {
4970
4904
  }
4971
- }, [client, address]);
4972
- useEffect(() => {
4973
- fetch2();
4974
- }, [fetch2]);
4975
- return { stats, loading, error, refetch: fetch2 };
4905
+ };
4976
4906
  }
4977
- function usePlayerTournaments(address, params) {
4907
+ function useRegistrationsByOwner(tournamentId, owner, params) {
4978
4908
  const client = useBudokanClient();
4979
- const [tournaments, setTournaments] = useState(null);
4980
- const [loading, setLoading] = useState(!!address);
4981
- const [error, setError] = useState(null);
4982
- useResetOnClient(client, setTournaments, setError);
4983
- const paramsKey = JSON.stringify(params);
4984
- const fetch2 = useCallback(async () => {
4985
- if (!address) return;
4986
- setLoading(true);
4987
- setError(null);
4988
- try {
4989
- const result = await client.getPlayerTournaments(address, params);
4990
- setTournaments(result);
4991
- } catch (e) {
4992
- setError(e);
4993
- } finally {
4994
- setLoading(false);
4909
+ const budokanAddress = client.clientConfig.budokanAddress;
4910
+ const contextId = tournamentId ? Number(tournamentId) : void 0;
4911
+ const enabled = !!owner && !!budokanAddress && tournamentId != null && contextId !== void 0;
4912
+ const { data: tokensResult, isLoading: tokensLoading } = useTokens(
4913
+ enabled ? {
4914
+ owner,
4915
+ minterAddress: budokanAddress,
4916
+ contextId,
4917
+ limit: MAX_OWNED_TOKENS
4918
+ } : void 0
4919
+ );
4920
+ const ownedGameTokenIds = useMemo(() => {
4921
+ if (!enabled) return null;
4922
+ if (!tokensResult?.data) return null;
4923
+ const ids = [];
4924
+ for (const t of tokensResult.data) {
4925
+ if (t.tokenId == null) continue;
4926
+ try {
4927
+ ids.push(BigInt(String(t.tokenId)).toString());
4928
+ } catch {
4929
+ }
4995
4930
  }
4996
- }, [client, address, paramsKey]);
4997
- useEffect(() => {
4998
- fetch2();
4999
- }, [fetch2]);
5000
- return { tournaments, loading, error, refetch: fetch2 };
4931
+ return ids;
4932
+ }, [enabled, tokensResult]);
4933
+ const inner = useRegistrations(
4934
+ ownedGameTokenIds && ownedGameTokenIds.length > 0 ? tournamentId : void 0,
4935
+ ownedGameTokenIds && ownedGameTokenIds.length > 0 ? { ...params, gameTokenIds: ownedGameTokenIds } : void 0
4936
+ );
4937
+ if (ownedGameTokenIds !== null && ownedGameTokenIds.length === 0) {
4938
+ return {
4939
+ registrations: emptyPage(
4940
+ params?.limit ?? 50,
4941
+ params?.offset ?? 0
4942
+ ),
4943
+ loading: false,
4944
+ error: null,
4945
+ refetch: async () => {
4946
+ }
4947
+ };
4948
+ }
4949
+ return {
4950
+ registrations: inner.registrations,
4951
+ loading: tokensLoading || inner.loading,
4952
+ error: inner.error,
4953
+ refetch: inner.refetch
4954
+ };
5001
4955
  }
5002
4956
  function useRewardClaims(tournamentId, params) {
5003
4957
  const client = useBudokanClient();
@@ -5212,6 +5166,6 @@ function useConnectionStatus() {
5212
5166
  return { isConnected, datasourceMode };
5213
5167
  }
5214
5168
 
5215
- export { BudokanProvider, useActivityStats, useBudokanClient, useConnectionStatus, useLeaderboard, usePlayer, usePlayerStats, usePlayerTournamentCount, usePlayerTournaments, usePrizeAggregation, usePrizeStats, usePrizes, useQualifications, useRegistrations, useRewardClaims, useRewardClaimsSummary, useSubscription, useTournament, useTournamentCount, useTournaments };
5169
+ export { BudokanProvider, useActivityStats, useBudokanClient, useConnectionStatus, useLeaderboard, usePrizeAggregation, usePrizeStats, usePrizes, useQualifications, useRegistrations, useRegistrationsByOwner, useRewardClaims, useRewardClaimsSummary, useSubscription, useTournament, useTournamentCount, useTournaments, useTournamentsByOwner, useTournamentsByOwnerCount };
5216
5170
  //# sourceMappingURL=react.js.map
5217
5171
  //# sourceMappingURL=react.js.map