@provable-games/budokan-sdk 0.1.21 → 0.1.23

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.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { i as BudokanClientConfig, B as BudokanClient, T as Tournament, b as PaginatedResult, e as TournamentListParams, m as Phase, l as LeaderboardEntry, R as Registration, c as RewardClaim, d as RewardClaimSummary, g as PrizeStats, a as Prize, P as PrizeAggregation, Q as QualificationEntry, f as PlatformStats, o as WSEventMessage, n as WSChannel, C as ConnectionMode } from './client-0HDPKrdw.cjs';
3
+ import { i as BudokanClientConfig, B as BudokanClient, T as Tournament, b as PaginatedResult, e as TournamentListParams, m as Phase, l as LeaderboardEntry, R as Registration, c as RewardClaim, d as RewardClaimSummary, g as PrizeStats, a as Prize, P as PrizeAggregation, Q as QualificationEntry, f as PlatformStats, o as PlayerRewards, q as WSEventMessage, p as WSChannel, C as ConnectionMode } from './player-BUynfv7D.cjs';
4
4
  import 'starknet';
5
5
  import '@provable-games/metagame-sdk';
6
6
 
@@ -200,6 +200,49 @@ interface UseActivityStatsResult {
200
200
  */
201
201
  declare function useActivityStats(): UseActivityStatsResult;
202
202
 
203
+ interface UsePlayerRewardsResult {
204
+ rewards: PlayerRewards | null;
205
+ loading: boolean;
206
+ error: Error | null;
207
+ refetch: () => Promise<void>;
208
+ }
209
+ /**
210
+ * Aggregate a player's placement/earnings data across finalized Budokan
211
+ * tournaments they currently hold tokens in.
212
+ *
213
+ * Composition:
214
+ *
215
+ * denshokan useTokens (current ownership)
216
+ * ↓ group by contextId (= tournament id)
217
+ * budokan useTournaments({ tournamentIds })
218
+ * ↓ filter to finalized
219
+ * for each finalized tournament (parallel):
220
+ * budokan getTournamentPrizes — full prize records
221
+ * budokan getTournamentRewardClaims — paginated, all pages
222
+ * denshokan getTokenRanks (bulk) — final ranks for owned tokens
223
+ * ↓ filter ranks to paid positions (max position derived from prizes
224
+ * + entry-fee distribution_count)
225
+ *
226
+ * Per-tournament failures are tolerated: a 5xx on one tournament's prize/
227
+ * claim/rank fetch skips that tournament and continues, rather than
228
+ * failing the whole hook. Failures are logged via `console.warn`.
229
+ *
230
+ * Why source ownership from denshokan: PR #243 dropped
231
+ * `registrations.player_address` because the indexed value goes stale on
232
+ * transfer. The contract keys registrations by token_id only, so the only
233
+ * trustworthy answer to "what tournaments has this wallet placed in" is
234
+ * to ask denshokan who currently holds Budokan-minted tokens.
235
+ *
236
+ * Staleness: the hook only re-fetches when the player's owned token set
237
+ * changes (transfers/new mints) or when the underlying tournament list
238
+ * changes. It does *not* observe time-based finalization transitions on
239
+ * its own — if a tournament's submission window closes while the
240
+ * consumer is mounted, call `refetch()` to pick up the new placement.
241
+ *
242
+ * Pass `undefined` to skip fetching.
243
+ */
244
+ declare function usePlayerRewards(address: string | undefined): UsePlayerRewardsResult;
245
+
203
246
  interface UseSubscriptionResult {
204
247
  lastMessage: WSEventMessage | null;
205
248
  isConnected: boolean;
@@ -223,4 +266,4 @@ declare function useConnectionStatus(): {
223
266
  datasourceMode: ConnectionMode;
224
267
  };
225
268
 
226
- export { BudokanProvider, type BudokanProviderProps, type UseActivityStatsResult, type UseLeaderboardResult, type UsePrizeAggregationResult, type UsePrizeStatsResult, type UsePrizesResult, type UseQualificationsResult, type UseRegistrationsResult, type UseRewardClaimsResult, type UseRewardClaimsSummaryResult, type UseSubscriptionResult, type UseTournamentCountResult, type UseTournamentResult, type UseTournamentsResult, useActivityStats, useBudokanClient, useConnectionStatus, useLeaderboard, usePrizeAggregation, usePrizeStats, usePrizes, useQualifications, useRegistrations, useRegistrationsByOwner, useRewardClaims, useRewardClaimsSummary, useSubscription, useTournament, useTournamentCount, useTournaments, useTournamentsByOwner, useTournamentsByOwnerCount };
269
+ export { BudokanProvider, type BudokanProviderProps, type UseActivityStatsResult, type UseLeaderboardResult, type UsePlayerRewardsResult, type UsePrizeAggregationResult, type UsePrizeStatsResult, type UsePrizesResult, type UseQualificationsResult, type UseRegistrationsResult, type UseRewardClaimsResult, type UseRewardClaimsSummaryResult, type UseSubscriptionResult, type UseTournamentCountResult, type UseTournamentResult, type UseTournamentsResult, useActivityStats, useBudokanClient, useConnectionStatus, useLeaderboard, usePlayerRewards, usePrizeAggregation, usePrizeStats, usePrizes, useQualifications, useRegistrations, useRegistrationsByOwner, useRewardClaims, useRewardClaimsSummary, useSubscription, useTournament, useTournamentCount, useTournaments, useTournamentsByOwner, useTournamentsByOwnerCount };
package/dist/react.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { i as BudokanClientConfig, B as BudokanClient, T as Tournament, b as PaginatedResult, e as TournamentListParams, m as Phase, l as LeaderboardEntry, R as Registration, c as RewardClaim, d as RewardClaimSummary, g as PrizeStats, a as Prize, P as PrizeAggregation, Q as QualificationEntry, f as PlatformStats, o as WSEventMessage, n as WSChannel, C as ConnectionMode } from './client-0HDPKrdw.js';
3
+ import { i as BudokanClientConfig, B as BudokanClient, T as Tournament, b as PaginatedResult, e as TournamentListParams, m as Phase, l as LeaderboardEntry, R as Registration, c as RewardClaim, d as RewardClaimSummary, g as PrizeStats, a as Prize, P as PrizeAggregation, Q as QualificationEntry, f as PlatformStats, o as PlayerRewards, q as WSEventMessage, p as WSChannel, C as ConnectionMode } from './player-BUynfv7D.js';
4
4
  import 'starknet';
5
5
  import '@provable-games/metagame-sdk';
6
6
 
@@ -200,6 +200,49 @@ interface UseActivityStatsResult {
200
200
  */
201
201
  declare function useActivityStats(): UseActivityStatsResult;
202
202
 
203
+ interface UsePlayerRewardsResult {
204
+ rewards: PlayerRewards | null;
205
+ loading: boolean;
206
+ error: Error | null;
207
+ refetch: () => Promise<void>;
208
+ }
209
+ /**
210
+ * Aggregate a player's placement/earnings data across finalized Budokan
211
+ * tournaments they currently hold tokens in.
212
+ *
213
+ * Composition:
214
+ *
215
+ * denshokan useTokens (current ownership)
216
+ * ↓ group by contextId (= tournament id)
217
+ * budokan useTournaments({ tournamentIds })
218
+ * ↓ filter to finalized
219
+ * for each finalized tournament (parallel):
220
+ * budokan getTournamentPrizes — full prize records
221
+ * budokan getTournamentRewardClaims — paginated, all pages
222
+ * denshokan getTokenRanks (bulk) — final ranks for owned tokens
223
+ * ↓ filter ranks to paid positions (max position derived from prizes
224
+ * + entry-fee distribution_count)
225
+ *
226
+ * Per-tournament failures are tolerated: a 5xx on one tournament's prize/
227
+ * claim/rank fetch skips that tournament and continues, rather than
228
+ * failing the whole hook. Failures are logged via `console.warn`.
229
+ *
230
+ * Why source ownership from denshokan: PR #243 dropped
231
+ * `registrations.player_address` because the indexed value goes stale on
232
+ * transfer. The contract keys registrations by token_id only, so the only
233
+ * trustworthy answer to "what tournaments has this wallet placed in" is
234
+ * to ask denshokan who currently holds Budokan-minted tokens.
235
+ *
236
+ * Staleness: the hook only re-fetches when the player's owned token set
237
+ * changes (transfers/new mints) or when the underlying tournament list
238
+ * changes. It does *not* observe time-based finalization transitions on
239
+ * its own — if a tournament's submission window closes while the
240
+ * consumer is mounted, call `refetch()` to pick up the new placement.
241
+ *
242
+ * Pass `undefined` to skip fetching.
243
+ */
244
+ declare function usePlayerRewards(address: string | undefined): UsePlayerRewardsResult;
245
+
203
246
  interface UseSubscriptionResult {
204
247
  lastMessage: WSEventMessage | null;
205
248
  isConnected: boolean;
@@ -223,4 +266,4 @@ declare function useConnectionStatus(): {
223
266
  datasourceMode: ConnectionMode;
224
267
  };
225
268
 
226
- export { BudokanProvider, type BudokanProviderProps, type UseActivityStatsResult, type UseLeaderboardResult, type UsePrizeAggregationResult, type UsePrizeStatsResult, type UsePrizesResult, type UseQualificationsResult, type UseRegistrationsResult, type UseRewardClaimsResult, type UseRewardClaimsSummaryResult, type UseSubscriptionResult, type UseTournamentCountResult, type UseTournamentResult, type UseTournamentsResult, useActivityStats, useBudokanClient, useConnectionStatus, useLeaderboard, usePrizeAggregation, usePrizeStats, usePrizes, useQualifications, useRegistrations, useRegistrationsByOwner, useRewardClaims, useRewardClaimsSummary, useSubscription, useTournament, useTournamentCount, useTournaments, useTournamentsByOwner, useTournamentsByOwnerCount };
269
+ export { BudokanProvider, type BudokanProviderProps, type UseActivityStatsResult, type UseLeaderboardResult, type UsePlayerRewardsResult, type UsePrizeAggregationResult, type UsePrizeStatsResult, type UsePrizesResult, type UseQualificationsResult, type UseRegistrationsResult, type UseRewardClaimsResult, type UseRewardClaimsSummaryResult, type UseSubscriptionResult, type UseTournamentCountResult, type UseTournamentResult, type UseTournamentsResult, useActivityStats, useBudokanClient, useConnectionStatus, useLeaderboard, usePlayerRewards, usePrizeAggregation, usePrizeStats, usePrizes, useQualifications, useRegistrations, useRegistrationsByOwner, useRewardClaims, useRewardClaimsSummary, useSubscription, useTournament, useTournamentCount, useTournaments, useTournamentsByOwner, useTournamentsByOwnerCount };
package/dist/react.js CHANGED
@@ -1,7 +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
+ import { useTokens, useDenshokanClient } from '@provable-games/denshokan-sdk/react';
5
5
 
6
6
  // src/react/context.tsx
7
7
 
@@ -1112,6 +1112,84 @@ async function viewerPrizes(contract, tournamentId) {
1112
1112
  return result.map(parsePrize);
1113
1113
  }, contract.address);
1114
1114
  }
1115
+ function translateCairoRewardType(rewardType) {
1116
+ if (!rewardType || typeof rewardType !== "object") {
1117
+ throw new Error(`Unexpected RewardType payload: ${JSON.stringify(rewardType)}`);
1118
+ }
1119
+ const rt = rewardType;
1120
+ const outer = typeof rt.activeVariant === "function" ? rt.activeVariant() : null;
1121
+ const innerBag = typeof rt.activeVariant === "function" ? rt.variant : rt;
1122
+ if (outer === "Prize" || innerBag.Prize !== void 0) {
1123
+ const prize = innerBag.Prize;
1124
+ const subVariant = typeof prize?.activeVariant === "function" ? prize.activeVariant() : null;
1125
+ const subBag = typeof prize?.activeVariant === "function" ? prize.variant : prize;
1126
+ if (subVariant === "Single" || subBag?.Single !== void 0) {
1127
+ return {
1128
+ claimKind: "prize_single",
1129
+ prizeId: BigInt(subBag.Single).toString(),
1130
+ payoutIndex: null,
1131
+ position: null,
1132
+ refundTokenId: null
1133
+ };
1134
+ }
1135
+ if (subVariant === "Distributed" || subBag?.Distributed !== void 0) {
1136
+ const distributed = subBag.Distributed;
1137
+ const prizeId = distributed?.["0"] ?? distributed?.[0];
1138
+ const payoutIndex = distributed?.["1"] ?? distributed?.[1];
1139
+ return {
1140
+ claimKind: "prize_distributed",
1141
+ prizeId: BigInt(prizeId).toString(),
1142
+ payoutIndex: Number(payoutIndex),
1143
+ position: null,
1144
+ refundTokenId: null
1145
+ };
1146
+ }
1147
+ }
1148
+ if (outer === "EntryFee" || innerBag.EntryFee !== void 0) {
1149
+ const entryFee = innerBag.EntryFee;
1150
+ const subVariant = typeof entryFee?.activeVariant === "function" ? entryFee.activeVariant() : null;
1151
+ const subBag = typeof entryFee?.activeVariant === "function" ? entryFee.variant : entryFee;
1152
+ if (subVariant === "Position" || subBag?.Position !== void 0) {
1153
+ return {
1154
+ claimKind: "entry_fee_position",
1155
+ prizeId: null,
1156
+ payoutIndex: null,
1157
+ position: Number(subBag.Position),
1158
+ refundTokenId: null
1159
+ };
1160
+ }
1161
+ if (subVariant === "TournamentCreator" || subBag?.TournamentCreator !== void 0) {
1162
+ return {
1163
+ claimKind: "entry_fee_tournament_creator",
1164
+ prizeId: null,
1165
+ payoutIndex: null,
1166
+ position: null,
1167
+ refundTokenId: null
1168
+ };
1169
+ }
1170
+ if (subVariant === "GameCreator" || subBag?.GameCreator !== void 0) {
1171
+ return {
1172
+ claimKind: "entry_fee_game_creator",
1173
+ prizeId: null,
1174
+ payoutIndex: null,
1175
+ position: null,
1176
+ refundTokenId: null
1177
+ };
1178
+ }
1179
+ if (subVariant === "Refund" || subBag?.Refund !== void 0) {
1180
+ return {
1181
+ claimKind: "entry_fee_refund",
1182
+ prizeId: null,
1183
+ payoutIndex: null,
1184
+ position: null,
1185
+ refundTokenId: `0x${BigInt(subBag.Refund).toString(16)}`
1186
+ };
1187
+ }
1188
+ }
1189
+ throw new Error(
1190
+ `Unrecognised on-chain RewardType variant: ${JSON.stringify(rewardType)}`
1191
+ );
1192
+ }
1115
1193
  async function viewerRewardClaims(contract, tournamentId, offset, limit) {
1116
1194
  return wrapRpcCall(async () => {
1117
1195
  const result = await contract.call("tournament_reward_claims", [tournamentId, offset, limit]);
@@ -1119,7 +1197,7 @@ async function viewerRewardClaims(contract, tournamentId, offset, limit) {
1119
1197
  const claims = obj.claims?.map((raw) => {
1120
1198
  const claim = raw;
1121
1199
  return {
1122
- rewardType: claim.reward_type,
1200
+ ...translateCairoRewardType(claim.reward_type),
1123
1201
  claimed: Boolean(claim.claimed)
1124
1202
  };
1125
1203
  }) ?? [];
@@ -4516,8 +4594,7 @@ var BudokanClient = class {
4516
4594
  const result = await viewerRewardClaims(contract, tournamentId, offset, limit);
4517
4595
  const data = result.claims.map((c) => ({
4518
4596
  tournamentId,
4519
- rewardType: c.rewardType,
4520
- claimed: c.claimed
4597
+ ...c
4521
4598
  }));
4522
4599
  return { data, total: result.total, limit, offset };
4523
4600
  };
@@ -4792,7 +4869,6 @@ function useOwnedTournamentIds(owner, contextId) {
4792
4869
  enabled ? {
4793
4870
  owner,
4794
4871
  minterAddress: budokanAddress,
4795
- hasContext: true,
4796
4872
  ...{},
4797
4873
  limit: MAX_OWNED_TOKENS
4798
4874
  } : void 0
@@ -4908,7 +4984,11 @@ function useRegistrationsByOwner(tournamentId, owner, params) {
4908
4984
  }, [enabled, tokensResult]);
4909
4985
  const inner = useRegistrations(
4910
4986
  ownedGameTokenIds && ownedGameTokenIds.length > 0 ? tournamentId : void 0,
4911
- ownedGameTokenIds && ownedGameTokenIds.length > 0 ? { ...params, gameTokenIds: ownedGameTokenIds } : void 0
4987
+ ownedGameTokenIds && ownedGameTokenIds.length > 0 ? {
4988
+ limit: Math.min(ownedGameTokenIds.length, MAX_OWNED_TOKENS),
4989
+ ...params,
4990
+ gameTokenIds: ownedGameTokenIds
4991
+ } : void 0
4912
4992
  );
4913
4993
  if (ownedGameTokenIds !== null && ownedGameTokenIds.length === 0) {
4914
4994
  return {
@@ -5097,6 +5177,200 @@ function useActivityStats() {
5097
5177
  }, [fetch2]);
5098
5178
  return { stats, loading, error, refetch: fetch2 };
5099
5179
  }
5180
+ function usePlayerRewards(address) {
5181
+ const budokan = useBudokanClient();
5182
+ const denshokan = useDenshokanClient();
5183
+ const budokanAddress = budokan.clientConfig.budokanAddress;
5184
+ const [rewards, setRewards] = useState(null);
5185
+ const [aggregating, setAggregating] = useState(false);
5186
+ const [error, setError] = useState(null);
5187
+ useResetOnClient(budokan, setRewards, setError);
5188
+ const tokensEnabled = !!address && !!budokanAddress;
5189
+ const { data: tokensResult, isLoading: tokensLoading } = useTokens(
5190
+ tokensEnabled ? {
5191
+ owner: address,
5192
+ minterAddress: budokanAddress,
5193
+ limit: 1e3
5194
+ } : void 0
5195
+ );
5196
+ const tokensByTournament = useMemo(() => {
5197
+ if (!tokensResult?.data) return null;
5198
+ const map = /* @__PURE__ */ new Map();
5199
+ for (const t of tokensResult.data) {
5200
+ if (t.contextId == null || !t.tokenId) continue;
5201
+ const tid = String(t.contextId);
5202
+ let list = map.get(tid);
5203
+ if (!list) {
5204
+ list = [];
5205
+ map.set(tid, list);
5206
+ }
5207
+ list.push(t.tokenId);
5208
+ }
5209
+ return map;
5210
+ }, [tokensResult]);
5211
+ const tournamentIds = useMemo(
5212
+ () => tokensByTournament ? Array.from(tokensByTournament.keys()) : [],
5213
+ [tokensByTournament]
5214
+ );
5215
+ const { tournaments: tournamentsPage, loading: tournamentsLoading } = useTournaments(
5216
+ tournamentIds.length > 0 ? { tournamentIds, limit: 1e3 } : void 0
5217
+ );
5218
+ const tournamentIdsKey = tournamentIds.join(",");
5219
+ const fetch2 = useCallback(async () => {
5220
+ if (!tokensEnabled) {
5221
+ setRewards(null);
5222
+ return;
5223
+ }
5224
+ if (!tokensByTournament) return;
5225
+ if (tokensByTournament.size === 0) {
5226
+ setRewards(emptyRewards());
5227
+ return;
5228
+ }
5229
+ if (!tournamentsPage?.data) return;
5230
+ const now = Math.floor(Date.now() / 1e3);
5231
+ const finalized = tournamentsPage.data.filter((t) => {
5232
+ const sub = Number(t.submissionEndTime ?? 0);
5233
+ return sub > 0 && sub <= now;
5234
+ });
5235
+ if (finalized.length === 0) {
5236
+ setRewards(emptyRewards());
5237
+ return;
5238
+ }
5239
+ setAggregating(true);
5240
+ setError(null);
5241
+ try {
5242
+ const settled = await Promise.allSettled(
5243
+ finalized.map(async (t) => {
5244
+ const tid = t.id;
5245
+ const tokenIds = tokensByTournament.get(tid) ?? [];
5246
+ if (tokenIds.length === 0) return null;
5247
+ const [prizes, allClaims, ranksResult] = await Promise.all([
5248
+ budokan.getTournamentPrizes(tid),
5249
+ fetchAllRewardClaims(budokan, tid),
5250
+ denshokan.getTokenRanks(tokenIds, {
5251
+ contextId: Number(tid),
5252
+ minterAddress: budokanAddress
5253
+ })
5254
+ ]);
5255
+ let maxPaid = 0;
5256
+ for (const p of prizes) {
5257
+ if ((p.payoutPosition ?? 0) > 0) {
5258
+ maxPaid = Math.max(maxPaid, p.payoutPosition);
5259
+ }
5260
+ if ((p.distributionCount ?? 0) > 0) {
5261
+ maxPaid = Math.max(maxPaid, p.distributionCount);
5262
+ }
5263
+ }
5264
+ const efDistCount = Number(t.entryFee?.distributionCount ?? 0);
5265
+ if (efDistCount > 0) maxPaid = Math.max(maxPaid, efDistCount);
5266
+ if (maxPaid === 0) return null;
5267
+ const placements = ranksResult.data.filter((r) => r.rank > 0 && r.rank <= maxPaid).map((r) => ({
5268
+ tournamentId: tid,
5269
+ tokenId: r.tokenId,
5270
+ position: r.rank,
5271
+ score: String(r.score ?? "0")
5272
+ }));
5273
+ if (placements.length === 0) return null;
5274
+ return {
5275
+ tournament: t,
5276
+ prizes,
5277
+ rewardClaims: allClaims,
5278
+ placements
5279
+ };
5280
+ })
5281
+ );
5282
+ const valid = settled.map((s, i) => {
5283
+ if (s.status === "fulfilled") return s.value;
5284
+ console.warn(
5285
+ `usePlayerRewards: tournament ${finalized[i].id} fetch failed; skipping`,
5286
+ s.reason
5287
+ );
5288
+ return null;
5289
+ }).filter((r) => r !== null);
5290
+ const allPlacements = valid.flatMap(
5291
+ (r) => r.placements
5292
+ );
5293
+ const wins = allPlacements.length;
5294
+ const bestPlacement = wins > 0 ? Math.min(...allPlacements.map((p) => p.position)) : null;
5295
+ const tournamentsList = valid.map((r) => r.tournament);
5296
+ const prizesList = valid.flatMap((r) => r.prizes);
5297
+ const rewardClaimsList = valid.flatMap(
5298
+ (r) => r.rewardClaims
5299
+ );
5300
+ setRewards({
5301
+ wins,
5302
+ bestPlacement,
5303
+ placements: allPlacements,
5304
+ tournaments: tournamentsList,
5305
+ prizes: prizesList,
5306
+ rewardClaims: rewardClaimsList
5307
+ });
5308
+ } catch (e) {
5309
+ setError(e);
5310
+ } finally {
5311
+ setAggregating(false);
5312
+ }
5313
+ }, [
5314
+ tokensEnabled,
5315
+ tokensByTournament,
5316
+ tournamentsPage,
5317
+ tournamentIdsKey,
5318
+ budokan,
5319
+ denshokan,
5320
+ budokanAddress
5321
+ ]);
5322
+ const lastRunRef = useRef("");
5323
+ useEffect(() => {
5324
+ if (!tokensEnabled) {
5325
+ setRewards(null);
5326
+ return;
5327
+ }
5328
+ if (!tokensByTournament || !tournamentsPage?.data) return;
5329
+ const fingerprint = `${address}|${tournamentIdsKey}|${tournamentsPage.data.length}`;
5330
+ if (fingerprint === lastRunRef.current) return;
5331
+ lastRunRef.current = fingerprint;
5332
+ fetch2();
5333
+ }, [
5334
+ address,
5335
+ tokensEnabled,
5336
+ tokensByTournament,
5337
+ tournamentsPage,
5338
+ tournamentIdsKey,
5339
+ fetch2
5340
+ ]);
5341
+ const loading = tokensEnabled && (tokensLoading || tournamentsLoading) || aggregating;
5342
+ return { rewards, loading, error, refetch: fetch2 };
5343
+ }
5344
+ function emptyRewards() {
5345
+ return {
5346
+ wins: 0,
5347
+ bestPlacement: null,
5348
+ placements: [],
5349
+ tournaments: [],
5350
+ prizes: [],
5351
+ rewardClaims: []
5352
+ };
5353
+ }
5354
+ async function fetchAllRewardClaims(client, tournamentId) {
5355
+ const first = await client.getTournamentRewardClaims(tournamentId, {
5356
+ limit: 100
5357
+ });
5358
+ const accumulated = [...first.data];
5359
+ const total = first.total ?? accumulated.length;
5360
+ if (accumulated.length >= total) return accumulated;
5361
+ const pageSize = Math.max(first.data.length, 1);
5362
+ let offset = accumulated.length;
5363
+ while (offset < total) {
5364
+ const next = await client.getTournamentRewardClaims(tournamentId, {
5365
+ limit: pageSize,
5366
+ offset
5367
+ });
5368
+ if (next.data.length === 0) break;
5369
+ accumulated.push(...next.data);
5370
+ offset += next.data.length;
5371
+ }
5372
+ return accumulated;
5373
+ }
5100
5374
  function useSubscription(channels, tournamentIds) {
5101
5375
  const client = useBudokanClient();
5102
5376
  const [lastMessage, setLastMessage] = useState(null);
@@ -5142,6 +5416,6 @@ function useConnectionStatus() {
5142
5416
  return { isConnected, datasourceMode };
5143
5417
  }
5144
5418
 
5145
- export { BudokanProvider, useActivityStats, useBudokanClient, useConnectionStatus, useLeaderboard, usePrizeAggregation, usePrizeStats, usePrizes, useQualifications, useRegistrations, useRegistrationsByOwner, useRewardClaims, useRewardClaimsSummary, useSubscription, useTournament, useTournamentCount, useTournaments, useTournamentsByOwner, useTournamentsByOwnerCount };
5419
+ export { BudokanProvider, useActivityStats, useBudokanClient, useConnectionStatus, useLeaderboard, usePlayerRewards, usePrizeAggregation, usePrizeStats, usePrizes, useQualifications, useRegistrations, useRegistrationsByOwner, useRewardClaims, useRewardClaimsSummary, useSubscription, useTournament, useTournamentCount, useTournaments, useTournamentsByOwner, useTournamentsByOwnerCount };
5146
5420
  //# sourceMappingURL=react.js.map
5147
5421
  //# sourceMappingURL=react.js.map