@provable-games/budokan-sdk 0.1.24 → 0.1.26

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.
@@ -53,6 +53,14 @@ interface Tournament {
53
53
  leaderboardGameMustBeOver: boolean | null;
54
54
  entryFeeToken: string | null;
55
55
  entryFeeAmount: string | null;
56
+ /**
57
+ * Effective protocol-fee rate (basis points) snapshotted for this tournament
58
+ * at creation — the slice of the built-in entry-fee pool routed to the DAO
59
+ * buyback/treasury. `0` when no protocol fee applies. Sourced from the
60
+ * `TournamentCreated` event via the indexer/API; `null` over the RPC/viewer
61
+ * data source (the per-tournament snapshot has no on-chain getter).
62
+ */
63
+ protocolFeeShare: number | null;
56
64
  hasEntryRequirement: boolean | null;
57
65
  schedule: Schedule | null;
58
66
  gameConfig: GameConfig | null;
@@ -70,6 +78,14 @@ interface Tournament {
70
78
  } | null;
71
79
  entryRequirement: EntryRequirement | null;
72
80
  leaderboardConfig: LeaderboardConfig | null;
81
+ /**
82
+ * Lifecycle phase derived from the schedule + on-chain creation time.
83
+ * Populated by `getTournament`/`getTournaments` (computed at read time via
84
+ * `tournamentPhase`); `null` when the creation time is unknown. Because it's
85
+ * time-derived, treat it as a snapshot for the moment it was read — call
86
+ * `tournamentPhase(t)` to re-evaluate later.
87
+ */
88
+ phase: Phase | null;
73
89
  entryCount: number;
74
90
  prizeCount: number;
75
91
  submissionCount: number;
@@ -189,14 +205,40 @@ interface Prize {
189
205
  /** Opaque `Span<felt252>` config; only set when `tokenType === "extension"`. */
190
206
  extensionConfig: string[] | null;
191
207
  }
208
+ type Erc20Prize = Prize & {
209
+ tokenType: "erc20";
210
+ tokenAddress: string;
211
+ amount: string;
212
+ tokenId: null;
213
+ extensionAddress: null;
214
+ extensionConfig: null;
215
+ };
216
+ type Erc721Prize = Prize & {
217
+ tokenType: "erc721";
218
+ tokenAddress: string;
219
+ amount: null;
220
+ tokenId: string;
221
+ extensionAddress: null;
222
+ extensionConfig: null;
223
+ };
224
+ type TokenPrize = Erc20Prize | Erc721Prize;
225
+ type ExtensionPrize = Prize & {
226
+ tokenType: "extension";
227
+ tokenAddress: null;
228
+ amount: null;
229
+ tokenId: null;
230
+ extensionAddress: string;
231
+ extensionConfig: string[] | null;
232
+ };
192
233
  /**
193
- * Discriminator for `RewardClaim.claimKind`. Picks one of the six terminal
234
+ * Discriminator for `RewardClaim.claimKind`. Picks one of the seven terminal
194
235
  * variants of the on-chain `RewardType` enum (Prize::Single, Prize::Distributed,
195
- * EntryFee::Position / TournamentCreator / GameCreator / Refund). The
196
- * variant-specific fields below are populated only for the kinds that carry
197
- * them; the two pure-marker creator kinds leave all four nullable fields null.
236
+ * EntryFee::Position / TournamentCreator / GameCreator / Refund / ProtocolFee).
237
+ * The variant-specific fields below are populated only for the kinds that carry
238
+ * them; the three pure-marker kinds (tournament_creator, game_creator,
239
+ * protocol_fee) leave all four nullable fields null.
198
240
  */
199
- type RewardClaimKind = "prize_single" | "prize_distributed" | "entry_fee_position" | "entry_fee_tournament_creator" | "entry_fee_game_creator" | "entry_fee_refund" | "prize_extension" | "entry_fee_extension";
241
+ type RewardClaimKind = "prize_single" | "prize_distributed" | "entry_fee_position" | "entry_fee_tournament_creator" | "entry_fee_game_creator" | "entry_fee_protocol_fee" | "entry_fee_refund" | "prize_extension" | "entry_fee_extension";
200
242
  interface RewardClaim {
201
243
  tournamentId: string;
202
244
  claimKind: RewardClaimKind;
@@ -341,7 +383,7 @@ declare class ConnectionStatus {
341
383
  * // RPC-only (bypass API entirely)
342
384
  * const client = new BudokanClient({
343
385
  * primarySource: "rpc",
344
- * rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet/rpc/v0_10",
386
+ * rpcUrl: "https://rpc.provable.games/rpc",
345
387
  * viewerAddress: "0x...",
346
388
  * });
347
389
  * ```
@@ -542,4 +584,4 @@ interface PlayerRewards {
542
584
  rewardClaims: RewardClaim[];
543
585
  }
544
586
 
545
- export { 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 PrizeStats as g, type WSEventHandler as h, type BudokanClientConfig as i, ConnectionStatus as j, type ConnectionStatusState as k, type LeaderboardEntry as l, type Phase as m, type PlayerPlacement as n, type PlayerRewards as o, type WSChannel as p, type WSEventMessage as q, type WSMessage as r, type WSSubscribeMessage as s, type WSUnsubscribeMessage as t, createBudokanClient as u };
587
+ export { BudokanClient as B, type ConnectionMode as C, type DataSource as D, type ExtensionPrize as E, 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 PrizeStats as g, type WSEventHandler as h, type TokenPrize as i, type PlayerPlacement as j, type Phase as k, type BudokanClientConfig as l, ConnectionStatus as m, type ConnectionStatusState as n, type Erc20Prize as o, type Erc721Prize as p, type LeaderboardEntry as q, type PlayerRewards as r, type WSChannel as s, type WSEventMessage as t, type WSMessage as u, type WSSubscribeMessage as v, type WSUnsubscribeMessage as w, createBudokanClient as x };
@@ -53,6 +53,14 @@ interface Tournament {
53
53
  leaderboardGameMustBeOver: boolean | null;
54
54
  entryFeeToken: string | null;
55
55
  entryFeeAmount: string | null;
56
+ /**
57
+ * Effective protocol-fee rate (basis points) snapshotted for this tournament
58
+ * at creation — the slice of the built-in entry-fee pool routed to the DAO
59
+ * buyback/treasury. `0` when no protocol fee applies. Sourced from the
60
+ * `TournamentCreated` event via the indexer/API; `null` over the RPC/viewer
61
+ * data source (the per-tournament snapshot has no on-chain getter).
62
+ */
63
+ protocolFeeShare: number | null;
56
64
  hasEntryRequirement: boolean | null;
57
65
  schedule: Schedule | null;
58
66
  gameConfig: GameConfig | null;
@@ -70,6 +78,14 @@ interface Tournament {
70
78
  } | null;
71
79
  entryRequirement: EntryRequirement | null;
72
80
  leaderboardConfig: LeaderboardConfig | null;
81
+ /**
82
+ * Lifecycle phase derived from the schedule + on-chain creation time.
83
+ * Populated by `getTournament`/`getTournaments` (computed at read time via
84
+ * `tournamentPhase`); `null` when the creation time is unknown. Because it's
85
+ * time-derived, treat it as a snapshot for the moment it was read — call
86
+ * `tournamentPhase(t)` to re-evaluate later.
87
+ */
88
+ phase: Phase | null;
73
89
  entryCount: number;
74
90
  prizeCount: number;
75
91
  submissionCount: number;
@@ -189,14 +205,40 @@ interface Prize {
189
205
  /** Opaque `Span<felt252>` config; only set when `tokenType === "extension"`. */
190
206
  extensionConfig: string[] | null;
191
207
  }
208
+ type Erc20Prize = Prize & {
209
+ tokenType: "erc20";
210
+ tokenAddress: string;
211
+ amount: string;
212
+ tokenId: null;
213
+ extensionAddress: null;
214
+ extensionConfig: null;
215
+ };
216
+ type Erc721Prize = Prize & {
217
+ tokenType: "erc721";
218
+ tokenAddress: string;
219
+ amount: null;
220
+ tokenId: string;
221
+ extensionAddress: null;
222
+ extensionConfig: null;
223
+ };
224
+ type TokenPrize = Erc20Prize | Erc721Prize;
225
+ type ExtensionPrize = Prize & {
226
+ tokenType: "extension";
227
+ tokenAddress: null;
228
+ amount: null;
229
+ tokenId: null;
230
+ extensionAddress: string;
231
+ extensionConfig: string[] | null;
232
+ };
192
233
  /**
193
- * Discriminator for `RewardClaim.claimKind`. Picks one of the six terminal
234
+ * Discriminator for `RewardClaim.claimKind`. Picks one of the seven terminal
194
235
  * variants of the on-chain `RewardType` enum (Prize::Single, Prize::Distributed,
195
- * EntryFee::Position / TournamentCreator / GameCreator / Refund). The
196
- * variant-specific fields below are populated only for the kinds that carry
197
- * them; the two pure-marker creator kinds leave all four nullable fields null.
236
+ * EntryFee::Position / TournamentCreator / GameCreator / Refund / ProtocolFee).
237
+ * The variant-specific fields below are populated only for the kinds that carry
238
+ * them; the three pure-marker kinds (tournament_creator, game_creator,
239
+ * protocol_fee) leave all four nullable fields null.
198
240
  */
199
- type RewardClaimKind = "prize_single" | "prize_distributed" | "entry_fee_position" | "entry_fee_tournament_creator" | "entry_fee_game_creator" | "entry_fee_refund" | "prize_extension" | "entry_fee_extension";
241
+ type RewardClaimKind = "prize_single" | "prize_distributed" | "entry_fee_position" | "entry_fee_tournament_creator" | "entry_fee_game_creator" | "entry_fee_protocol_fee" | "entry_fee_refund" | "prize_extension" | "entry_fee_extension";
200
242
  interface RewardClaim {
201
243
  tournamentId: string;
202
244
  claimKind: RewardClaimKind;
@@ -341,7 +383,7 @@ declare class ConnectionStatus {
341
383
  * // RPC-only (bypass API entirely)
342
384
  * const client = new BudokanClient({
343
385
  * primarySource: "rpc",
344
- * rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet/rpc/v0_10",
386
+ * rpcUrl: "https://rpc.provable.games/rpc",
345
387
  * viewerAddress: "0x...",
346
388
  * });
347
389
  * ```
@@ -542,4 +584,4 @@ interface PlayerRewards {
542
584
  rewardClaims: RewardClaim[];
543
585
  }
544
586
 
545
- export { 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 PrizeStats as g, type WSEventHandler as h, type BudokanClientConfig as i, ConnectionStatus as j, type ConnectionStatusState as k, type LeaderboardEntry as l, type Phase as m, type PlayerPlacement as n, type PlayerRewards as o, type WSChannel as p, type WSEventMessage as q, type WSMessage as r, type WSSubscribeMessage as s, type WSUnsubscribeMessage as t, createBudokanClient as u };
587
+ export { BudokanClient as B, type ConnectionMode as C, type DataSource as D, type ExtensionPrize as E, 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 PrizeStats as g, type WSEventHandler as h, type TokenPrize as i, type PlayerPlacement as j, type Phase as k, type BudokanClientConfig as l, ConnectionStatus as m, type ConnectionStatusState as n, type Erc20Prize as o, type Erc721Prize as p, type LeaderboardEntry as q, type PlayerRewards as r, type WSChannel as s, type WSEventMessage as t, type WSMessage as u, type WSSubscribeMessage as v, type WSUnsubscribeMessage as w, createBudokanClient as x };
package/dist/react.cjs CHANGED
@@ -199,11 +199,37 @@ function snakeToCamel(obj) {
199
199
  return obj;
200
200
  }
201
201
 
202
+ // src/phase/index.ts
203
+ function tournamentPhase(t, nowSeconds) {
204
+ const createdAt = Number(t.createdAtOnchain ?? NaN);
205
+ if (!Number.isFinite(createdAt)) return null;
206
+ const regStartDelay = Number(t.registrationStartDelay ?? t.schedule?.registrationStartDelay ?? 0);
207
+ const regEndDelay = Number(t.registrationEndDelay ?? t.schedule?.registrationEndDelay ?? 0);
208
+ const gameStartDelay = Number(t.gameStartDelay ?? t.schedule?.gameStartDelay ?? 0);
209
+ const gameEndDelay = Number(t.gameEndDelay ?? t.schedule?.gameEndDelay ?? 0);
210
+ const submissionDuration = Number(t.submissionDuration ?? t.schedule?.submissionDuration ?? 0);
211
+ const now = Math.floor(Date.now() / 1e3);
212
+ const hasReg = regStartDelay > 0 || regEndDelay > 0;
213
+ const regStart = createdAt + regStartDelay;
214
+ const regEnd = regStart + regEndDelay;
215
+ const gameStart = createdAt + gameStartDelay;
216
+ const gameEnd = gameStart + gameEndDelay;
217
+ const subEnd = gameEnd + submissionDuration;
218
+ if (hasReg && now < regStart) return "scheduled";
219
+ if (hasReg && now < regEnd) return "registration";
220
+ if (now < gameStart) return "staging";
221
+ if (now < gameEnd) return "live";
222
+ if (now < subEnd) return "submission";
223
+ return "finalized";
224
+ }
225
+
202
226
  // src/api/tournaments.ts
203
227
  function normalizeTournament(raw) {
204
228
  const t = snakeToCamel(raw);
205
229
  const id = t.id ?? t.tournamentId;
206
- return { ...t, id, tournamentId: id };
230
+ const protocolFeeShare = t.protocolFeeShare ?? t.entryFee?.protocolFeeShare ?? null;
231
+ const phase = t.phase ?? tournamentPhase(t);
232
+ return { ...t, id, tournamentId: id, protocolFeeShare, phase };
207
233
  }
208
234
  function fetchOpts(ctx) {
209
235
  return {
@@ -528,7 +554,7 @@ var WSManager = class {
528
554
  // src/chains/constants.ts
529
555
  var CHAINS = {
530
556
  mainnet: {
531
- rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet/rpc/v0_10",
557
+ rpcUrl: "https://rpc.provable.games/rpc",
532
558
  apiBaseUrl: "https://budokan-api-production.up.railway.app",
533
559
  wsUrl: "wss://budokan-api-production.up.railway.app/ws",
534
560
  budokanAddress: "0x0596ced030e74ebc37f33607f07ecd5a62eff22cdc4ae31fe2d724040c1bdc0b",
@@ -807,7 +833,7 @@ function phaseToRpcArg(phase) {
807
833
  }
808
834
  return new starknet.CairoCustomEnum(variants);
809
835
  }
810
- function parseTournament(raw, entryCount) {
836
+ function parseTournament(raw, entryCount, protocolFeeShare = null) {
811
837
  const obj = raw;
812
838
  const id = String(obj.id ?? "0");
813
839
  const createdAt = Number(obj.created_at ?? 0);
@@ -905,6 +931,8 @@ function parseTournament(raw, entryCount) {
905
931
  leaderboardGameMustBeOver: gameMustBeOver,
906
932
  entryFeeToken,
907
933
  entryFeeAmount,
934
+ // Protocol-fee bps snapshot, surfaced by the viewer's TournamentFullState.
935
+ protocolFeeShare,
908
936
  hasEntryRequirement,
909
937
  schedule: {
910
938
  registrationStartDelay,
@@ -926,6 +954,14 @@ function parseTournament(raw, entryCount) {
926
954
  entryFeeExtension,
927
955
  entryRequirement,
928
956
  leaderboardConfig: { ascending, gameMustBeOver },
957
+ phase: tournamentPhase({
958
+ createdAtOnchain: createdAtStr,
959
+ registrationStartDelay,
960
+ registrationEndDelay,
961
+ gameStartDelay,
962
+ gameEndDelay,
963
+ submissionDuration
964
+ }),
929
965
  entryCount,
930
966
  prizeCount: 0,
931
967
  // Not available from viewer
@@ -1071,7 +1107,8 @@ function parseFilterResult(raw) {
1071
1107
  function parseTournamentFullState(raw) {
1072
1108
  const obj = raw;
1073
1109
  const entryCount = Number(obj.entry_count ?? 0);
1074
- return parseTournament(obj.tournament, entryCount);
1110
+ const protocolFeeShare = obj.protocol_fee_bps != null ? Number(obj.protocol_fee_bps) : null;
1111
+ return parseTournament(obj.tournament, entryCount, protocolFeeShare);
1075
1112
  }
1076
1113
  async function viewerTournaments(contract, offset, limit) {
1077
1114
  return wrapRpcCall(async () => {
@@ -1247,6 +1284,9 @@ function translateCairoRewardType(rewardType) {
1247
1284
  if (subVariant === "GameCreator" || subBag?.GameCreator !== void 0) {
1248
1285
  return rewardClaim({ claimKind: "entry_fee_game_creator" });
1249
1286
  }
1287
+ if (subVariant === "ProtocolFee" || subBag?.ProtocolFee !== void 0) {
1288
+ return rewardClaim({ claimKind: "entry_fee_protocol_fee" });
1289
+ }
1250
1290
  if (subVariant === "Refund" || subBag?.Refund !== void 0) {
1251
1291
  return rewardClaim({
1252
1292
  claimKind: "entry_fee_refund",
@@ -1719,6 +1759,10 @@ var budokanViewer_default = [
1719
1759
  {
1720
1760
  name: "phase",
1721
1761
  type: "budokan_interfaces::budokan::Phase"
1762
+ },
1763
+ {
1764
+ name: "protocol_fee_bps",
1765
+ type: "core::integer::u16"
1722
1766
  }
1723
1767
  ]
1724
1768
  },
@@ -1989,6 +2033,10 @@ var budokanViewer_default = [
1989
2033
  {
1990
2034
  name: "Refund",
1991
2035
  type: "core::felt252"
2036
+ },
2037
+ {
2038
+ name: "ProtocolFee",
2039
+ type: "()"
1992
2040
  }
1993
2041
  ]
1994
2042
  },
@@ -3367,6 +3415,10 @@ var budokan_default = [
3367
3415
  {
3368
3416
  name: "Refund",
3369
3417
  type: "core::felt252"
3418
+ },
3419
+ {
3420
+ name: "ProtocolFee",
3421
+ type: "()"
3370
3422
  }
3371
3423
  ]
3372
3424
  },
@@ -4655,6 +4707,11 @@ var budokan_default = [
4655
4707
  name: "entry_requirement",
4656
4708
  type: "core::option::Option::<game_components_interfaces::entry_requirement::EntryRequirement>",
4657
4709
  kind: "data"
4710
+ },
4711
+ {
4712
+ name: "protocol_fee_bps",
4713
+ type: "core::integer::u16",
4714
+ kind: "data"
4658
4715
  }
4659
4716
  ]
4660
4717
  },
@@ -4877,6 +4934,108 @@ var budokan_default = [
4877
4934
  name: "QualificationEntriesUpdated",
4878
4935
  type: "budokan::events::QualificationEntriesUpdated",
4879
4936
  kind: "nested"
4937
+ },
4938
+ {
4939
+ name: "ProtocolFeeBpsUpdated",
4940
+ type: "budokan::events::ProtocolFeeBpsUpdated",
4941
+ kind: "nested"
4942
+ },
4943
+ {
4944
+ name: "ProtocolFeeRecipientUpdated",
4945
+ type: "budokan::events::ProtocolFeeRecipientUpdated",
4946
+ kind: "nested"
4947
+ }
4948
+ ]
4949
+ },
4950
+ {
4951
+ type: "interface",
4952
+ name: "budokan::budokan::Budokan::IBudokanProtocolFeeAdmin",
4953
+ items: [
4954
+ {
4955
+ type: "function",
4956
+ name: "set_protocol_fee_bps",
4957
+ inputs: [
4958
+ {
4959
+ name: "bps",
4960
+ type: "core::integer::u16"
4961
+ }
4962
+ ],
4963
+ outputs: [],
4964
+ state_mutability: "external"
4965
+ },
4966
+ {
4967
+ type: "function",
4968
+ name: "set_protocol_fee_recipient",
4969
+ inputs: [
4970
+ {
4971
+ name: "recipient",
4972
+ type: "core::starknet::contract_address::ContractAddress"
4973
+ }
4974
+ ],
4975
+ outputs: [],
4976
+ state_mutability: "external"
4977
+ },
4978
+ {
4979
+ type: "function",
4980
+ name: "protocol_fee_bps",
4981
+ inputs: [],
4982
+ outputs: [
4983
+ {
4984
+ type: "core::integer::u16"
4985
+ }
4986
+ ],
4987
+ state_mutability: "view"
4988
+ },
4989
+ {
4990
+ type: "function",
4991
+ name: "protocol_fee_recipient",
4992
+ inputs: [],
4993
+ outputs: [
4994
+ {
4995
+ type: "core::starknet::contract_address::ContractAddress"
4996
+ }
4997
+ ],
4998
+ state_mutability: "view"
4999
+ },
5000
+ {
5001
+ type: "function",
5002
+ name: "tournament_protocol_fee_bps",
5003
+ inputs: [
5004
+ {
5005
+ name: "tournament_id",
5006
+ type: "core::integer::u64"
5007
+ }
5008
+ ],
5009
+ outputs: [
5010
+ {
5011
+ type: "core::integer::u16"
5012
+ }
5013
+ ],
5014
+ state_mutability: "view"
5015
+ }
5016
+ ]
5017
+ },
5018
+ {
5019
+ type: "event",
5020
+ name: "budokan::events::ProtocolFeeBpsUpdated",
5021
+ kind: "struct",
5022
+ members: [
5023
+ {
5024
+ name: "bps",
5025
+ type: "core::integer::u16",
5026
+ kind: "data"
5027
+ }
5028
+ ]
5029
+ },
5030
+ {
5031
+ type: "event",
5032
+ name: "budokan::events::ProtocolFeeRecipientUpdated",
5033
+ kind: "struct",
5034
+ members: [
5035
+ {
5036
+ name: "recipient",
5037
+ type: "core::starknet::contract_address::ContractAddress",
5038
+ kind: "key"
4880
5039
  }
4881
5040
  ]
4882
5041
  }