@provable-games/budokan-sdk 0.1.23 → 0.1.25

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.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { T as Tournament, P as PrizeAggregation, a as Prize, b as PaginatedResult, Q as QualificationEntry, R as Registration, c as RewardClaim, d as RewardClaimSummary, e as TournamentListParams, f as PlatformStats, g as PrizeStats, W as WSSubscribeOptions, h as WSEventHandler } from './player-BUynfv7D.js';
2
- export { B as BudokanClient, i as BudokanClientConfig, C as ConnectionMode, j as ConnectionStatus, k as ConnectionStatusState, D as DataSource, G as GameConfig, L as LeaderboardConfig, l as LeaderboardEntry, m as Phase, n as PlayerPlacement, o as PlayerRewards, S as Schedule, p as WSChannel, q as WSEventMessage, r as WSMessage, s as WSSubscribeMessage, t as WSUnsubscribeMessage, u as createBudokanClient } from './player-BUynfv7D.js';
1
+ import { T as Tournament, P as PrizeAggregation, a as Prize, b as PaginatedResult, Q as QualificationEntry, R as Registration, c as RewardClaim, d as RewardClaimSummary, e as TournamentListParams, f as PlatformStats, g as PrizeStats, W as WSSubscribeOptions, h as WSEventHandler, i as TokenPrize, E as ExtensionPrize$1 } from './player-P6Dd1lNb.js';
2
+ export { B as BudokanClient, j as BudokanClientConfig, C as ConnectionMode, k as ConnectionStatus, l as ConnectionStatusState, D as DataSource, m as Erc20Prize, n as Erc721Prize, G as GameConfig, L as LeaderboardConfig, o as LeaderboardEntry, p as Phase, q as PlayerPlacement, r as PlayerRewards, S as Schedule, s as WSChannel, t as WSEventMessage, u as WSMessage, v as WSSubscribeMessage, w as WSUnsubscribeMessage, x as createBudokanClient } from './player-P6Dd1lNb.js';
3
+ import { ExtensionPrize, PrizeLike, Prize as Prize$1 } from '@provable-games/metagame-sdk';
3
4
  export { EntryFee } from '@provable-games/metagame-sdk';
4
5
  import 'starknet';
5
6
 
@@ -180,6 +181,80 @@ declare function camelToSnake<T>(obj: unknown): T;
180
181
 
181
182
  declare function withRetry<T>(fn: () => Promise<T>, attempts?: number, delay?: number): Promise<T>;
182
183
 
184
+ type MetagameTokenPrize = Prize$1;
185
+ type MetagameExtensionPrize = ExtensionPrize;
186
+ type MetagamePrizeLike = PrizeLike;
187
+ declare function isRawTokenPrize(prize: Prize): prize is TokenPrize;
188
+ declare function isRawExtensionPrize(prize: Prize): prize is ExtensionPrize$1;
189
+ declare function isTokenPrize(prize: Prize): prize is TokenPrize;
190
+ declare function isExtensionPrize(prize: Prize): prize is ExtensionPrize$1;
191
+ /**
192
+ * Returns true when a prize is a valid Budokan token/extension prize and has a
193
+ * hydrated leaderboard position suitable for the metagame prize shape.
194
+ */
195
+ declare function isMetagameAdaptablePrize(prize: Prize): prize is TokenPrize | ExtensionPrize$1;
196
+ /**
197
+ * Returns validated raw token prizes. Extension records are skipped without
198
+ * validation; malformed `erc20`/`erc721` records throw instead of being
199
+ * silently dropped. RPC records with `payoutPosition === 0` are returned here
200
+ * for raw token-prize visibility.
201
+ */
202
+ declare function getRawTokenPrizes(prizes: readonly Prize[]): TokenPrize[];
203
+ /**
204
+ * Returns validated hydrated token prizes. Extension records are skipped
205
+ * without validation, and valid raw token prizes with `payoutPosition === 0`
206
+ * are skipped; malformed `erc20`/`erc721` records throw instead of being
207
+ * silently dropped.
208
+ */
209
+ declare function getTokenPrizes(prizes: readonly Prize[]): TokenPrize[];
210
+ /**
211
+ * Converts a guard-validated Budokan token prize into the Metagame SDK token
212
+ * prize shape. Metagame token prizes do not carry Budokan distribution fields,
213
+ * so distributed ERC20 prizes are represented by their aggregate `amount` at
214
+ * `payoutPosition`; use the original Budokan `Prize` for payout-split math.
215
+ * For ERC721 prizes, metagame-sdk@0.1.13 uses `amount` to carry the token ID.
216
+ * Throws when `payoutPosition` is zero because the RPC path uses zero for
217
+ * unhydrated token-prize positions and metagame positions are leaderboard slots.
218
+ */
219
+ declare function toMetagameTokenPrize(prize: TokenPrize): MetagameTokenPrize;
220
+ /**
221
+ * Converts a guard-validated Budokan extension prize into the Metagame SDK
222
+ * extension-prize shape. Throws when `payoutPosition` is zero because metagame
223
+ * positions are leaderboard slots and the RPC path uses zero for unhydrated
224
+ * prize positions.
225
+ */
226
+ declare function toMetagameExtensionPrize(prize: ExtensionPrize$1): MetagameExtensionPrize;
227
+ /**
228
+ * Converts supported Budokan prize variants into Metagame SDK prize shapes.
229
+ * Throws when a prize has malformed fields or an unhydrated payout position.
230
+ * Raw-but-valid zero-position prizes throw the unhydrated-position error.
231
+ * See `toMetagameTokenPrize` for token prize distribution behavior.
232
+ */
233
+ declare function toMetagamePrize(prize: Prize): MetagamePrizeLike;
234
+ /**
235
+ * Non-throwing metagame adapter. Returns null for malformed prize records and
236
+ * for valid RPC-sourced prizes whose `payoutPosition` is not hydrated yet.
237
+ */
238
+ declare function tryToMetagamePrize(prize: Prize): MetagamePrizeLike | null;
239
+ /**
240
+ * Converts supported Budokan prize variants into Metagame SDK prize shapes.
241
+ * Throws when any prize has malformed fields or an unhydrated payout position.
242
+ * See `toMetagameTokenPrize` for token prize distribution behavior.
243
+ */
244
+ declare function toMetagamePrizes(prizes: readonly Prize[]): MetagamePrizeLike[];
245
+ /**
246
+ * Non-throwing batch metagame adapter. Skips malformed records and valid
247
+ * RPC-sourced prizes whose `payoutPosition` is not hydrated yet.
248
+ */
249
+ declare function tryToMetagamePrizes(prizes: readonly Prize[]): MetagamePrizeLike[];
250
+ /**
251
+ * Converts Budokan token prizes into Metagame SDK token prize shapes. Extension
252
+ * records are skipped without validation. Throws for malformed token records
253
+ * and unhydrated token positions. See `toMetagameTokenPrize` for distribution
254
+ * behavior.
255
+ */
256
+ declare function toMetagameTokenPrizes(prizes: readonly Prize[]): MetagameTokenPrize[];
257
+
183
258
  interface ChainConfig {
184
259
  rpcUrl: string;
185
260
  apiBaseUrl: string;
@@ -189,5 +264,542 @@ interface ChainConfig {
189
264
  }
190
265
  declare const CHAINS: Record<string, ChainConfig>;
191
266
  declare function getChainConfig(chain: string): ChainConfig | undefined;
267
+ /**
268
+ * Voyager block-explorer base URL for the chain. Used to build
269
+ * shareable links for tx hashes and contracts in chat / Discord / CLI
270
+ * surfaces. Unknown chains fall back to mainnet — Voyager 404s
271
+ * gracefully and the caller can still click the link.
272
+ */
273
+ declare function explorerBaseUrl(chain: string): string;
274
+ /** Voyager URL for a transaction hash. */
275
+ declare function explorerTxUrl(chain: string, txHash: string): string;
276
+ /** Voyager URL for a contract / account address. */
277
+ declare function explorerAddressUrl(chain: string, address: string): string;
278
+ /**
279
+ * Canonical budokan.gg URL for a tournament. The `network` query param
280
+ * tells the client which chain to load — important when sharing sepolia
281
+ * tournaments since the site defaults to mainnet.
282
+ */
283
+ declare function tournamentPageUrl(chain: string, tournamentId: string | number | bigint): string;
284
+
285
+ /** Subset of chain identifiers the whitelist covers. */
286
+ type WhitelistChain = "mainnet" | "sepolia";
287
+ interface WhitelistedGame {
288
+ /** Canonical 0x-prefixed, 66-char lowercase contract address. */
289
+ contractAddress: string;
290
+ /** Display name. */
291
+ name: string;
292
+ /** Optional remote logo URL. The SDK never bundles binary assets — host externally. */
293
+ imageUrl?: string;
294
+ /** Game's homepage / landing URL. */
295
+ url?: string;
296
+ /** Direct-play URL template. May include `{tokenId}`. */
297
+ playUrl?: string;
298
+ /** Optional spectator URLs. */
299
+ watchLink?: string;
300
+ replayLink?: string;
301
+ /** True if the game requires a Cartridge Controller to play. */
302
+ controllerOnly?: boolean;
303
+ /** Hide from default listings while keeping the metadata around. */
304
+ disabled?: boolean;
305
+ /** Minimum entry fee floor in USD, used as a UX hint at tournament-create time. */
306
+ minEntryFeeUsd?: number;
307
+ /** Recommended ERC-20 token for entry fee on this chain. */
308
+ defaultEntryFeeToken?: string;
309
+ /** Game-creator share of entry fee (basis-points-style — `5` means 5%). */
310
+ defaultGameFeePercentage?: number;
311
+ /** Approximate gas cost per entry, in USD — UX hint only. */
312
+ averageGasCostUsd?: number;
313
+ /** Some game tokens use animated SVG that needs `<object>` rather than `<img>`. */
314
+ objectImage?: boolean;
315
+ /**
316
+ * Score ordering. `true` = lower-is-better (golf-style), `false` = higher-
317
+ * is-better (points-style). Defaults to false when omitted — most games
318
+ * are points-based.
319
+ */
320
+ leaderboardAscending?: boolean;
321
+ /**
322
+ * Whether the game's score is only valid once the game is in a completed
323
+ * (e.g. dead, finished) state. Tournament-creation UIs hide this question
324
+ * when the property of the game is known. Defaults to false.
325
+ */
326
+ leaderboardGameMustBeOver?: boolean;
327
+ }
328
+ /**
329
+ * Whitelisted games for a chain, sorted by name with disabled entries last.
330
+ *
331
+ * Returns a frozen copy — mutations don't bleed back into the module state.
332
+ */
333
+ declare function getWhitelistedGames(chain: WhitelistChain): WhitelistedGame[];
334
+ /**
335
+ * Look up a single whitelisted game by contract address. Address is normalized
336
+ * before comparison so callers can pass any padding.
337
+ */
338
+ declare function findWhitelistedGame(chain: WhitelistChain, contractAddress: string): WhitelistedGame | undefined;
339
+ /** True if the given game is on the whitelist. */
340
+ declare function isGameWhitelisted(chain: WhitelistChain, contractAddress: string): boolean;
341
+ /**
342
+ * Defaults block — what UI surfaces should pre-fill when the user picks this
343
+ * game. Falls back to per-chain sensible defaults (STRK as fee token, 1% fee,
344
+ * $0.25 minimum) when the game isn't whitelisted, so callers don't have to
345
+ * special-case missing entries.
346
+ */
347
+ interface GameDefaults {
348
+ minEntryFeeUsd: number;
349
+ defaultEntryFeeToken: string;
350
+ defaultGameFeePercentage: number;
351
+ averageGasCostUsd: number | undefined;
352
+ /** Inherited leaderboard ordering (true = lower wins, false = higher wins). */
353
+ leaderboardAscending: boolean;
354
+ /** Inherited "must finish game before submitting" flag. */
355
+ leaderboardGameMustBeOver: boolean;
356
+ }
357
+ declare function getGameDefaults(chain: WhitelistChain, contractAddress: string): GameDefaults;
358
+
359
+ /**
360
+ * Calldata builders for Budokan's on-chain entrypoints.
361
+ *
362
+ * Each builder is a pure function that returns a starknet.js `Call` —
363
+ * `{ contractAddress, entrypoint, calldata }` — without signing or
364
+ * executing anything. Callers pass the returned Call to
365
+ * `account.execute([...])` themselves so this module is decoupled from
366
+ * how an integrator obtains an account (controller, sessions, agent
367
+ * wallets, signing servers).
368
+ *
369
+ * Cairo encoding gotchas this module hides from callers:
370
+ * - Option<T> and custom enums must be wrapped in `CairoOption` /
371
+ * `CairoCustomEnum`. Plain `{ type, variant }` objects look right but
372
+ * CallData.compile treats them as generic structs and serializes the
373
+ * type-name string as a ByteArray — i.e. produces garbage calldata.
374
+ * - `Metadata.description` is a ByteArray (3+ felts). A plain JS
375
+ * string becomes a single felt and the deserializer reverts with
376
+ * "Failed to deserialize param".
377
+ * - Cairo enum variant tags are 0-indexed in declaration order; the
378
+ * manually-built calldata in enter/claim/submit follows this order
379
+ * exactly. References:
380
+ * contracts/packages/interfaces/src/budokan.cairo (RewardType,
381
+ * EntryFeeRewardType, EntryRequirementType, Distribution)
382
+ * game-components/.../prize.cairo (PrizeType)
383
+ *
384
+ * Used today by the Telegram bot in
385
+ * `examples/telegram-controller-bot/`. Any other integration that needs
386
+ * to drive the same contract (a Discord bot, a CLI, agent code) should
387
+ * import from here so we don't fork the encoding logic again.
388
+ */
389
+ interface Call {
390
+ contractAddress: string;
391
+ entrypoint: string;
392
+ calldata: string[];
393
+ }
394
+ /**
395
+ * Shape of the entry-fee distribution. Mirrors the Cairo `Distribution`
396
+ * enum (Linear / Exponential / Uniform / Custom). The integer `weight`
397
+ * is in client units — the encoder scales it ×10 to match the on-chain
398
+ * convention the budokan client uses, so distributions created via this
399
+ * SDK and via budokan.gg render identically.
400
+ */
401
+ type DistributionSpec = {
402
+ kind: "linear";
403
+ weight: number;
404
+ } | {
405
+ kind: "exponential";
406
+ weight: number;
407
+ } | {
408
+ kind: "uniform";
409
+ };
410
+ interface EntryFeeArgs {
411
+ tokenAddress: string;
412
+ /** Raw u128 amount in smallest token units (decimal string). */
413
+ amount: string;
414
+ /** All shares are basis points (0–10000). Sum + leaderboard pool = 10000. */
415
+ tournamentCreatorShare: number;
416
+ gameCreatorShare: number;
417
+ refundShare: number;
418
+ distribution: DistributionSpec;
419
+ /** Number of top placements that share the leaderboard pool. */
420
+ distributionCount: number;
421
+ }
422
+ /**
423
+ * Entry-requirement gating. Two variants on the chain's
424
+ * EntryRequirementType enum:
425
+ * - token: ContractAddress — must own a token from this contract
426
+ * - extension: ExtensionConfig — validator contract + config Span
427
+ *
428
+ * For "extension" callers build the `config` Span<felt252> in the exact
429
+ * felt order the target validator's `add_config` expects (see
430
+ * `src/extensions` for preset builders that produce this for the
431
+ * shared deployed validators).
432
+ */
433
+ type EntryRequirementSpec = {
434
+ kind: "token";
435
+ tokenAddress: string;
436
+ } | {
437
+ kind: "extension";
438
+ address: string;
439
+ config: string[];
440
+ };
441
+ interface EntryRequirementArgs {
442
+ /** Max entries per qualifying token / extension match. */
443
+ entryLimit: number;
444
+ type: EntryRequirementSpec;
445
+ }
446
+ interface EnterTournamentArgs {
447
+ tournamentId: string;
448
+ /**
449
+ * Mint recipient. Encoded as `Option<ContractAddress>` — omit for
450
+ * `None` (the contract defaults the mint to the caller).
451
+ */
452
+ playerAddress?: string;
453
+ /** Optional felt252 short string (≤31 ASCII bytes). Omit → Option::None. */
454
+ playerName?: string;
455
+ /**
456
+ * Third-party qualifier to claim, as `Option<ContractAddress>`. Omit for
457
+ * `None` (caller is the qualifier — the common path). Only needed for
458
+ * sponsor flows against gated tournaments.
459
+ */
460
+ qualifier?: string;
461
+ /**
462
+ * `entry_fee_pay_params` (`Option<Span<felt252>>`). Required only for
463
+ * tournaments with an `EntryFeeKind::Extension` fee — the felts the fee
464
+ * extension expects. Omit for the built-in fee flow (Option::None).
465
+ */
466
+ entryFeePayParams?: string[];
467
+ salt?: number;
468
+ metadataValue?: number;
469
+ }
470
+ interface CreateTournamentArgs {
471
+ creatorRewardsAddress: string;
472
+ /** ≤31 ASCII bytes (felt252 short string). */
473
+ name: string;
474
+ description: string;
475
+ gameAddress: string;
476
+ settingsId: number;
477
+ schedule: {
478
+ registrationStartDelay: number;
479
+ registrationEndDelay: number;
480
+ gameStartDelay: number;
481
+ gameEndDelay: number;
482
+ submissionDuration: number;
483
+ };
484
+ leaderboard: {
485
+ ascending: boolean;
486
+ gameMustBeOver: boolean;
487
+ };
488
+ /** Encoded as Option::Some(EntryFeeKind::BuiltIn(EntryFee)) when set. */
489
+ entryFee?: EntryFeeArgs;
490
+ /** Encoded as Option::Some(EntryRequirement) on chain when set. */
491
+ entryRequirement?: EntryRequirementArgs;
492
+ salt?: number;
493
+ metadataValue?: number;
494
+ }
495
+ /**
496
+ * Token prize payload. Mirrors the Cairo `TokenTypeData` enum.
497
+ *
498
+ * - `erc20` — fungible. `amount` is required; `distribution` optional
499
+ * (undefined → single winner-takes-all payout). When `distribution`
500
+ * is set, `distributionCount` is required (number of paid positions).
501
+ * - `erc721` — single NFT. `tokenId` is the u128 id of the token the
502
+ * sponsor is escrowing.
503
+ */
504
+ type TokenTypeSpec = {
505
+ kind: "erc20";
506
+ /** Raw u128 amount (decimal string). */
507
+ amount: string;
508
+ distribution?: DistributionSpec;
509
+ distributionCount?: number;
510
+ } | {
511
+ kind: "erc721";
512
+ tokenId: string;
513
+ };
514
+ /**
515
+ * Tagged union mirroring the on-chain `Prize` enum.
516
+ *
517
+ * - `config` — built-in path: sponsor escrows an ERC20/ERC721 prize via
518
+ * the budokan PrizeComponent; `position` selects a leaderboard slot
519
+ * for non-distributed prizes (ignored for distributed ERC20).
520
+ * - `extension` — external `IPrizeExtension`: budokan forwards the
521
+ * `config` blob to `IPrizeExtension.add_prize`. `position` is ignored
522
+ * (the extension owns position semantics).
523
+ */
524
+ type PrizeSpec = {
525
+ kind: "token";
526
+ tokenAddress: string;
527
+ tokenType: TokenTypeSpec;
528
+ /** Leaderboard slot for single (non-distributed) prizes. Omit for distributed. */
529
+ position?: number;
530
+ } | {
531
+ kind: "extension";
532
+ /** Address of the contract implementing `IPrizeExtension`. */
533
+ address: string;
534
+ /** Opaque payload forwarded to `IPrizeExtension.add_prize`. */
535
+ config: string[];
536
+ };
537
+ interface AddPrizeArgs {
538
+ tournamentId: string;
539
+ prize: PrizeSpec;
540
+ }
541
+ /**
542
+ * Tagged union mirroring the Cairo `RewardType` enum hierarchy:
543
+ *
544
+ * variant 0: Prize(PrizeClaim)
545
+ * PrizeClaim variant 0: Token(PrizeType)
546
+ * PrizeType variant 0: Single(u64)
547
+ * PrizeType variant 1: Distributed((u64, u8))
548
+ * PrizeClaim variant 1: Extension({prize_id, position, payout_params})
549
+ * variant 1: EntryFee(EntryFeeClaim)
550
+ * EntryFeeClaim variant 0: Token(EntryFeeRewardType)
551
+ * EntryFeeRewardType variant 0: Position(u32)
552
+ * EntryFeeRewardType variant 1: TournamentCreator
553
+ * EntryFeeRewardType variant 2: GameCreator
554
+ * EntryFeeRewardType variant 3: Refund(felt252)
555
+ * EntryFeeClaim variant 1: Extension(ExtensionEntryFeeClaim)
556
+ *
557
+ * Extension claims are pure pass-through on the host: budokan forwards
558
+ * `(token_id, payout_params)` to the extension and lets it resolve
559
+ * recipient + eligibility from its own state. Callers don't supply
560
+ * recipient or position — the extension derives them.
561
+ *
562
+ * Conventions:
563
+ * - `tokenId` is the game token claiming. Positional extensions
564
+ * (NFTPrize, NFTEntryFee) use it to look up the leaderboard
565
+ * position; ownership-based extensions use it to derive the
566
+ * recipient via `owner_of`.
567
+ * - `tokenId: undefined` signals a non-claim flow (sponsor refund,
568
+ * dao distribution, raffle draw). The extension extracts whatever
569
+ * it needs from `payoutParams` / `claimParams` — e.g. NFTPrize
570
+ * reads `payoutParams[0]` as the slot index to refund.
571
+ */
572
+ type RewardType = {
573
+ kind: "prize_single";
574
+ prizeId: string;
575
+ } | {
576
+ kind: "prize_distributed";
577
+ prizeId: string;
578
+ payoutPosition: number;
579
+ } | {
580
+ kind: "prize_extension";
581
+ prizeId: string;
582
+ /**
583
+ * Game token claiming the prize, or undefined for non-claim flows
584
+ * (sponsor refunds, raffle draws, etc.).
585
+ */
586
+ tokenId?: string;
587
+ payoutParams: string[];
588
+ } | {
589
+ kind: "entry_fee_position";
590
+ position: number;
591
+ } | {
592
+ kind: "entry_fee_tournament_creator";
593
+ } | {
594
+ kind: "entry_fee_game_creator";
595
+ } | {
596
+ kind: "entry_fee_protocol_fee";
597
+ } | {
598
+ kind: "entry_fee_refund";
599
+ tokenId: string;
600
+ } | {
601
+ kind: "entry_fee_extension";
602
+ /**
603
+ * Game token claiming the fee-pool share, or undefined for
604
+ * non-claim flows (sponsor refunds, creator shares, etc.).
605
+ */
606
+ tokenId?: string;
607
+ claimParams: string[];
608
+ };
609
+ /** Standard ERC20 `approve(spender, amount)` call. */
610
+ declare function buildErc20ApproveCall(tokenAddress: string, spender: string, amount: string): Call;
611
+ /**
612
+ * `enter_tournament(tournament_id: u64, player_name: Option<felt252>,
613
+ * player_address: Option<ContractAddress>,
614
+ * qualifier: Option<ContractAddress>,
615
+ * qualification: Option<QualificationProof>,
616
+ * entry_fee_pay_params: Option<Span<felt252>>,
617
+ * salt: u16, metadata_value: u16)`
618
+ *
619
+ * Targets the current budokan contract (#264/#269). `qualification` and
620
+ * `entry_fee_pay_params` are always `None` here — gated/extension-fee
621
+ * tournaments need a real proof / pay-params payload, which depend on the
622
+ * validator and the caller's runtime state.
623
+ *
624
+ * Returns `(felt252, u32)` on-chain — game_token_id and entry_number — but
625
+ * `execute()` surfaces only the tx hash. Callers can fetch the receipt
626
+ * and parse events if they need the values.
627
+ *
628
+ * Tournaments with a non-trivial entry_requirement (NFT-gated or
629
+ * extension-validator) need a real `QualificationProof` and shouldn't go
630
+ * through this entrypoint — route those via the budokan client UI or
631
+ * implement a qualification-proof builder.
632
+ */
633
+ declare function buildEnterTournamentCall(budokanAddress: string, args: EnterTournamentArgs): Call;
634
+ /** `submit_score(tournament_id: u64, token_id: felt252, position: u32)` */
635
+ declare function buildSubmitScoreCall(budokanAddress: string, args: {
636
+ tournamentId: string;
637
+ tokenId: string;
638
+ position: number;
639
+ }): Call;
640
+ /** `claim_reward(tournament_id: u64, reward_type: RewardType)` */
641
+ declare function buildClaimRewardCall(budokanAddress: string, args: {
642
+ tournamentId: string;
643
+ reward: RewardType;
644
+ }): Call;
645
+ /**
646
+ * `create_tournament(creator_rewards_address, metadata, schedule,
647
+ * game_config, entry_fee, entry_requirement,
648
+ * leaderboard_config, salt, metadata_value)`
649
+ *
650
+ * Schedule fields are durations (`registration_end_delay`,
651
+ * `game_end_delay` measured from their respective starts) — *not*
652
+ * absolute offsets from creation. Callers are responsible for the
653
+ * arithmetic; the contract validates min/max bounds itself.
654
+ *
655
+ * Pass `entryFee` / `entryRequirement` as `undefined` for free / open
656
+ * tournaments. Both fields are wrapped in `CairoOption` so
657
+ * `CallData.compile` emits the correct variant tag.
658
+ */
659
+ declare function buildCreateTournamentCall(budokanAddress: string, args: CreateTournamentArgs): Call;
660
+ /**
661
+ * `add_prize(tournament_id: u64, prize: Prize, position: Option<u32>) -> u64`
662
+ *
663
+ * The `Prize` sum type discriminates between the built-in
664
+ * (ERC20/ERC721) flow and an external `IPrizeExtension` integration —
665
+ * see `PrizeSpec` for the variants.
666
+ *
667
+ * The on-chain entrypoint returns the minted `prize_id` (u64); callers
668
+ * wanting the full payload should subscribe to the `PrizeAdded` event.
669
+ */
670
+ declare function buildAddPrizeCall(budokanAddress: string, args: AddPrizeArgs): Call;
671
+ /**
672
+ * Minimal receipt shape — `events: Array<{ from_address, keys, ... }>`
673
+ * is all `parseTournamentIdFromReceipt` needs and matches what every
674
+ * Starknet RPC / starknet.js `waitForTransaction` returns.
675
+ */
676
+ interface ReceiptWithEvents {
677
+ events?: Array<{
678
+ from_address?: string;
679
+ keys?: string[];
680
+ }>;
681
+ }
682
+ /**
683
+ * Extract the new tournament's id from a `create_tournament` tx receipt
684
+ * by scanning for the `TournamentCreated` event emitted by the budokan
685
+ * contract. The event has the tournament id in its first indexed key
686
+ * (`keys[1]` — `keys[0]` is the selector).
687
+ *
688
+ * Returns the id as a `bigint` (the on-chain type is `u64`, which exceeds
689
+ * JS `Number.MAX_SAFE_INTEGER`, so a lossless type is required — callers
690
+ * deep-linking to a tournament page should `.toString()` it). Returns
691
+ * `undefined` if no matching event is found (e.g. the receipt came from a
692
+ * different call, or the budokan address didn't match).
693
+ *
694
+ * Caller is responsible for fetching the receipt — typically via
695
+ * `account.waitForTransaction(hash)` or `provider.waitForTransaction(hash)`.
696
+ */
697
+ declare function parseTournamentIdFromReceipt(receipt: ReceiptWithEvents, budokanAddress: string): bigint | undefined;
698
+
699
+ /**
700
+ * Entry-requirement validator extensions.
701
+ *
702
+ * Thin wrappers on top of @provable-games/metagame-sdk for the four
703
+ * validator presets we recommend for chat / bot integrations:
704
+ *
705
+ * - merkle — Allowlist of addresses via a pre-built merkle tree
706
+ * - erc20Balance — Player must hold ≥ X of some ERC-20
707
+ * - opusTroves — Player must have borrowed ≥ $X CASH on Opus
708
+ * - tournament — Player must have entered / placed in a prior tournament
709
+ *
710
+ * Each `buildXxxConfig` function emits the `Span<felt252>` config array
711
+ * the on-chain validator's `add_config` expects. Pair the array with the
712
+ * validator address (via `extensionAddressFor`) when building an
713
+ * `EntryRequirementArgs` of kind `"extension"`.
714
+ *
715
+ * Authoritative on-chain layouts:
716
+ * metagame-extensions/packages/presets/src/entry_requirement/*.cairo
717
+ *
718
+ * u256 values (ERC-20 balance thresholds) are split into low/high felt
719
+ * pairs to match those layouts. CASH amounts for Opus are passed as
720
+ * single felts because they're u128-range in practice.
721
+ */
722
+
723
+ type ExtensionPresetKind = "merkle" | "erc20Balance" | "opusTroves" | "tournament";
724
+ /**
725
+ * Lookup the deployed validator address for a given preset on a given
726
+ * chain. Throws if the metagame-sdk address table doesn't have one — the
727
+ * preset isn't usable on that chain.
728
+ */
729
+ declare function extensionAddressFor(chain: WhitelistChain, kind: ExtensionPresetKind): string;
730
+ /** Split a u256 (as bigint) into [low_128, high_128] felt strings. */
731
+ declare function u256ToLowHigh(value: bigint): [string, string];
732
+ interface Erc20BalanceConfig {
733
+ tokenAddress: string;
734
+ /** Raw u256, smallest units. */
735
+ minThreshold: bigint;
736
+ /** Raw u256, smallest units; 0 = no max. */
737
+ maxThreshold: bigint;
738
+ /** Raw u256, smallest units; 0 = single entry, regardless of balance. */
739
+ valuePerEntry: bigint;
740
+ /** 0 = unlimited (only meaningful when valuePerEntry > 0). */
741
+ maxEntries: number;
742
+ bannable: boolean;
743
+ }
744
+ /**
745
+ * Build the felt-string config array.
746
+ *
747
+ * Layout (from erc20_balance_validator.cairo):
748
+ * [token, min_low, min_high, max_low, max_high, vpe_low, vpe_high,
749
+ * max_entries, bannable]
750
+ */
751
+ declare function buildErc20BalanceConfig(cfg: Erc20BalanceConfig): string[];
752
+ interface OpusTrovesConfig {
753
+ /** Specific collateral filters; empty = wildcard (any trove qualifies). */
754
+ assetAddresses: string[];
755
+ /** Min CASH borrowed (raw, 18 decimals). CASH is 1:1 USD. */
756
+ threshold: bigint;
757
+ /** CASH per additional entry; 0 = single entry per qualifying trove. */
758
+ valuePerEntry: bigint;
759
+ /** 0 = unlimited (only meaningful with proportional valuePerEntry > 0). */
760
+ maxEntries: number;
761
+ bannable: boolean;
762
+ }
763
+ /**
764
+ * Layout (from opus_troves_validator):
765
+ * [asset_count, ...asset_addresses, threshold, value_per_entry,
766
+ * max_entries, bannable]
767
+ *
768
+ * threshold / value_per_entry are CASH amounts (18 decimals, ≤ u128 range
769
+ * for any reasonable USD value) — passed as single felts, not low/high
770
+ * pairs. This matches the validator's parse (parseOpusTrovesValidatorConfig
771
+ * in metagame-sdk reads them as bigints directly).
772
+ */
773
+ declare function buildOpusTrovesConfig(cfg: OpusTrovesConfig): string[];
774
+ interface MerkleConfig {
775
+ /** On-chain tree ID from the merkle-validator's create_tree. */
776
+ treeId: number;
777
+ }
778
+ /** Layout: [tree_id]. */
779
+ declare function buildMerkleConfig(cfg: MerkleConfig): string[];
780
+ /** 0 = participated (any entry counts), 1 = won (placed in top N). */
781
+ type TournamentRequirementType = "participated" | "won";
782
+ /**
783
+ * How to combine multiple qualifying tournaments. Matches QualifyingMode
784
+ * in metagame-sdk: 0=AtLeastOne, 1=CumulativePerTournament, 2=All,
785
+ * 3=CumulativePerEntry, 4=AllParticipateAnyWin, 5=AllWithCumulative.
786
+ */
787
+ interface TournamentValidatorConfig {
788
+ requirement: TournamentRequirementType;
789
+ /** Tournament IDs whose history qualifies. */
790
+ tournamentIds: string[];
791
+ /** Top N positions that count (only used when requirement = "won"). */
792
+ topPositions: number;
793
+ /** Default 0 (= AtLeastOne). */
794
+ qualifyingMode?: number;
795
+ }
796
+ /**
797
+ * Layout (from tournament_validator):
798
+ * [qualifier_type, qualifying_mode, top_positions, ...tournament_ids]
799
+ * - qualifier_type: 0 = participated, 1 = won
800
+ * - qualifying_mode: 0–5 enum
801
+ * - top_positions: 0 for "all positions" (used with participated)
802
+ */
803
+ declare function buildTournamentValidatorConfig(cfg: TournamentValidatorConfig): string[];
192
804
 
193
- export { BudokanApiError, BudokanConnectionError, BudokanError, BudokanTimeoutError, CHAINS, type ChainConfig, DataSourceError, PaginatedResult, PlatformStats, Prize, PrizeAggregation, PrizeStats, QualificationEntry, Registration, RewardClaim, RewardClaimSummary, RpcError, Tournament, TournamentListParams, TournamentNotFoundError, WSEventHandler, WSManager, WSSubscribeOptions, camelToSnake, getActivityStats, getChainConfig, getGameStats, getGameTournaments, getPrizeStats, getTournament, getTournamentPrizeAggregation, getTournamentPrizes, getTournamentQualifications, getTournamentRegistrations, getTournamentRewardClaims, getTournamentRewardClaimsSummary, getTournaments, normalizeAddress, snakeToCamel, withRetry };
805
+ export { type AddPrizeArgs, BudokanApiError, BudokanConnectionError, BudokanError, BudokanTimeoutError, CHAINS, type Call, type ChainConfig, type CreateTournamentArgs, DataSourceError, type DistributionSpec, type EnterTournamentArgs, type EntryFeeArgs, type EntryRequirementArgs, type EntryRequirementSpec, type Erc20BalanceConfig, type ExtensionPresetKind, ExtensionPrize$1 as ExtensionPrize, type GameDefaults, type MerkleConfig, type MetagameExtensionPrize, type MetagamePrizeLike, type MetagameTokenPrize, type OpusTrovesConfig, PaginatedResult, PlatformStats, Prize, PrizeAggregation, type PrizeSpec, PrizeStats, QualificationEntry, type ReceiptWithEvents, Registration, RewardClaim, RewardClaimSummary, type RewardType, RpcError, TokenPrize, type TokenTypeSpec, Tournament, TournamentListParams, TournamentNotFoundError, type TournamentRequirementType, type TournamentValidatorConfig, WSEventHandler, WSManager, WSSubscribeOptions, type WhitelistChain, type WhitelistedGame, buildAddPrizeCall, buildClaimRewardCall, buildCreateTournamentCall, buildEnterTournamentCall, buildErc20ApproveCall, buildErc20BalanceConfig, buildMerkleConfig, buildOpusTrovesConfig, buildSubmitScoreCall, buildTournamentValidatorConfig, camelToSnake, explorerAddressUrl, explorerBaseUrl, explorerTxUrl, extensionAddressFor, findWhitelistedGame, getActivityStats, getChainConfig, getGameDefaults, getGameStats, getGameTournaments, getPrizeStats, getRawTokenPrizes, getTokenPrizes, getTournament, getTournamentPrizeAggregation, getTournamentPrizes, getTournamentQualifications, getTournamentRegistrations, getTournamentRewardClaims, getTournamentRewardClaimsSummary, getTournaments, getWhitelistedGames, isExtensionPrize, isGameWhitelisted, isMetagameAdaptablePrize, isRawExtensionPrize, isRawTokenPrize, isTokenPrize, normalizeAddress, parseTournamentIdFromReceipt, snakeToCamel, toMetagameExtensionPrize, toMetagamePrize, toMetagamePrizes, toMetagameTokenPrize, toMetagameTokenPrizes, tournamentPageUrl, tryToMetagamePrize, tryToMetagamePrizes, u256ToLowHigh, withRetry };