@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/dist/index.cjs CHANGED
@@ -213,12 +213,8 @@ function camelToSnake(obj) {
213
213
  // src/api/tournaments.ts
214
214
  function normalizeTournament(raw) {
215
215
  const t = snakeToCamel(raw);
216
- if (t.id && !t.tournamentId) {
217
- t.tournamentId = t.id;
218
- } else if (t.tournamentId && !t.id) {
219
- t.id = t.tournamentId;
220
- }
221
- return t;
216
+ const id = t.id ?? t.tournamentId;
217
+ return { ...t, id, tournamentId: id };
222
218
  }
223
219
  function fetchOpts(ctx) {
224
220
  return {
@@ -351,11 +347,12 @@ async function getPlayerTournaments(baseUrl, address, params, ctx) {
351
347
  game_token_ids: params?.gameTokenIds?.join(",")
352
348
  });
353
349
  const result = await apiFetch(`${baseUrl}/players/${normalized}/tournaments${qs}`, fetchOpts2(ctx));
350
+ const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
354
351
  return {
355
352
  data: result.data.map((item) => snakeToCamel(item)),
356
- total: result.pagination?.total ?? result.total,
357
- limit: result.pagination?.limit ?? result.limit,
358
- offset: result.pagination?.offset ?? result.offset
353
+ total,
354
+ limit: resLimit,
355
+ offset: resOffset
359
356
  };
360
357
  }
361
358
  async function getPlayerStats(baseUrl, address, ctx) {
@@ -384,11 +381,12 @@ async function getGameTournaments(baseUrl, gameAddress, params, ctx) {
384
381
  offset: params?.offset
385
382
  });
386
383
  const result = await apiFetch(`${baseUrl}/games/${normalized}/tournaments${qs}`, fetchOpts3(ctx));
384
+ const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
387
385
  return {
388
386
  data: result.data.map((item) => snakeToCamel(item)),
389
- total: result.pagination?.total ?? result.total,
390
- limit: result.pagination?.limit ?? result.limit,
391
- offset: result.pagination?.offset ?? result.offset
387
+ total,
388
+ limit: resLimit,
389
+ offset: resOffset
392
390
  };
393
391
  }
394
392
  async function getGameStats(baseUrl, gameAddress, ctx) {
@@ -417,11 +415,12 @@ async function getActivity(baseUrl, params, ctx) {
417
415
  offset: params?.offset
418
416
  });
419
417
  const result = await apiFetch(`${baseUrl}/activity${qs}`, fetchOpts4(ctx));
418
+ const { total, limit: resLimit, offset: resOffset } = extractPagination(result, { limit: params?.limit, offset: params?.offset });
420
419
  return {
421
420
  data: result.data.map((item) => snakeToCamel(item)),
422
- total: result.pagination?.total ?? result.total,
423
- limit: result.pagination?.limit ?? result.limit,
424
- offset: result.pagination?.offset ?? result.offset
421
+ total,
422
+ limit: resLimit,
423
+ offset: resOffset
425
424
  };
426
425
  }
427
426
  async function getActivityStats(baseUrl, ctx) {
@@ -597,19 +596,15 @@ var CHAINS = {
597
596
  rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet/rpc/v0_10",
598
597
  apiBaseUrl: "https://budokan-api-production.up.railway.app",
599
598
  wsUrl: "wss://budokan-api-production.up.railway.app/ws",
600
- budokanAddress: "",
601
- // TODO: set after mainnet deployment
602
- viewerAddress: ""
603
- // TODO: set after mainnet deployment
599
+ budokanAddress: "0x06137ee50f57d08e1d0d758045e45982e2f5ef4826091ed4db136e7afbafecce",
600
+ viewerAddress: "0x075d1b9f1a9751e6b8f8b5a4ca8e721f10c58d87607e703cda062e512a434443"
604
601
  },
605
602
  sepolia: {
606
603
  rpcUrl: "https://starknet-sepolia.public.blastapi.io",
607
604
  apiBaseUrl: "https://budokan-api-sepolia.up.railway.app",
608
605
  wsUrl: "wss://budokan-api-sepolia.up.railway.app/ws",
609
- budokanAddress: "",
610
- // TODO: set after sepolia deployment
611
- viewerAddress: ""
612
- // TODO: set after sepolia deployment
606
+ budokanAddress: "0x0072a26c29ba5021508bbbb8487663a2a536b8a926acf388d3d772961bd063e0",
607
+ viewerAddress: "0x06bef644110a02c1b075b539953c707cd03b4bb32b42f5f1b0b0090b5139529f"
613
608
  }
614
609
  };
615
610
  function getChainConfig(chain) {
@@ -789,7 +784,6 @@ async function withFallback(primary, fallback, health) {
789
784
 
790
785
  // src/rpc/provider.ts
791
786
  var starknetModule = null;
792
- var useObjectConstructor = null;
793
787
  async function getStarknet() {
794
788
  if (!starknetModule) {
795
789
  starknetModule = await import('starknet');
@@ -807,30 +801,7 @@ async function createContract(abi, address, provider) {
807
801
  resolvedAbi = abi.default;
808
802
  }
809
803
  const starknet = await getStarknet();
810
- const StarknetContract = starknet.Contract;
811
- if (useObjectConstructor === null) {
812
- try {
813
- const contract = new StarknetContract({
814
- abi: resolvedAbi,
815
- address,
816
- providerOrAccount: provider
817
- });
818
- useObjectConstructor = true;
819
- return contract;
820
- } catch {
821
- useObjectConstructor = false;
822
- return new StarknetContract(resolvedAbi, address, provider);
823
- }
824
- }
825
- if (useObjectConstructor) {
826
- return new StarknetContract({
827
- abi: resolvedAbi,
828
- address,
829
- providerOrAccount: provider
830
- });
831
- } else {
832
- return new StarknetContract(resolvedAbi, address, provider);
833
- }
804
+ return new starknet.Contract({ abi: resolvedAbi, address, providerOrAccount: provider });
834
805
  }
835
806
  function wrapRpcCall(fn, contractAddress) {
836
807
  return fn().catch((error) => {
@@ -878,16 +849,22 @@ function decodeByteArray(value) {
878
849
  }
879
850
  return result;
880
851
  }
852
+ var PHASE_VARIANTS = ["Scheduled", "Registration", "Staging", "Live", "Submission", "Finalized"];
853
+ var PHASE_NAME_MAP = {
854
+ scheduled: "Scheduled",
855
+ registration: "Registration",
856
+ staging: "Staging",
857
+ live: "Live",
858
+ submission: "Submission",
859
+ finalized: "Finalized"
860
+ };
881
861
  function phaseToRpcArg(phase) {
882
- const map = {
883
- scheduled: "Scheduled",
884
- registration: "Registration",
885
- staging: "Staging",
886
- live: "Live",
887
- submission: "Submission",
888
- finalized: "Finalized"
889
- };
890
- return { [map[phase]]: {} };
862
+ const activeVariant = PHASE_NAME_MAP[phase];
863
+ const variants = {};
864
+ for (const v of PHASE_VARIANTS) {
865
+ variants[v] = v === activeVariant ? {} : void 0;
866
+ }
867
+ return new starknet.CairoCustomEnum(variants);
891
868
  }
892
869
  function parseTournament(raw, entryCount) {
893
870
  const obj = raw;
@@ -905,11 +882,16 @@ function parseTournament(raw, entryCount) {
905
882
  const gameEndDelay = Number(sched?.game_end_delay ?? 0);
906
883
  const submissionDuration = Number(sched?.submission_duration ?? 0);
907
884
  const createdAtStr = String(createdAt);
908
- const registrationStartTime = String(createdAt + registrationStartDelay);
909
- const registrationEndTime = String(createdAt + registrationEndDelay);
910
- const gameStartTime = String(createdAt + gameStartDelay);
911
- const gameEndTime = String(createdAt + gameEndDelay);
912
- const submissionEndTime = String(createdAt + gameEndDelay + submissionDuration);
885
+ const regStart = createdAt + registrationStartDelay;
886
+ const regEnd = regStart + registrationEndDelay;
887
+ const gameStart = createdAt + gameStartDelay;
888
+ const gameEnd = gameStart + gameEndDelay;
889
+ const subEnd = gameEnd + submissionDuration;
890
+ const registrationStartTime = String(regStart);
891
+ const registrationEndTime = String(regEnd);
892
+ const gameStartTime = String(gameStart);
893
+ const gameEndTime = String(gameEnd);
894
+ const submissionEndTime = String(subEnd);
913
895
  const gc = obj.game_config;
914
896
  const gameAddress = gc ? starknet.num.toHex(gc.game_address) : "";
915
897
  const settingsId = Number(gc?.settings_id ?? 0);
@@ -938,7 +920,7 @@ function parseTournament(raw, entryCount) {
938
920
  distributionCount: Number(ef.distribution_count ?? 0)
939
921
  };
940
922
  }
941
- const entryRequirement = parseOption(obj.entry_requirement) ?? null;
923
+ const entryRequirement = parseOption(obj.entry_requirement);
942
924
  const hasEntryRequirement = entryRequirement !== null;
943
925
  return {
944
926
  id,
@@ -1028,35 +1010,30 @@ function parsePrize(raw) {
1028
1010
  let distributionCount = null;
1029
1011
  let payoutPosition = 0;
1030
1012
  if (tokenTypeData) {
1031
- if ("erc20" in tokenTypeData) {
1032
- const erc20 = tokenTypeData.erc20;
1013
+ const activeVariant = typeof tokenTypeData.activeVariant === "function" ? tokenTypeData.activeVariant() : tokenTypeData.erc20 !== void 0 ? "erc20" : tokenTypeData.erc721 !== void 0 ? "erc721" : null;
1014
+ const variantData = tokenTypeData.variant;
1015
+ const unwrap = (name) => variantData?.[name] ?? tokenTypeData[name];
1016
+ if (activeVariant === "erc20") {
1017
+ const erc20 = unwrap("erc20");
1033
1018
  tokenType = "erc20";
1034
- amount = String(erc20.amount ?? "0");
1035
- const dist = erc20.distribution;
1036
- if (dist) {
1037
- distributionType = String(dist.type ?? null);
1038
- distributionWeight = dist.weight != null ? Number(dist.weight) : null;
1039
- }
1040
- distributionCount = erc20.distribution_count != null ? Number(erc20.distribution_count) : null;
1041
- } else if ("erc721" in tokenTypeData) {
1042
- const erc721 = tokenTypeData.erc721;
1043
- tokenType = "erc721";
1044
- tokenId = String(erc721.id ?? "0");
1045
- } else if ("variant" in tokenTypeData) {
1046
- const variant = tokenTypeData.variant?.toLowerCase();
1047
- if (variant === "erc20") {
1048
- tokenType = "erc20";
1049
- amount = String(tokenTypeData.amount ?? "0");
1050
- const dist = tokenTypeData.distribution;
1051
- if (dist) {
1052
- distributionType = String(dist.type ?? null);
1053
- distributionWeight = dist.weight != null ? Number(dist.weight) : null;
1019
+ amount = String(erc20?.amount ?? "0");
1020
+ const distOption = erc20?.distribution;
1021
+ const distInner = distOption?.Some;
1022
+ if (distInner) {
1023
+ const distVariant = distInner.variant ?? distInner;
1024
+ const distType = Object.keys(distVariant).find((k) => distVariant[k] !== void 0);
1025
+ if (distType) {
1026
+ distributionType = distType.toLowerCase();
1027
+ const distValue = distVariant[distType];
1028
+ distributionWeight = distValue != null ? Number(distValue) : null;
1054
1029
  }
1055
- distributionCount = tokenTypeData.distribution_count != null ? Number(tokenTypeData.distribution_count) : null;
1056
- } else if (variant === "erc721") {
1057
- tokenType = "erc721";
1058
- tokenId = String(tokenTypeData.id ?? "0");
1059
1030
  }
1031
+ const countOption = erc20?.distribution_count;
1032
+ distributionCount = countOption?.Some != null ? Number(countOption.Some) : null;
1033
+ } else if (activeVariant === "erc721") {
1034
+ const erc721 = unwrap("erc721");
1035
+ tokenType = "erc721";
1036
+ tokenId = String(erc721?.id ?? "0");
1060
1037
  }
1061
1038
  }
1062
1039
  return {
@@ -1120,9 +1097,24 @@ async function viewerTournamentsByCreator(contract, creator, offset, limit) {
1120
1097
  return parseFilterResult(result);
1121
1098
  }, contract.address);
1122
1099
  }
1100
+ var PHASE_GROUPS = {
1101
+ scheduled: ["scheduled", "registration", "staging"],
1102
+ registration: ["registration"],
1103
+ staging: ["staging"],
1104
+ live: ["live", "submission"],
1105
+ submission: ["submission"],
1106
+ finalized: ["finalized"]
1107
+ };
1123
1108
  async function viewerTournamentsByPhase(contract, phase, offset, limit) {
1109
+ const phases = PHASE_GROUPS[phase];
1110
+ if (phases.length === 1) {
1111
+ return wrapRpcCall(async () => {
1112
+ const result = await contract.call("tournaments_by_phase", [phaseToRpcArg(phase), offset, limit]);
1113
+ return parseFilterResult(result);
1114
+ }, contract.address);
1115
+ }
1124
1116
  return wrapRpcCall(async () => {
1125
- const result = await contract.call("tournaments_by_phase", [phaseToRpcArg(phase), offset, limit]);
1117
+ const result = await contract.call("tournaments_by_phases", [phases.map(phaseToRpcArg), offset, limit]);
1126
1118
  return parseFilterResult(result);
1127
1119
  }, contract.address);
1128
1120
  }
@@ -1164,6 +1156,31 @@ async function viewerPrizes(contract, tournamentId) {
1164
1156
  return result.map(parsePrize);
1165
1157
  }, contract.address);
1166
1158
  }
1159
+ async function viewerRewardClaims(contract, tournamentId, offset, limit) {
1160
+ return wrapRpcCall(async () => {
1161
+ const result = await contract.call("tournament_reward_claims", [tournamentId, offset, limit]);
1162
+ const obj = result;
1163
+ const claims = obj.claims?.map((raw) => {
1164
+ const claim = raw;
1165
+ return {
1166
+ rewardType: claim.reward_type,
1167
+ claimed: Boolean(claim.claimed)
1168
+ };
1169
+ }) ?? [];
1170
+ return {
1171
+ claims,
1172
+ total: Number(obj.total ?? 0),
1173
+ totalClaimed: Number(obj.total_claimed ?? 0),
1174
+ totalUnclaimed: Number(obj.total_unclaimed ?? 0)
1175
+ };
1176
+ }, contract.address);
1177
+ }
1178
+ async function viewerPlayerTournaments(contract, playerAddress, offset, limit) {
1179
+ return wrapRpcCall(async () => {
1180
+ const result = await contract.call("player_tournaments", [playerAddress, offset, limit]);
1181
+ return parseFilterResult(result);
1182
+ }, contract.address);
1183
+ }
1167
1184
 
1168
1185
  // src/rpc/abis/budokanViewer.json
1169
1186
  var budokanViewer_default = [
@@ -1449,16 +1466,6 @@ var budokanViewer_default = [
1449
1466
  }
1450
1467
  ]
1451
1468
  },
1452
- {
1453
- type: "struct",
1454
- name: "core::array::Span::<core::starknet::contract_address::ContractAddress>",
1455
- members: [
1456
- {
1457
- name: "snapshot",
1458
- type: "@core::array::Array::<core::starknet::contract_address::ContractAddress>"
1459
- }
1460
- ]
1461
- },
1462
1469
  {
1463
1470
  type: "struct",
1464
1471
  name: "core::array::Span::<core::felt252>",
@@ -1471,7 +1478,7 @@ var budokanViewer_default = [
1471
1478
  },
1472
1479
  {
1473
1480
  type: "struct",
1474
- name: "interfaces::extension::ExtensionConfig",
1481
+ name: "metagame_extensions_interfaces::extension::ExtensionConfig",
1475
1482
  members: [
1476
1483
  {
1477
1484
  name: "address",
@@ -1491,13 +1498,9 @@ var budokanViewer_default = [
1491
1498
  name: "token",
1492
1499
  type: "core::starknet::contract_address::ContractAddress"
1493
1500
  },
1494
- {
1495
- name: "allowlist",
1496
- type: "core::array::Span::<core::starknet::contract_address::ContractAddress>"
1497
- },
1498
1501
  {
1499
1502
  name: "extension",
1500
- type: "interfaces::extension::ExtensionConfig"
1503
+ type: "metagame_extensions_interfaces::extension::ExtensionConfig"
1501
1504
  }
1502
1505
  ]
1503
1506
  },
@@ -1757,6 +1760,92 @@ var budokanViewer_default = [
1757
1760
  }
1758
1761
  ]
1759
1762
  },
1763
+ {
1764
+ type: "enum",
1765
+ name: "game_components_interfaces::prize::PrizeType",
1766
+ variants: [
1767
+ {
1768
+ name: "Single",
1769
+ type: "core::integer::u64"
1770
+ },
1771
+ {
1772
+ name: "Distributed",
1773
+ type: "(core::integer::u64, core::integer::u32)"
1774
+ }
1775
+ ]
1776
+ },
1777
+ {
1778
+ type: "enum",
1779
+ name: "budokan_interfaces::budokan::EntryFeeRewardType",
1780
+ variants: [
1781
+ {
1782
+ name: "Position",
1783
+ type: "core::integer::u32"
1784
+ },
1785
+ {
1786
+ name: "TournamentCreator",
1787
+ type: "()"
1788
+ },
1789
+ {
1790
+ name: "GameCreator",
1791
+ type: "()"
1792
+ },
1793
+ {
1794
+ name: "Refund",
1795
+ type: "core::felt252"
1796
+ }
1797
+ ]
1798
+ },
1799
+ {
1800
+ type: "enum",
1801
+ name: "budokan_interfaces::budokan::RewardType",
1802
+ variants: [
1803
+ {
1804
+ name: "Prize",
1805
+ type: "game_components_interfaces::prize::PrizeType"
1806
+ },
1807
+ {
1808
+ name: "EntryFee",
1809
+ type: "budokan_interfaces::budokan::EntryFeeRewardType"
1810
+ }
1811
+ ]
1812
+ },
1813
+ {
1814
+ type: "struct",
1815
+ name: "budokan_interfaces::viewer::RewardClaimView",
1816
+ members: [
1817
+ {
1818
+ name: "reward_type",
1819
+ type: "budokan_interfaces::budokan::RewardType"
1820
+ },
1821
+ {
1822
+ name: "claimed",
1823
+ type: "core::bool"
1824
+ }
1825
+ ]
1826
+ },
1827
+ {
1828
+ type: "struct",
1829
+ name: "budokan_interfaces::viewer::RewardClaimResult",
1830
+ members: [
1831
+ {
1832
+ name: "claims",
1833
+ type: "core::array::Array::<budokan_interfaces::viewer::RewardClaimView>"
1834
+ },
1835
+ {
1836
+ name: "total",
1837
+ type: "core::integer::u32"
1838
+ },
1839
+ {
1840
+ name: "total_claimed",
1841
+ type: "core::integer::u32"
1842
+ },
1843
+ {
1844
+ name: "total_unclaimed",
1845
+ type: "core::integer::u32"
1846
+ }
1847
+ ]
1848
+ },
1760
1849
  {
1761
1850
  type: "interface",
1762
1851
  name: "budokan_interfaces::viewer::IBudokanViewer",
@@ -1853,6 +1942,30 @@ var budokanViewer_default = [
1853
1942
  ],
1854
1943
  state_mutability: "view"
1855
1944
  },
1945
+ {
1946
+ type: "function",
1947
+ name: "tournaments_by_phases",
1948
+ inputs: [
1949
+ {
1950
+ name: "phases",
1951
+ type: "core::array::Array::<budokan_interfaces::budokan::Phase>"
1952
+ },
1953
+ {
1954
+ name: "offset",
1955
+ type: "core::integer::u64"
1956
+ },
1957
+ {
1958
+ name: "limit",
1959
+ type: "core::integer::u64"
1960
+ }
1961
+ ],
1962
+ outputs: [
1963
+ {
1964
+ type: "budokan_interfaces::viewer::TournamentFilterResult"
1965
+ }
1966
+ ],
1967
+ state_mutability: "view"
1968
+ },
1856
1969
  {
1857
1970
  type: "function",
1858
1971
  name: "count_tournaments",
@@ -1912,6 +2025,22 @@ var budokanViewer_default = [
1912
2025
  ],
1913
2026
  state_mutability: "view"
1914
2027
  },
2028
+ {
2029
+ type: "function",
2030
+ name: "count_tournaments_by_phases",
2031
+ inputs: [
2032
+ {
2033
+ name: "phases",
2034
+ type: "core::array::Array::<budokan_interfaces::budokan::Phase>"
2035
+ }
2036
+ ],
2037
+ outputs: [
2038
+ {
2039
+ type: "core::integer::u64"
2040
+ }
2041
+ ],
2042
+ state_mutability: "view"
2043
+ },
1915
2044
  {
1916
2045
  type: "function",
1917
2046
  name: "tournament_detail",
@@ -2007,6 +2136,54 @@ var budokanViewer_default = [
2007
2136
  }
2008
2137
  ],
2009
2138
  state_mutability: "view"
2139
+ },
2140
+ {
2141
+ type: "function",
2142
+ name: "tournament_reward_claims",
2143
+ inputs: [
2144
+ {
2145
+ name: "tournament_id",
2146
+ type: "core::integer::u64"
2147
+ },
2148
+ {
2149
+ name: "offset",
2150
+ type: "core::integer::u32"
2151
+ },
2152
+ {
2153
+ name: "limit",
2154
+ type: "core::integer::u32"
2155
+ }
2156
+ ],
2157
+ outputs: [
2158
+ {
2159
+ type: "budokan_interfaces::viewer::RewardClaimResult"
2160
+ }
2161
+ ],
2162
+ state_mutability: "view"
2163
+ },
2164
+ {
2165
+ type: "function",
2166
+ name: "player_tournaments",
2167
+ inputs: [
2168
+ {
2169
+ name: "player_address",
2170
+ type: "core::starknet::contract_address::ContractAddress"
2171
+ },
2172
+ {
2173
+ name: "offset",
2174
+ type: "core::integer::u64"
2175
+ },
2176
+ {
2177
+ name: "limit",
2178
+ type: "core::integer::u64"
2179
+ }
2180
+ ],
2181
+ outputs: [
2182
+ {
2183
+ type: "budokan_interfaces::viewer::TournamentFilterResult"
2184
+ }
2185
+ ],
2186
+ state_mutability: "view"
2010
2187
  }
2011
2188
  ]
2012
2189
  },
@@ -2291,6 +2468,41 @@ var BudokanClient = class {
2291
2468
  let data = [];
2292
2469
  if (filterResult.tournamentIds.length > 0) {
2293
2470
  data = await viewerTournamentsBatch(contract, filterResult.tournamentIds);
2471
+ if (params?.includePrizeSummary) {
2472
+ const prizePromises = data.map(
2473
+ (t) => viewerPrizes(contract, t.id).catch(() => [])
2474
+ );
2475
+ const allPrizes = await Promise.all(prizePromises);
2476
+ data = data.map((t, i) => {
2477
+ const prizes = allPrizes[i];
2478
+ if (prizes.length === 0) return t;
2479
+ const tokenMap = /* @__PURE__ */ new Map();
2480
+ for (const p of prizes) {
2481
+ const key = p.tokenAddress;
2482
+ const existing = tokenMap.get(key);
2483
+ if (existing) {
2484
+ existing.totalAmount += BigInt(p.amount ?? "0");
2485
+ if (p.tokenType === "erc721") existing.nftCount += 1;
2486
+ } else {
2487
+ tokenMap.set(key, {
2488
+ tokenAddress: p.tokenAddress,
2489
+ tokenType: p.tokenType,
2490
+ totalAmount: BigInt(p.amount ?? "0"),
2491
+ nftCount: p.tokenType === "erc721" ? 1 : 0
2492
+ });
2493
+ }
2494
+ }
2495
+ return {
2496
+ ...t,
2497
+ prizeAggregation: Array.from(tokenMap.values()).map((v) => ({
2498
+ tokenAddress: v.tokenAddress,
2499
+ tokenType: v.tokenType,
2500
+ totalAmount: v.totalAmount.toString(),
2501
+ nftCount: v.nftCount
2502
+ }))
2503
+ };
2504
+ });
2505
+ }
2294
2506
  }
2295
2507
  return { data, total: filterResult.total, limit, offset };
2296
2508
  };
@@ -2381,10 +2593,32 @@ var BudokanClient = class {
2381
2593
  // ---- Player Queries (API-only, no on-chain equivalent) ----
2382
2594
  /**
2383
2595
  * Fetch tournaments that a player has registered for.
2384
- * API-only — no RPC fallback available.
2596
+ * Supports RPC fallback via viewer contract.
2385
2597
  */
2386
2598
  async getPlayerTournaments(address, params) {
2387
- return getPlayerTournaments(this.resolvedConfig.apiBaseUrl, address, params, this.apiCtx);
2599
+ const rpcFallback = async () => {
2600
+ const contract = await this.getViewerContract();
2601
+ const offset = params?.offset ?? 0;
2602
+ const limit = params?.limit ?? 20;
2603
+ const filterResult = await viewerPlayerTournaments(contract, address, offset, limit);
2604
+ let data = [];
2605
+ if (filterResult.tournamentIds.length > 0) {
2606
+ const tournaments = await viewerTournamentsBatch(contract, filterResult.tournamentIds);
2607
+ data = tournaments.map((t) => ({
2608
+ ...t,
2609
+ tournamentId: t.id
2610
+ }));
2611
+ }
2612
+ return { data, total: filterResult.total, limit, offset };
2613
+ };
2614
+ if (this.resolvedConfig.primarySource === "rpc") {
2615
+ return rpcFallback();
2616
+ }
2617
+ return withFallback(
2618
+ () => getPlayerTournaments(this.resolvedConfig.apiBaseUrl, address, params, this.apiCtx),
2619
+ rpcFallback,
2620
+ this.connectionStatus
2621
+ );
2388
2622
  }
2389
2623
  /**
2390
2624
  * Fetch stats for a player.
@@ -2426,20 +2660,55 @@ var BudokanClient = class {
2426
2660
  async getGameStats(gameAddress) {
2427
2661
  return getGameStats(this.resolvedConfig.apiBaseUrl, gameAddress, this.apiCtx);
2428
2662
  }
2429
- // ---- Reward Claims & Qualifications (API-only) ----
2663
+ // ---- Reward Claims & Qualifications ----
2430
2664
  /**
2431
2665
  * Fetch reward claims for a tournament.
2432
- * API-only -- no RPC fallback available.
2666
+ * Supports RPC fallback via viewer contract.
2433
2667
  */
2434
2668
  async getTournamentRewardClaims(tournamentId, params) {
2435
- return getTournamentRewardClaims(this.resolvedConfig.apiBaseUrl, tournamentId, params, this.apiCtx);
2669
+ const rpcFallback = async () => {
2670
+ const contract = await this.getViewerContract();
2671
+ const offset = params?.offset ?? 0;
2672
+ const limit = params?.limit ?? 100;
2673
+ const result = await viewerRewardClaims(contract, tournamentId, offset, limit);
2674
+ const data = result.claims.map((c) => ({
2675
+ tournamentId,
2676
+ rewardType: c.rewardType,
2677
+ claimed: c.claimed
2678
+ }));
2679
+ return { data, total: result.total, limit, offset };
2680
+ };
2681
+ if (this.resolvedConfig.primarySource === "rpc") {
2682
+ return rpcFallback();
2683
+ }
2684
+ return withFallback(
2685
+ () => getTournamentRewardClaims(this.resolvedConfig.apiBaseUrl, tournamentId, params, this.apiCtx),
2686
+ rpcFallback,
2687
+ this.connectionStatus
2688
+ );
2436
2689
  }
2437
2690
  /**
2438
2691
  * Fetch reward claims summary for a tournament.
2439
- * API-only -- no RPC fallback available.
2692
+ * Supports RPC fallback via viewer contract.
2440
2693
  */
2441
2694
  async getTournamentRewardClaimsSummary(tournamentId) {
2442
- return getTournamentRewardClaimsSummary(this.resolvedConfig.apiBaseUrl, tournamentId, this.apiCtx);
2695
+ const rpcFallback = async () => {
2696
+ const contract = await this.getViewerContract();
2697
+ const result = await viewerRewardClaims(contract, tournamentId, 0, 0);
2698
+ return {
2699
+ totalPrizes: result.total,
2700
+ totalClaimed: result.totalClaimed,
2701
+ totalUnclaimed: result.totalUnclaimed
2702
+ };
2703
+ };
2704
+ if (this.resolvedConfig.primarySource === "rpc") {
2705
+ return rpcFallback();
2706
+ }
2707
+ return withFallback(
2708
+ () => getTournamentRewardClaimsSummary(this.resolvedConfig.apiBaseUrl, tournamentId, this.apiCtx),
2709
+ rpcFallback,
2710
+ this.connectionStatus
2711
+ );
2443
2712
  }
2444
2713
  /**
2445
2714
  * Fetch qualifications for a tournament.