@provable-games/budokan-sdk 0.1.13 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js CHANGED
@@ -586,15 +586,15 @@ var CHAINS = {
586
586
  rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet/rpc/v0_10",
587
587
  apiBaseUrl: "https://budokan-api-production.up.railway.app",
588
588
  wsUrl: "wss://budokan-api-production.up.railway.app/ws",
589
- budokanAddress: "0x04dae41808911e51af8efe8ac3202cb3b2a32c10c169703010b7e0cbd885bf83",
590
- viewerAddress: "0x02ef405cf2a8e8aec2946e5be39fa4e8bcb51cea5ce3573760418e7cdc7e5a22"
589
+ budokanAddress: "0x0765e6f07c1a5cebe08aba7f840741242dffb1ed77ac619120501f540ec9a52a",
590
+ viewerAddress: "0x0232fb32bd06e38f3555000f255c01812198418d5fced3b6246900725bf2f4d1"
591
591
  },
592
592
  sepolia: {
593
593
  rpcUrl: "https://starknet-sepolia.public.blastapi.io",
594
594
  apiBaseUrl: "https://budokan-api-sepolia.up.railway.app",
595
595
  wsUrl: "wss://budokan-api-sepolia.up.railway.app/ws",
596
- budokanAddress: "0x02a97de0b33fb115f5c32a58232d9941c4a5b2598aa71d30c094076cc592f94d",
597
- viewerAddress: "0x001f2be7ed811bfa859f8f6cf72d2458f36103ac172ff8e65a630bbcc6cf98c9"
596
+ budokanAddress: "0x0105573bf9184f0a3da78dda70a87055e6aafc7b3fb6e331732a0d25675b7be5",
597
+ viewerAddress: "0x0414fe2f48db1e3598a83f017d17b4d06cec180b160141fea9244054267c1ff1"
598
598
  }
599
599
  };
600
600
  function getChainConfig(chain) {
@@ -1000,6 +1000,7 @@ function parsePrize(raw) {
1000
1000
  let tokenId = null;
1001
1001
  let distributionType = null;
1002
1002
  let distributionWeight = null;
1003
+ let distributionShares = null;
1003
1004
  let distributionCount = null;
1004
1005
  let payoutPosition = 0;
1005
1006
  if (tokenTypeData) {
@@ -1018,7 +1019,11 @@ function parsePrize(raw) {
1018
1019
  if (distType) {
1019
1020
  distributionType = distType.toLowerCase();
1020
1021
  const distValue = distVariant[distType];
1021
- distributionWeight = distValue != null ? Number(distValue) : null;
1022
+ if (distributionType === "custom") {
1023
+ distributionShares = Array.isArray(distValue) ? distValue.map((v) => Number(v)) : null;
1024
+ } else {
1025
+ distributionWeight = distValue != null ? Number(distValue) : null;
1026
+ }
1022
1027
  }
1023
1028
  }
1024
1029
  const countOption = erc20?.distribution_count;
@@ -1039,6 +1044,7 @@ function parsePrize(raw) {
1039
1044
  tokenId,
1040
1045
  distributionType,
1041
1046
  distributionWeight,
1047
+ distributionShares,
1042
1048
  distributionCount,
1043
1049
  sponsorAddress: num.toHex(obj.sponsor_address)
1044
1050
  };
@@ -2389,180 +2395,2105 @@ var budokanViewer_default = [
2389
2395
  }
2390
2396
  ];
2391
2397
 
2392
- // src/client.ts
2393
- var BudokanClient = class {
2394
- resolvedConfig;
2395
- wsManager;
2396
- connectionStatus;
2397
- cachedProvider = null;
2398
- cachedViewerContract = null;
2399
- constructor(config) {
2400
- const chainConfig = config.chain ? getChainConfig(config.chain) : void 0;
2401
- this.resolvedConfig = {
2402
- ...config,
2403
- apiBaseUrl: config.apiBaseUrl ?? chainConfig?.apiBaseUrl ?? "",
2404
- rpcUrl: config.rpcUrl ?? chainConfig?.rpcUrl ?? "",
2405
- viewerAddress: config.viewerAddress ?? chainConfig?.viewerAddress ?? "",
2406
- budokanAddress: config.budokanAddress ?? chainConfig?.budokanAddress ?? ""
2407
- };
2408
- const wsUrl = config.wsUrl ?? chainConfig?.wsUrl ?? this.resolvedConfig.apiBaseUrl.replace(/^http/, "ws").replace(/\/$/, "") + "/ws";
2409
- this.wsManager = new WSManager(wsUrl);
2410
- this.connectionStatus = new ConnectionStatus(
2411
- this.resolvedConfig.apiBaseUrl,
2412
- this.resolvedConfig.rpcUrl,
2413
- config.health
2414
- );
2415
- if (this.resolvedConfig.apiBaseUrl && this.resolvedConfig.rpcUrl) {
2416
- this.connectionStatus.startMonitoring();
2417
- }
2418
- }
2419
- // ---- Configuration ----
2420
- /** Returns the resolved configuration. */
2421
- get clientConfig() {
2422
- return { ...this.resolvedConfig };
2423
- }
2424
- /** Whether the WebSocket is currently connected. */
2425
- get wsConnected() {
2426
- return this.wsManager.isConnected;
2427
- }
2428
- // ---- Connection status ----
2429
- /** Returns the current connection status (API, RPC, mode). */
2430
- getConnectionStatus() {
2431
- return this.connectionStatus.getStatus();
2432
- }
2433
- /** Subscribe to connection status changes. Returns an unsubscribe function. */
2434
- onConnectionStatusChange(listener) {
2435
- return this.connectionStatus.subscribe(listener);
2436
- }
2437
- // ---- Lazy RPC getters ----
2438
- async getProvider() {
2439
- if (this.cachedProvider) return this.cachedProvider;
2440
- if (!this.resolvedConfig.rpcUrl) {
2441
- throw new RpcError("No rpcUrl configured");
2442
- }
2443
- if (this.resolvedConfig.provider) {
2444
- this.cachedProvider = this.resolvedConfig.provider;
2445
- return this.cachedProvider;
2446
- }
2447
- this.cachedProvider = await createProvider(
2448
- this.resolvedConfig.rpcUrl,
2449
- this.resolvedConfig.rpcHeaders
2450
- );
2451
- return this.cachedProvider;
2452
- }
2453
- async getViewerContract() {
2454
- if (this.cachedViewerContract) return this.cachedViewerContract;
2455
- if (!this.resolvedConfig.viewerAddress) {
2456
- throw new RpcError("No viewerAddress configured. Set viewerAddress in config or use a chain preset with a deployed viewer contract.");
2457
- }
2458
- const provider = await this.getProvider();
2459
- this.cachedViewerContract = await createContract(
2460
- budokanViewer_default,
2461
- this.resolvedConfig.viewerAddress,
2462
- provider
2463
- );
2464
- return this.cachedViewerContract;
2465
- }
2466
- // ---- API context ----
2467
- get apiCtx() {
2468
- return {
2469
- retryAttempts: this.resolvedConfig.retryAttempts,
2470
- retryDelay: this.resolvedConfig.retryDelay,
2471
- timeout: this.resolvedConfig.timeout
2472
- };
2473
- }
2474
- // ---- Tournament Queries ----
2475
- /**
2476
- * Fetch a paginated list of tournaments with optional filtering.
2477
- * Supports RPC fallback when API is unavailable.
2478
- */
2479
- async getTournaments(params) {
2480
- const rpcFallback = async () => {
2481
- const contract = await this.getViewerContract();
2482
- const offset = params?.offset ?? 0;
2483
- const limit = params?.limit ?? 20;
2484
- let filterResult;
2485
- if (params?.phase) {
2486
- filterResult = await viewerTournamentsByPhase(contract, params.phase, offset, limit);
2487
- } else if (params?.gameAddress) {
2488
- filterResult = await viewerTournamentsByGame(contract, params.gameAddress, offset, limit);
2489
- } else if (params?.creator) {
2490
- filterResult = await viewerTournamentsByCreator(contract, params.creator, offset, limit);
2491
- } else {
2492
- filterResult = await viewerTournaments(contract, offset, limit);
2398
+ // src/rpc/abis/budokan.json
2399
+ var budokan_default = [
2400
+ {
2401
+ type: "impl",
2402
+ name: "UpgradeableImpl",
2403
+ interface_name: "openzeppelin_interfaces::upgrades::IUpgradeable"
2404
+ },
2405
+ {
2406
+ type: "interface",
2407
+ name: "openzeppelin_interfaces::upgrades::IUpgradeable",
2408
+ items: [
2409
+ {
2410
+ type: "function",
2411
+ name: "upgrade",
2412
+ inputs: [
2413
+ {
2414
+ name: "new_class_hash",
2415
+ type: "core::starknet::class_hash::ClassHash"
2416
+ }
2417
+ ],
2418
+ outputs: [],
2419
+ state_mutability: "external"
2493
2420
  }
2494
- let data = [];
2495
- if (filterResult.tournamentIds.length > 0) {
2496
- data = await viewerTournamentsBatch(contract, filterResult.tournamentIds);
2497
- if (params?.includePrizeSummary) {
2498
- const prizePromises = data.map(
2499
- (t) => viewerPrizes(contract, t.id).catch(() => [])
2500
- );
2501
- const allPrizes = await Promise.all(prizePromises);
2502
- data = data.map((t, i) => {
2503
- const prizes = allPrizes[i];
2504
- if (prizes.length === 0) return t;
2505
- const tokenMap = /* @__PURE__ */ new Map();
2506
- for (const p of prizes) {
2507
- const key = p.tokenAddress;
2508
- const existing = tokenMap.get(key);
2509
- if (existing) {
2510
- existing.totalAmount += BigInt(p.amount ?? "0");
2511
- if (p.tokenType === "erc721") existing.nftCount += 1;
2512
- } else {
2513
- tokenMap.set(key, {
2514
- tokenAddress: p.tokenAddress,
2515
- tokenType: p.tokenType,
2516
- totalAmount: BigInt(p.amount ?? "0"),
2517
- nftCount: p.tokenType === "erc721" ? 1 : 0
2518
- });
2519
- }
2520
- }
2521
- return {
2522
- ...t,
2523
- prizeAggregation: Array.from(tokenMap.values()).map((v) => ({
2524
- tokenAddress: v.tokenAddress,
2525
- tokenType: v.tokenType,
2526
- totalAmount: v.totalAmount.toString(),
2527
- nftCount: v.nftCount
2528
- }))
2529
- };
2530
- });
2531
- }
2421
+ ]
2422
+ },
2423
+ {
2424
+ type: "impl",
2425
+ name: "GameContextImpl",
2426
+ interface_name: "game_components_interfaces::metagame::context::IMetagameContext"
2427
+ },
2428
+ {
2429
+ type: "enum",
2430
+ name: "core::bool",
2431
+ variants: [
2432
+ {
2433
+ name: "False",
2434
+ type: "()"
2435
+ },
2436
+ {
2437
+ name: "True",
2438
+ type: "()"
2532
2439
  }
2533
- return { data, total: filterResult.total, limit, offset };
2534
- };
2535
- if (this.resolvedConfig.primarySource === "rpc") {
2536
- return rpcFallback();
2537
- }
2538
- return withFallback(
2539
- () => getTournaments(this.resolvedConfig.apiBaseUrl, params, this.apiCtx),
2540
- rpcFallback,
2541
- this.connectionStatus
2542
- );
2543
- }
2544
- /**
2545
- * Fetch a single tournament by its ID.
2546
- * Supports RPC fallback when API is unavailable.
2547
- */
2548
- async getTournament(tournamentId) {
2549
- const rpcFallback = async () => {
2550
- const contract = await this.getViewerContract();
2551
- return viewerTournamentDetail(contract, tournamentId);
2552
- };
2553
- if (this.resolvedConfig.primarySource === "rpc") {
2554
- return rpcFallback();
2555
- }
2556
- try {
2557
- return await getTournament(this.resolvedConfig.apiBaseUrl, tournamentId, this.apiCtx);
2558
- } catch {
2559
- try {
2560
- this.connectionStatus.markApiUnavailable();
2561
- return await rpcFallback();
2562
- } catch {
2563
- return null;
2440
+ ]
2441
+ },
2442
+ {
2443
+ type: "interface",
2444
+ name: "game_components_interfaces::metagame::context::IMetagameContext",
2445
+ items: [
2446
+ {
2447
+ type: "function",
2448
+ name: "has_context",
2449
+ inputs: [
2450
+ {
2451
+ name: "token_id",
2452
+ type: "core::felt252"
2453
+ }
2454
+ ],
2455
+ outputs: [
2456
+ {
2457
+ type: "core::bool"
2458
+ }
2459
+ ],
2460
+ state_mutability: "view"
2564
2461
  }
2565
- }
2462
+ ]
2463
+ },
2464
+ {
2465
+ type: "impl",
2466
+ name: "GameContextDetailsImpl",
2467
+ interface_name: "game_components_interfaces::metagame::context::IMetagameContextDetails"
2468
+ },
2469
+ {
2470
+ type: "struct",
2471
+ name: "core::byte_array::ByteArray",
2472
+ members: [
2473
+ {
2474
+ name: "data",
2475
+ type: "core::array::Array::<core::bytes_31::bytes31>"
2476
+ },
2477
+ {
2478
+ name: "pending_word",
2479
+ type: "core::felt252"
2480
+ },
2481
+ {
2482
+ name: "pending_word_len",
2483
+ type: "core::internal::bounded_int::BoundedInt::<0, 30>"
2484
+ }
2485
+ ]
2486
+ },
2487
+ {
2488
+ type: "enum",
2489
+ name: "core::option::Option::<core::integer::u32>",
2490
+ variants: [
2491
+ {
2492
+ name: "Some",
2493
+ type: "core::integer::u32"
2494
+ },
2495
+ {
2496
+ name: "None",
2497
+ type: "()"
2498
+ }
2499
+ ]
2500
+ },
2501
+ {
2502
+ type: "struct",
2503
+ name: "game_components_interfaces::structs::metagame::GameContext",
2504
+ members: [
2505
+ {
2506
+ name: "name",
2507
+ type: "core::byte_array::ByteArray"
2508
+ },
2509
+ {
2510
+ name: "value",
2511
+ type: "core::byte_array::ByteArray"
2512
+ }
2513
+ ]
2514
+ },
2515
+ {
2516
+ type: "struct",
2517
+ name: "core::array::Span::<game_components_interfaces::structs::metagame::GameContext>",
2518
+ members: [
2519
+ {
2520
+ name: "snapshot",
2521
+ type: "@core::array::Array::<game_components_interfaces::structs::metagame::GameContext>"
2522
+ }
2523
+ ]
2524
+ },
2525
+ {
2526
+ type: "struct",
2527
+ name: "game_components_interfaces::structs::metagame::GameContextDetails",
2528
+ members: [
2529
+ {
2530
+ name: "name",
2531
+ type: "core::byte_array::ByteArray"
2532
+ },
2533
+ {
2534
+ name: "description",
2535
+ type: "core::byte_array::ByteArray"
2536
+ },
2537
+ {
2538
+ name: "id",
2539
+ type: "core::option::Option::<core::integer::u32>"
2540
+ },
2541
+ {
2542
+ name: "context",
2543
+ type: "core::array::Span::<game_components_interfaces::structs::metagame::GameContext>"
2544
+ }
2545
+ ]
2546
+ },
2547
+ {
2548
+ type: "interface",
2549
+ name: "game_components_interfaces::metagame::context::IMetagameContextDetails",
2550
+ items: [
2551
+ {
2552
+ type: "function",
2553
+ name: "context_details",
2554
+ inputs: [
2555
+ {
2556
+ name: "token_id",
2557
+ type: "core::felt252"
2558
+ }
2559
+ ],
2560
+ outputs: [
2561
+ {
2562
+ type: "game_components_interfaces::structs::metagame::GameContextDetails"
2563
+ }
2564
+ ],
2565
+ state_mutability: "view"
2566
+ }
2567
+ ]
2568
+ },
2569
+ {
2570
+ type: "impl",
2571
+ name: "BudokanImpl",
2572
+ interface_name: "budokan_interfaces::budokan::IBudokan"
2573
+ },
2574
+ {
2575
+ type: "struct",
2576
+ name: "budokan_interfaces::budokan::Metadata",
2577
+ members: [
2578
+ {
2579
+ name: "name",
2580
+ type: "core::felt252"
2581
+ },
2582
+ {
2583
+ name: "description",
2584
+ type: "core::byte_array::ByteArray"
2585
+ }
2586
+ ]
2587
+ },
2588
+ {
2589
+ type: "struct",
2590
+ name: "budokan_interfaces::budokan::Schedule",
2591
+ members: [
2592
+ {
2593
+ name: "registration_start_delay",
2594
+ type: "core::integer::u32"
2595
+ },
2596
+ {
2597
+ name: "registration_end_delay",
2598
+ type: "core::integer::u32"
2599
+ },
2600
+ {
2601
+ name: "game_start_delay",
2602
+ type: "core::integer::u32"
2603
+ },
2604
+ {
2605
+ name: "game_end_delay",
2606
+ type: "core::integer::u32"
2607
+ },
2608
+ {
2609
+ name: "submission_duration",
2610
+ type: "core::integer::u32"
2611
+ }
2612
+ ]
2613
+ },
2614
+ {
2615
+ type: "enum",
2616
+ name: "core::option::Option::<core::byte_array::ByteArray>",
2617
+ variants: [
2618
+ {
2619
+ name: "Some",
2620
+ type: "core::byte_array::ByteArray"
2621
+ },
2622
+ {
2623
+ name: "None",
2624
+ type: "()"
2625
+ }
2626
+ ]
2627
+ },
2628
+ {
2629
+ type: "enum",
2630
+ name: "core::option::Option::<core::starknet::contract_address::ContractAddress>",
2631
+ variants: [
2632
+ {
2633
+ name: "Some",
2634
+ type: "core::starknet::contract_address::ContractAddress"
2635
+ },
2636
+ {
2637
+ name: "None",
2638
+ type: "()"
2639
+ }
2640
+ ]
2641
+ },
2642
+ {
2643
+ type: "struct",
2644
+ name: "budokan_interfaces::budokan::GameConfig",
2645
+ members: [
2646
+ {
2647
+ name: "game_address",
2648
+ type: "core::starknet::contract_address::ContractAddress"
2649
+ },
2650
+ {
2651
+ name: "settings_id",
2652
+ type: "core::integer::u32"
2653
+ },
2654
+ {
2655
+ name: "soulbound",
2656
+ type: "core::bool"
2657
+ },
2658
+ {
2659
+ name: "paymaster",
2660
+ type: "core::bool"
2661
+ },
2662
+ {
2663
+ name: "client_url",
2664
+ type: "core::option::Option::<core::byte_array::ByteArray>"
2665
+ },
2666
+ {
2667
+ name: "renderer",
2668
+ type: "core::option::Option::<core::starknet::contract_address::ContractAddress>"
2669
+ }
2670
+ ]
2671
+ },
2672
+ {
2673
+ type: "struct",
2674
+ name: "core::array::Span::<core::integer::u16>",
2675
+ members: [
2676
+ {
2677
+ name: "snapshot",
2678
+ type: "@core::array::Array::<core::integer::u16>"
2679
+ }
2680
+ ]
2681
+ },
2682
+ {
2683
+ type: "enum",
2684
+ name: "game_components_interfaces::distribution::Distribution",
2685
+ variants: [
2686
+ {
2687
+ name: "Linear",
2688
+ type: "core::integer::u16"
2689
+ },
2690
+ {
2691
+ name: "Exponential",
2692
+ type: "core::integer::u16"
2693
+ },
2694
+ {
2695
+ name: "Uniform",
2696
+ type: "()"
2697
+ },
2698
+ {
2699
+ name: "Custom",
2700
+ type: "core::array::Span::<core::integer::u16>"
2701
+ }
2702
+ ]
2703
+ },
2704
+ {
2705
+ type: "struct",
2706
+ name: "budokan_interfaces::budokan::EntryFee",
2707
+ members: [
2708
+ {
2709
+ name: "token_address",
2710
+ type: "core::starknet::contract_address::ContractAddress"
2711
+ },
2712
+ {
2713
+ name: "amount",
2714
+ type: "core::integer::u128"
2715
+ },
2716
+ {
2717
+ name: "tournament_creator_share",
2718
+ type: "core::integer::u16"
2719
+ },
2720
+ {
2721
+ name: "game_creator_share",
2722
+ type: "core::integer::u16"
2723
+ },
2724
+ {
2725
+ name: "refund_share",
2726
+ type: "core::integer::u16"
2727
+ },
2728
+ {
2729
+ name: "distribution",
2730
+ type: "game_components_interfaces::distribution::Distribution"
2731
+ },
2732
+ {
2733
+ name: "distribution_count",
2734
+ type: "core::integer::u32"
2735
+ }
2736
+ ]
2737
+ },
2738
+ {
2739
+ type: "enum",
2740
+ name: "core::option::Option::<budokan_interfaces::budokan::EntryFee>",
2741
+ variants: [
2742
+ {
2743
+ name: "Some",
2744
+ type: "budokan_interfaces::budokan::EntryFee"
2745
+ },
2746
+ {
2747
+ name: "None",
2748
+ type: "()"
2749
+ }
2750
+ ]
2751
+ },
2752
+ {
2753
+ type: "struct",
2754
+ name: "core::array::Span::<core::starknet::contract_address::ContractAddress>",
2755
+ members: [
2756
+ {
2757
+ name: "snapshot",
2758
+ type: "@core::array::Array::<core::starknet::contract_address::ContractAddress>"
2759
+ }
2760
+ ]
2761
+ },
2762
+ {
2763
+ type: "struct",
2764
+ name: "core::array::Span::<core::felt252>",
2765
+ members: [
2766
+ {
2767
+ name: "snapshot",
2768
+ type: "@core::array::Array::<core::felt252>"
2769
+ }
2770
+ ]
2771
+ },
2772
+ {
2773
+ type: "struct",
2774
+ name: "interfaces::extension::ExtensionConfig",
2775
+ members: [
2776
+ {
2777
+ name: "address",
2778
+ type: "core::starknet::contract_address::ContractAddress"
2779
+ },
2780
+ {
2781
+ name: "config",
2782
+ type: "core::array::Span::<core::felt252>"
2783
+ }
2784
+ ]
2785
+ },
2786
+ {
2787
+ type: "enum",
2788
+ name: "game_components_interfaces::entry_requirement::EntryRequirementType",
2789
+ variants: [
2790
+ {
2791
+ name: "token",
2792
+ type: "core::starknet::contract_address::ContractAddress"
2793
+ },
2794
+ {
2795
+ name: "extension",
2796
+ type: "interfaces::extension::ExtensionConfig"
2797
+ }
2798
+ ]
2799
+ },
2800
+ {
2801
+ type: "struct",
2802
+ name: "game_components_interfaces::entry_requirement::EntryRequirement",
2803
+ members: [
2804
+ {
2805
+ name: "entry_limit",
2806
+ type: "core::integer::u32"
2807
+ },
2808
+ {
2809
+ name: "entry_requirement_type",
2810
+ type: "game_components_interfaces::entry_requirement::EntryRequirementType"
2811
+ }
2812
+ ]
2813
+ },
2814
+ {
2815
+ type: "enum",
2816
+ name: "core::option::Option::<game_components_interfaces::entry_requirement::EntryRequirement>",
2817
+ variants: [
2818
+ {
2819
+ name: "Some",
2820
+ type: "game_components_interfaces::entry_requirement::EntryRequirement"
2821
+ },
2822
+ {
2823
+ name: "None",
2824
+ type: "()"
2825
+ }
2826
+ ]
2827
+ },
2828
+ {
2829
+ type: "struct",
2830
+ name: "budokan_interfaces::budokan::LeaderboardConfig",
2831
+ members: [
2832
+ {
2833
+ name: "ascending",
2834
+ type: "core::bool"
2835
+ },
2836
+ {
2837
+ name: "game_must_be_over",
2838
+ type: "core::bool"
2839
+ }
2840
+ ]
2841
+ },
2842
+ {
2843
+ type: "struct",
2844
+ name: "budokan_interfaces::budokan::Tournament",
2845
+ members: [
2846
+ {
2847
+ name: "id",
2848
+ type: "core::integer::u64"
2849
+ },
2850
+ {
2851
+ name: "created_at",
2852
+ type: "core::integer::u64"
2853
+ },
2854
+ {
2855
+ name: "created_by",
2856
+ type: "core::starknet::contract_address::ContractAddress"
2857
+ },
2858
+ {
2859
+ name: "creator_token_id",
2860
+ type: "core::felt252"
2861
+ },
2862
+ {
2863
+ name: "metadata",
2864
+ type: "budokan_interfaces::budokan::Metadata"
2865
+ },
2866
+ {
2867
+ name: "schedule",
2868
+ type: "budokan_interfaces::budokan::Schedule"
2869
+ },
2870
+ {
2871
+ name: "game_config",
2872
+ type: "budokan_interfaces::budokan::GameConfig"
2873
+ },
2874
+ {
2875
+ name: "entry_fee",
2876
+ type: "core::option::Option::<budokan_interfaces::budokan::EntryFee>"
2877
+ },
2878
+ {
2879
+ name: "entry_requirement",
2880
+ type: "core::option::Option::<game_components_interfaces::entry_requirement::EntryRequirement>"
2881
+ },
2882
+ {
2883
+ name: "leaderboard_config",
2884
+ type: "budokan_interfaces::budokan::LeaderboardConfig"
2885
+ }
2886
+ ]
2887
+ },
2888
+ {
2889
+ type: "enum",
2890
+ name: "budokan_interfaces::budokan::Phase",
2891
+ variants: [
2892
+ {
2893
+ name: "Scheduled",
2894
+ type: "()"
2895
+ },
2896
+ {
2897
+ name: "Registration",
2898
+ type: "()"
2899
+ },
2900
+ {
2901
+ name: "Staging",
2902
+ type: "()"
2903
+ },
2904
+ {
2905
+ name: "Live",
2906
+ type: "()"
2907
+ },
2908
+ {
2909
+ name: "Submission",
2910
+ type: "()"
2911
+ },
2912
+ {
2913
+ name: "Finalized",
2914
+ type: "()"
2915
+ }
2916
+ ]
2917
+ },
2918
+ {
2919
+ type: "struct",
2920
+ name: "core::integer::u256",
2921
+ members: [
2922
+ {
2923
+ name: "low",
2924
+ type: "core::integer::u128"
2925
+ },
2926
+ {
2927
+ name: "high",
2928
+ type: "core::integer::u128"
2929
+ }
2930
+ ]
2931
+ },
2932
+ {
2933
+ type: "struct",
2934
+ name: "game_components_interfaces::entry_requirement::NFTQualification",
2935
+ members: [
2936
+ {
2937
+ name: "token_id",
2938
+ type: "core::integer::u256"
2939
+ }
2940
+ ]
2941
+ },
2942
+ {
2943
+ type: "enum",
2944
+ name: "game_components_interfaces::entry_requirement::QualificationProof",
2945
+ variants: [
2946
+ {
2947
+ name: "NFT",
2948
+ type: "game_components_interfaces::entry_requirement::NFTQualification"
2949
+ },
2950
+ {
2951
+ name: "Address",
2952
+ type: "core::starknet::contract_address::ContractAddress"
2953
+ },
2954
+ {
2955
+ name: "Extension",
2956
+ type: "core::array::Span::<core::felt252>"
2957
+ }
2958
+ ]
2959
+ },
2960
+ {
2961
+ type: "enum",
2962
+ name: "core::option::Option::<game_components_interfaces::entry_requirement::QualificationProof>",
2963
+ variants: [
2964
+ {
2965
+ name: "Some",
2966
+ type: "game_components_interfaces::entry_requirement::QualificationProof"
2967
+ },
2968
+ {
2969
+ name: "None",
2970
+ type: "()"
2971
+ }
2972
+ ]
2973
+ },
2974
+ {
2975
+ type: "enum",
2976
+ name: "game_components_interfaces::prize::PrizeType",
2977
+ variants: [
2978
+ {
2979
+ name: "Single",
2980
+ type: "core::integer::u64"
2981
+ },
2982
+ {
2983
+ name: "Distributed",
2984
+ type: "(core::integer::u64, core::integer::u32)"
2985
+ }
2986
+ ]
2987
+ },
2988
+ {
2989
+ type: "enum",
2990
+ name: "budokan_interfaces::budokan::EntryFeeRewardType",
2991
+ variants: [
2992
+ {
2993
+ name: "Position",
2994
+ type: "core::integer::u32"
2995
+ },
2996
+ {
2997
+ name: "TournamentCreator",
2998
+ type: "()"
2999
+ },
3000
+ {
3001
+ name: "GameCreator",
3002
+ type: "()"
3003
+ },
3004
+ {
3005
+ name: "Refund",
3006
+ type: "core::felt252"
3007
+ }
3008
+ ]
3009
+ },
3010
+ {
3011
+ type: "enum",
3012
+ name: "budokan_interfaces::budokan::RewardType",
3013
+ variants: [
3014
+ {
3015
+ name: "Prize",
3016
+ type: "game_components_interfaces::prize::PrizeType"
3017
+ },
3018
+ {
3019
+ name: "EntryFee",
3020
+ type: "budokan_interfaces::budokan::EntryFeeRewardType"
3021
+ }
3022
+ ]
3023
+ },
3024
+ {
3025
+ type: "enum",
3026
+ name: "core::option::Option::<game_components_interfaces::distribution::Distribution>",
3027
+ variants: [
3028
+ {
3029
+ name: "Some",
3030
+ type: "game_components_interfaces::distribution::Distribution"
3031
+ },
3032
+ {
3033
+ name: "None",
3034
+ type: "()"
3035
+ }
3036
+ ]
3037
+ },
3038
+ {
3039
+ type: "struct",
3040
+ name: "game_components_interfaces::prize::ERC20Data",
3041
+ members: [
3042
+ {
3043
+ name: "amount",
3044
+ type: "core::integer::u128"
3045
+ },
3046
+ {
3047
+ name: "distribution",
3048
+ type: "core::option::Option::<game_components_interfaces::distribution::Distribution>"
3049
+ },
3050
+ {
3051
+ name: "distribution_count",
3052
+ type: "core::option::Option::<core::integer::u32>"
3053
+ }
3054
+ ]
3055
+ },
3056
+ {
3057
+ type: "struct",
3058
+ name: "game_components_interfaces::prize::ERC721Data",
3059
+ members: [
3060
+ {
3061
+ name: "id",
3062
+ type: "core::integer::u128"
3063
+ }
3064
+ ]
3065
+ },
3066
+ {
3067
+ type: "enum",
3068
+ name: "game_components_interfaces::prize::TokenTypeData",
3069
+ variants: [
3070
+ {
3071
+ name: "erc20",
3072
+ type: "game_components_interfaces::prize::ERC20Data"
3073
+ },
3074
+ {
3075
+ name: "erc721",
3076
+ type: "game_components_interfaces::prize::ERC721Data"
3077
+ }
3078
+ ]
3079
+ },
3080
+ {
3081
+ type: "struct",
3082
+ name: "game_components_interfaces::prize::PrizeData",
3083
+ members: [
3084
+ {
3085
+ name: "id",
3086
+ type: "core::integer::u64"
3087
+ },
3088
+ {
3089
+ name: "context_id",
3090
+ type: "core::integer::u64"
3091
+ },
3092
+ {
3093
+ name: "token_address",
3094
+ type: "core::starknet::contract_address::ContractAddress"
3095
+ },
3096
+ {
3097
+ name: "token_type",
3098
+ type: "game_components_interfaces::prize::TokenTypeData"
3099
+ },
3100
+ {
3101
+ name: "sponsor_address",
3102
+ type: "core::starknet::contract_address::ContractAddress"
3103
+ }
3104
+ ]
3105
+ },
3106
+ {
3107
+ type: "interface",
3108
+ name: "budokan_interfaces::budokan::IBudokan",
3109
+ items: [
3110
+ {
3111
+ type: "function",
3112
+ name: "total_tournaments",
3113
+ inputs: [],
3114
+ outputs: [
3115
+ {
3116
+ type: "core::integer::u64"
3117
+ }
3118
+ ],
3119
+ state_mutability: "view"
3120
+ },
3121
+ {
3122
+ type: "function",
3123
+ name: "tournament",
3124
+ inputs: [
3125
+ {
3126
+ name: "tournament_id",
3127
+ type: "core::integer::u64"
3128
+ }
3129
+ ],
3130
+ outputs: [
3131
+ {
3132
+ type: "budokan_interfaces::budokan::Tournament"
3133
+ }
3134
+ ],
3135
+ state_mutability: "view"
3136
+ },
3137
+ {
3138
+ type: "function",
3139
+ name: "tournament_entries",
3140
+ inputs: [
3141
+ {
3142
+ name: "tournament_id",
3143
+ type: "core::integer::u64"
3144
+ }
3145
+ ],
3146
+ outputs: [
3147
+ {
3148
+ type: "core::integer::u32"
3149
+ }
3150
+ ],
3151
+ state_mutability: "view"
3152
+ },
3153
+ {
3154
+ type: "function",
3155
+ name: "get_leaderboard",
3156
+ inputs: [
3157
+ {
3158
+ name: "tournament_id",
3159
+ type: "core::integer::u64"
3160
+ }
3161
+ ],
3162
+ outputs: [
3163
+ {
3164
+ type: "core::array::Array::<core::felt252>"
3165
+ }
3166
+ ],
3167
+ state_mutability: "view"
3168
+ },
3169
+ {
3170
+ type: "function",
3171
+ name: "current_phase",
3172
+ inputs: [
3173
+ {
3174
+ name: "tournament_id",
3175
+ type: "core::integer::u64"
3176
+ }
3177
+ ],
3178
+ outputs: [
3179
+ {
3180
+ type: "budokan_interfaces::budokan::Phase"
3181
+ }
3182
+ ],
3183
+ state_mutability: "view"
3184
+ },
3185
+ {
3186
+ type: "function",
3187
+ name: "tournament_distribution_shares",
3188
+ inputs: [
3189
+ {
3190
+ name: "tournament_id",
3191
+ type: "core::integer::u64"
3192
+ }
3193
+ ],
3194
+ outputs: [
3195
+ {
3196
+ type: "core::array::Array::<core::integer::u16>"
3197
+ }
3198
+ ],
3199
+ state_mutability: "view"
3200
+ },
3201
+ {
3202
+ type: "function",
3203
+ name: "create_tournament",
3204
+ inputs: [
3205
+ {
3206
+ name: "creator_rewards_address",
3207
+ type: "core::starknet::contract_address::ContractAddress"
3208
+ },
3209
+ {
3210
+ name: "metadata",
3211
+ type: "budokan_interfaces::budokan::Metadata"
3212
+ },
3213
+ {
3214
+ name: "schedule",
3215
+ type: "budokan_interfaces::budokan::Schedule"
3216
+ },
3217
+ {
3218
+ name: "game_config",
3219
+ type: "budokan_interfaces::budokan::GameConfig"
3220
+ },
3221
+ {
3222
+ name: "entry_fee",
3223
+ type: "core::option::Option::<budokan_interfaces::budokan::EntryFee>"
3224
+ },
3225
+ {
3226
+ name: "entry_requirement",
3227
+ type: "core::option::Option::<game_components_interfaces::entry_requirement::EntryRequirement>"
3228
+ },
3229
+ {
3230
+ name: "leaderboard_config",
3231
+ type: "budokan_interfaces::budokan::LeaderboardConfig"
3232
+ },
3233
+ {
3234
+ name: "salt",
3235
+ type: "core::integer::u16"
3236
+ },
3237
+ {
3238
+ name: "metadata_value",
3239
+ type: "core::integer::u16"
3240
+ }
3241
+ ],
3242
+ outputs: [
3243
+ {
3244
+ type: "budokan_interfaces::budokan::Tournament"
3245
+ }
3246
+ ],
3247
+ state_mutability: "external"
3248
+ },
3249
+ {
3250
+ type: "function",
3251
+ name: "enter_tournament",
3252
+ inputs: [
3253
+ {
3254
+ name: "tournament_id",
3255
+ type: "core::integer::u64"
3256
+ },
3257
+ {
3258
+ name: "player_name",
3259
+ type: "core::felt252"
3260
+ },
3261
+ {
3262
+ name: "player_address",
3263
+ type: "core::starknet::contract_address::ContractAddress"
3264
+ },
3265
+ {
3266
+ name: "qualification",
3267
+ type: "core::option::Option::<game_components_interfaces::entry_requirement::QualificationProof>"
3268
+ },
3269
+ {
3270
+ name: "salt",
3271
+ type: "core::integer::u16"
3272
+ },
3273
+ {
3274
+ name: "metadata_value",
3275
+ type: "core::integer::u16"
3276
+ }
3277
+ ],
3278
+ outputs: [
3279
+ {
3280
+ type: "(core::felt252, core::integer::u32)"
3281
+ }
3282
+ ],
3283
+ state_mutability: "external"
3284
+ },
3285
+ {
3286
+ type: "function",
3287
+ name: "ban_entry",
3288
+ inputs: [
3289
+ {
3290
+ name: "tournament_id",
3291
+ type: "core::integer::u64"
3292
+ },
3293
+ {
3294
+ name: "game_token_id",
3295
+ type: "core::felt252"
3296
+ },
3297
+ {
3298
+ name: "proof",
3299
+ type: "core::array::Span::<core::felt252>"
3300
+ }
3301
+ ],
3302
+ outputs: [],
3303
+ state_mutability: "external"
3304
+ },
3305
+ {
3306
+ type: "function",
3307
+ name: "submit_score",
3308
+ inputs: [
3309
+ {
3310
+ name: "tournament_id",
3311
+ type: "core::integer::u64"
3312
+ },
3313
+ {
3314
+ name: "token_id",
3315
+ type: "core::felt252"
3316
+ },
3317
+ {
3318
+ name: "position",
3319
+ type: "core::integer::u32"
3320
+ }
3321
+ ],
3322
+ outputs: [],
3323
+ state_mutability: "external"
3324
+ },
3325
+ {
3326
+ type: "function",
3327
+ name: "claim_reward",
3328
+ inputs: [
3329
+ {
3330
+ name: "tournament_id",
3331
+ type: "core::integer::u64"
3332
+ },
3333
+ {
3334
+ name: "reward_type",
3335
+ type: "budokan_interfaces::budokan::RewardType"
3336
+ }
3337
+ ],
3338
+ outputs: [],
3339
+ state_mutability: "external"
3340
+ },
3341
+ {
3342
+ type: "function",
3343
+ name: "add_prize",
3344
+ inputs: [
3345
+ {
3346
+ name: "tournament_id",
3347
+ type: "core::integer::u64"
3348
+ },
3349
+ {
3350
+ name: "token_address",
3351
+ type: "core::starknet::contract_address::ContractAddress"
3352
+ },
3353
+ {
3354
+ name: "token_type",
3355
+ type: "game_components_interfaces::prize::TokenTypeData"
3356
+ },
3357
+ {
3358
+ name: "position",
3359
+ type: "core::option::Option::<core::integer::u32>"
3360
+ }
3361
+ ],
3362
+ outputs: [
3363
+ {
3364
+ type: "game_components_interfaces::prize::PrizeData"
3365
+ }
3366
+ ],
3367
+ state_mutability: "external"
3368
+ }
3369
+ ]
3370
+ },
3371
+ {
3372
+ type: "impl",
3373
+ name: "MetagameImpl",
3374
+ interface_name: "game_components_interfaces::metagame::core::IMetagame"
3375
+ },
3376
+ {
3377
+ type: "interface",
3378
+ name: "game_components_interfaces::metagame::core::IMetagame",
3379
+ items: [
3380
+ {
3381
+ type: "function",
3382
+ name: "context_address",
3383
+ inputs: [],
3384
+ outputs: [
3385
+ {
3386
+ type: "core::starknet::contract_address::ContractAddress"
3387
+ }
3388
+ ],
3389
+ state_mutability: "view"
3390
+ },
3391
+ {
3392
+ type: "function",
3393
+ name: "default_token_address",
3394
+ inputs: [],
3395
+ outputs: [
3396
+ {
3397
+ type: "core::starknet::contract_address::ContractAddress"
3398
+ }
3399
+ ],
3400
+ state_mutability: "view"
3401
+ }
3402
+ ]
3403
+ },
3404
+ {
3405
+ type: "impl",
3406
+ name: "SRC5Impl",
3407
+ interface_name: "openzeppelin_interfaces::introspection::ISRC5"
3408
+ },
3409
+ {
3410
+ type: "interface",
3411
+ name: "openzeppelin_interfaces::introspection::ISRC5",
3412
+ items: [
3413
+ {
3414
+ type: "function",
3415
+ name: "supports_interface",
3416
+ inputs: [
3417
+ {
3418
+ name: "interface_id",
3419
+ type: "core::felt252"
3420
+ }
3421
+ ],
3422
+ outputs: [
3423
+ {
3424
+ type: "core::bool"
3425
+ }
3426
+ ],
3427
+ state_mutability: "view"
3428
+ }
3429
+ ]
3430
+ },
3431
+ {
3432
+ type: "impl",
3433
+ name: "OwnableImpl",
3434
+ interface_name: "openzeppelin_interfaces::access::ownable::IOwnable"
3435
+ },
3436
+ {
3437
+ type: "interface",
3438
+ name: "openzeppelin_interfaces::access::ownable::IOwnable",
3439
+ items: [
3440
+ {
3441
+ type: "function",
3442
+ name: "owner",
3443
+ inputs: [],
3444
+ outputs: [
3445
+ {
3446
+ type: "core::starknet::contract_address::ContractAddress"
3447
+ }
3448
+ ],
3449
+ state_mutability: "view"
3450
+ },
3451
+ {
3452
+ type: "function",
3453
+ name: "transfer_ownership",
3454
+ inputs: [
3455
+ {
3456
+ name: "new_owner",
3457
+ type: "core::starknet::contract_address::ContractAddress"
3458
+ }
3459
+ ],
3460
+ outputs: [],
3461
+ state_mutability: "external"
3462
+ },
3463
+ {
3464
+ type: "function",
3465
+ name: "renounce_ownership",
3466
+ inputs: [],
3467
+ outputs: [],
3468
+ state_mutability: "external"
3469
+ }
3470
+ ]
3471
+ },
3472
+ {
3473
+ type: "impl",
3474
+ name: "EntryFeeImpl",
3475
+ interface_name: "game_components_interfaces::entry_fee::IEntryFee"
3476
+ },
3477
+ {
3478
+ type: "enum",
3479
+ name: "core::option::Option::<core::integer::u16>",
3480
+ variants: [
3481
+ {
3482
+ name: "Some",
3483
+ type: "core::integer::u16"
3484
+ },
3485
+ {
3486
+ name: "None",
3487
+ type: "()"
3488
+ }
3489
+ ]
3490
+ },
3491
+ {
3492
+ type: "struct",
3493
+ name: "game_components_interfaces::entry_fee::AdditionalShare",
3494
+ members: [
3495
+ {
3496
+ name: "recipient",
3497
+ type: "core::starknet::contract_address::ContractAddress"
3498
+ },
3499
+ {
3500
+ name: "share_bps",
3501
+ type: "core::integer::u16"
3502
+ }
3503
+ ]
3504
+ },
3505
+ {
3506
+ type: "struct",
3507
+ name: "core::array::Span::<game_components_interfaces::entry_fee::AdditionalShare>",
3508
+ members: [
3509
+ {
3510
+ name: "snapshot",
3511
+ type: "@core::array::Array::<game_components_interfaces::entry_fee::AdditionalShare>"
3512
+ }
3513
+ ]
3514
+ },
3515
+ {
3516
+ type: "struct",
3517
+ name: "game_components_interfaces::entry_fee::EntryFeeConfig",
3518
+ members: [
3519
+ {
3520
+ name: "token_address",
3521
+ type: "core::starknet::contract_address::ContractAddress"
3522
+ },
3523
+ {
3524
+ name: "amount",
3525
+ type: "core::integer::u128"
3526
+ },
3527
+ {
3528
+ name: "game_creator_share",
3529
+ type: "core::option::Option::<core::integer::u16>"
3530
+ },
3531
+ {
3532
+ name: "refund_share",
3533
+ type: "core::option::Option::<core::integer::u16>"
3534
+ },
3535
+ {
3536
+ name: "additional_shares",
3537
+ type: "core::array::Span::<game_components_interfaces::entry_fee::AdditionalShare>"
3538
+ }
3539
+ ]
3540
+ },
3541
+ {
3542
+ type: "enum",
3543
+ name: "core::option::Option::<game_components_interfaces::entry_fee::EntryFeeConfig>",
3544
+ variants: [
3545
+ {
3546
+ name: "Some",
3547
+ type: "game_components_interfaces::entry_fee::EntryFeeConfig"
3548
+ },
3549
+ {
3550
+ name: "None",
3551
+ type: "()"
3552
+ }
3553
+ ]
3554
+ },
3555
+ {
3556
+ type: "interface",
3557
+ name: "game_components_interfaces::entry_fee::IEntryFee",
3558
+ items: [
3559
+ {
3560
+ type: "function",
3561
+ name: "get_entry_fee",
3562
+ inputs: [
3563
+ {
3564
+ name: "context_id",
3565
+ type: "core::integer::u64"
3566
+ }
3567
+ ],
3568
+ outputs: [
3569
+ {
3570
+ type: "core::option::Option::<game_components_interfaces::entry_fee::EntryFeeConfig>"
3571
+ }
3572
+ ],
3573
+ state_mutability: "view"
3574
+ }
3575
+ ]
3576
+ },
3577
+ {
3578
+ type: "impl",
3579
+ name: "EntryRequirementImpl",
3580
+ interface_name: "game_components_interfaces::entry_requirement::IEntryRequirement"
3581
+ },
3582
+ {
3583
+ type: "struct",
3584
+ name: "game_components_interfaces::entry_requirement::QualificationEntries",
3585
+ members: [
3586
+ {
3587
+ name: "context_id",
3588
+ type: "core::integer::u64"
3589
+ },
3590
+ {
3591
+ name: "qualification_proof",
3592
+ type: "game_components_interfaces::entry_requirement::QualificationProof"
3593
+ },
3594
+ {
3595
+ name: "entry_count",
3596
+ type: "core::integer::u32"
3597
+ }
3598
+ ]
3599
+ },
3600
+ {
3601
+ type: "interface",
3602
+ name: "game_components_interfaces::entry_requirement::IEntryRequirement",
3603
+ items: [
3604
+ {
3605
+ type: "function",
3606
+ name: "get_entry_requirement",
3607
+ inputs: [
3608
+ {
3609
+ name: "context_id",
3610
+ type: "core::integer::u64"
3611
+ }
3612
+ ],
3613
+ outputs: [
3614
+ {
3615
+ type: "core::option::Option::<game_components_interfaces::entry_requirement::EntryRequirement>"
3616
+ }
3617
+ ],
3618
+ state_mutability: "view"
3619
+ },
3620
+ {
3621
+ type: "function",
3622
+ name: "get_qualification_entries",
3623
+ inputs: [
3624
+ {
3625
+ name: "context_id",
3626
+ type: "core::integer::u64"
3627
+ },
3628
+ {
3629
+ name: "proof",
3630
+ type: "game_components_interfaces::entry_requirement::QualificationProof"
3631
+ }
3632
+ ],
3633
+ outputs: [
3634
+ {
3635
+ type: "game_components_interfaces::entry_requirement::QualificationEntries"
3636
+ }
3637
+ ],
3638
+ state_mutability: "view"
3639
+ }
3640
+ ]
3641
+ },
3642
+ {
3643
+ type: "impl",
3644
+ name: "PrizeImpl",
3645
+ interface_name: "game_components_interfaces::prize::IPrize"
3646
+ },
3647
+ {
3648
+ type: "interface",
3649
+ name: "game_components_interfaces::prize::IPrize",
3650
+ items: [
3651
+ {
3652
+ type: "function",
3653
+ name: "get_prize",
3654
+ inputs: [
3655
+ {
3656
+ name: "prize_id",
3657
+ type: "core::integer::u64"
3658
+ }
3659
+ ],
3660
+ outputs: [
3661
+ {
3662
+ type: "game_components_interfaces::prize::PrizeData"
3663
+ }
3664
+ ],
3665
+ state_mutability: "view"
3666
+ },
3667
+ {
3668
+ type: "function",
3669
+ name: "get_total_prizes",
3670
+ inputs: [],
3671
+ outputs: [
3672
+ {
3673
+ type: "core::integer::u64"
3674
+ }
3675
+ ],
3676
+ state_mutability: "view"
3677
+ },
3678
+ {
3679
+ type: "function",
3680
+ name: "is_prize_claimed",
3681
+ inputs: [
3682
+ {
3683
+ name: "context_id",
3684
+ type: "core::integer::u64"
3685
+ },
3686
+ {
3687
+ name: "prize_type",
3688
+ type: "game_components_interfaces::prize::PrizeType"
3689
+ }
3690
+ ],
3691
+ outputs: [
3692
+ {
3693
+ type: "core::bool"
3694
+ }
3695
+ ],
3696
+ state_mutability: "view"
3697
+ }
3698
+ ]
3699
+ },
3700
+ {
3701
+ type: "impl",
3702
+ name: "RegistrationImpl",
3703
+ interface_name: "game_components_interfaces::registration::IRegistration"
3704
+ },
3705
+ {
3706
+ type: "struct",
3707
+ name: "game_components_interfaces::registration::Registration",
3708
+ members: [
3709
+ {
3710
+ name: "context_id",
3711
+ type: "core::integer::u64"
3712
+ },
3713
+ {
3714
+ name: "entry_id",
3715
+ type: "core::integer::u32"
3716
+ },
3717
+ {
3718
+ name: "game_token_id",
3719
+ type: "core::felt252"
3720
+ },
3721
+ {
3722
+ name: "has_submitted",
3723
+ type: "core::bool"
3724
+ },
3725
+ {
3726
+ name: "is_banned",
3727
+ type: "core::bool"
3728
+ }
3729
+ ]
3730
+ },
3731
+ {
3732
+ type: "interface",
3733
+ name: "game_components_interfaces::registration::IRegistration",
3734
+ items: [
3735
+ {
3736
+ type: "function",
3737
+ name: "get_entry",
3738
+ inputs: [
3739
+ {
3740
+ name: "context_id",
3741
+ type: "core::integer::u64"
3742
+ },
3743
+ {
3744
+ name: "entry_id",
3745
+ type: "core::integer::u32"
3746
+ }
3747
+ ],
3748
+ outputs: [
3749
+ {
3750
+ type: "game_components_interfaces::registration::Registration"
3751
+ }
3752
+ ],
3753
+ state_mutability: "view"
3754
+ },
3755
+ {
3756
+ type: "function",
3757
+ name: "entry_exists",
3758
+ inputs: [
3759
+ {
3760
+ name: "context_id",
3761
+ type: "core::integer::u64"
3762
+ },
3763
+ {
3764
+ name: "entry_id",
3765
+ type: "core::integer::u32"
3766
+ }
3767
+ ],
3768
+ outputs: [
3769
+ {
3770
+ type: "core::bool"
3771
+ }
3772
+ ],
3773
+ state_mutability: "view"
3774
+ },
3775
+ {
3776
+ type: "function",
3777
+ name: "is_entry_banned",
3778
+ inputs: [
3779
+ {
3780
+ name: "context_id",
3781
+ type: "core::integer::u64"
3782
+ },
3783
+ {
3784
+ name: "entry_id",
3785
+ type: "core::integer::u32"
3786
+ }
3787
+ ],
3788
+ outputs: [
3789
+ {
3790
+ type: "core::bool"
3791
+ }
3792
+ ],
3793
+ state_mutability: "view"
3794
+ },
3795
+ {
3796
+ type: "function",
3797
+ name: "get_entry_count",
3798
+ inputs: [
3799
+ {
3800
+ name: "context_id",
3801
+ type: "core::integer::u64"
3802
+ }
3803
+ ],
3804
+ outputs: [
3805
+ {
3806
+ type: "core::integer::u32"
3807
+ }
3808
+ ],
3809
+ state_mutability: "view"
3810
+ }
3811
+ ]
3812
+ },
3813
+ {
3814
+ type: "constructor",
3815
+ name: "constructor",
3816
+ inputs: [
3817
+ {
3818
+ name: "owner",
3819
+ type: "core::starknet::contract_address::ContractAddress"
3820
+ },
3821
+ {
3822
+ name: "default_token_address",
3823
+ type: "core::starknet::contract_address::ContractAddress"
3824
+ }
3825
+ ]
3826
+ },
3827
+ {
3828
+ type: "event",
3829
+ name: "game_components_embeddable_game_standard::metagame::metagame_component::MetagameComponent::Event",
3830
+ kind: "enum",
3831
+ variants: []
3832
+ },
3833
+ {
3834
+ type: "event",
3835
+ name: "game_components_embeddable_game_standard::metagame::extensions::context::context::ContextComponent::Event",
3836
+ kind: "enum",
3837
+ variants: []
3838
+ },
3839
+ {
3840
+ type: "event",
3841
+ name: "openzeppelin_introspection::src5::SRC5Component::Event",
3842
+ kind: "enum",
3843
+ variants: []
3844
+ },
3845
+ {
3846
+ type: "event",
3847
+ name: "game_components_metagame::leaderboard::leaderboard_component::LeaderboardComponent::Event",
3848
+ kind: "enum",
3849
+ variants: []
3850
+ },
3851
+ {
3852
+ type: "event",
3853
+ name: "openzeppelin_access::ownable::ownable::OwnableComponent::OwnershipTransferred",
3854
+ kind: "struct",
3855
+ members: [
3856
+ {
3857
+ name: "previous_owner",
3858
+ type: "core::starknet::contract_address::ContractAddress",
3859
+ kind: "key"
3860
+ },
3861
+ {
3862
+ name: "new_owner",
3863
+ type: "core::starknet::contract_address::ContractAddress",
3864
+ kind: "key"
3865
+ }
3866
+ ]
3867
+ },
3868
+ {
3869
+ type: "event",
3870
+ name: "openzeppelin_access::ownable::ownable::OwnableComponent::OwnershipTransferStarted",
3871
+ kind: "struct",
3872
+ members: [
3873
+ {
3874
+ name: "previous_owner",
3875
+ type: "core::starknet::contract_address::ContractAddress",
3876
+ kind: "key"
3877
+ },
3878
+ {
3879
+ name: "new_owner",
3880
+ type: "core::starknet::contract_address::ContractAddress",
3881
+ kind: "key"
3882
+ }
3883
+ ]
3884
+ },
3885
+ {
3886
+ type: "event",
3887
+ name: "openzeppelin_access::ownable::ownable::OwnableComponent::Event",
3888
+ kind: "enum",
3889
+ variants: [
3890
+ {
3891
+ name: "OwnershipTransferred",
3892
+ type: "openzeppelin_access::ownable::ownable::OwnableComponent::OwnershipTransferred",
3893
+ kind: "nested"
3894
+ },
3895
+ {
3896
+ name: "OwnershipTransferStarted",
3897
+ type: "openzeppelin_access::ownable::ownable::OwnableComponent::OwnershipTransferStarted",
3898
+ kind: "nested"
3899
+ }
3900
+ ]
3901
+ },
3902
+ {
3903
+ type: "event",
3904
+ name: "openzeppelin_upgrades::upgradeable::UpgradeableComponent::Upgraded",
3905
+ kind: "struct",
3906
+ members: [
3907
+ {
3908
+ name: "class_hash",
3909
+ type: "core::starknet::class_hash::ClassHash",
3910
+ kind: "data"
3911
+ }
3912
+ ]
3913
+ },
3914
+ {
3915
+ type: "event",
3916
+ name: "openzeppelin_upgrades::upgradeable::UpgradeableComponent::Event",
3917
+ kind: "enum",
3918
+ variants: [
3919
+ {
3920
+ name: "Upgraded",
3921
+ type: "openzeppelin_upgrades::upgradeable::UpgradeableComponent::Upgraded",
3922
+ kind: "nested"
3923
+ }
3924
+ ]
3925
+ },
3926
+ {
3927
+ type: "event",
3928
+ name: "game_components_metagame::registration::registration_component::RegistrationComponent::Event",
3929
+ kind: "enum",
3930
+ variants: []
3931
+ },
3932
+ {
3933
+ type: "event",
3934
+ name: "game_components_metagame::entry_fee::entry_fee_component::EntryFeeComponent::Event",
3935
+ kind: "enum",
3936
+ variants: []
3937
+ },
3938
+ {
3939
+ type: "event",
3940
+ name: "game_components_metagame::entry_requirement::entry_requirement_component::EntryRequirementComponent::Event",
3941
+ kind: "enum",
3942
+ variants: []
3943
+ },
3944
+ {
3945
+ type: "event",
3946
+ name: "game_components_metagame::prize::prize_component::PrizeComponent::Event",
3947
+ kind: "enum",
3948
+ variants: []
3949
+ },
3950
+ {
3951
+ type: "event",
3952
+ name: "budokan::events::TournamentCreated",
3953
+ kind: "struct",
3954
+ members: [
3955
+ {
3956
+ name: "tournament_id",
3957
+ type: "core::integer::u64",
3958
+ kind: "key"
3959
+ },
3960
+ {
3961
+ name: "game_address",
3962
+ type: "core::starknet::contract_address::ContractAddress",
3963
+ kind: "key"
3964
+ },
3965
+ {
3966
+ name: "created_at",
3967
+ type: "core::integer::u64",
3968
+ kind: "data"
3969
+ },
3970
+ {
3971
+ name: "created_by",
3972
+ type: "core::starknet::contract_address::ContractAddress",
3973
+ kind: "data"
3974
+ },
3975
+ {
3976
+ name: "creator_token_id",
3977
+ type: "core::felt252",
3978
+ kind: "data"
3979
+ },
3980
+ {
3981
+ name: "metadata",
3982
+ type: "budokan_interfaces::budokan::Metadata",
3983
+ kind: "data"
3984
+ },
3985
+ {
3986
+ name: "schedule",
3987
+ type: "budokan_interfaces::budokan::Schedule",
3988
+ kind: "data"
3989
+ },
3990
+ {
3991
+ name: "game_config",
3992
+ type: "budokan_interfaces::budokan::GameConfig",
3993
+ kind: "data"
3994
+ },
3995
+ {
3996
+ name: "entry_fee",
3997
+ type: "core::option::Option::<budokan_interfaces::budokan::EntryFee>",
3998
+ kind: "data"
3999
+ },
4000
+ {
4001
+ name: "entry_requirement",
4002
+ type: "core::option::Option::<game_components_interfaces::entry_requirement::EntryRequirement>",
4003
+ kind: "data"
4004
+ },
4005
+ {
4006
+ name: "leaderboard_config",
4007
+ type: "budokan_interfaces::budokan::LeaderboardConfig",
4008
+ kind: "data"
4009
+ }
4010
+ ]
4011
+ },
4012
+ {
4013
+ type: "event",
4014
+ name: "budokan::events::TournamentRegistration",
4015
+ kind: "struct",
4016
+ members: [
4017
+ {
4018
+ name: "tournament_id",
4019
+ type: "core::integer::u64",
4020
+ kind: "key"
4021
+ },
4022
+ {
4023
+ name: "game_token_id",
4024
+ type: "core::felt252",
4025
+ kind: "key"
4026
+ },
4027
+ {
4028
+ name: "game_address",
4029
+ type: "core::starknet::contract_address::ContractAddress",
4030
+ kind: "data"
4031
+ },
4032
+ {
4033
+ name: "player_address",
4034
+ type: "core::starknet::contract_address::ContractAddress",
4035
+ kind: "data"
4036
+ },
4037
+ {
4038
+ name: "entry_number",
4039
+ type: "core::integer::u32",
4040
+ kind: "data"
4041
+ },
4042
+ {
4043
+ name: "has_submitted",
4044
+ type: "core::bool",
4045
+ kind: "data"
4046
+ },
4047
+ {
4048
+ name: "is_banned",
4049
+ type: "core::bool",
4050
+ kind: "data"
4051
+ }
4052
+ ]
4053
+ },
4054
+ {
4055
+ type: "event",
4056
+ name: "budokan::events::LeaderboardUpdated",
4057
+ kind: "struct",
4058
+ members: [
4059
+ {
4060
+ name: "tournament_id",
4061
+ type: "core::integer::u64",
4062
+ kind: "key"
4063
+ },
4064
+ {
4065
+ name: "token_ids",
4066
+ type: "core::array::Span::<core::felt252>",
4067
+ kind: "data"
4068
+ }
4069
+ ]
4070
+ },
4071
+ {
4072
+ type: "event",
4073
+ name: "budokan::events::PrizeAdded",
4074
+ kind: "struct",
4075
+ members: [
4076
+ {
4077
+ name: "tournament_id",
4078
+ type: "core::integer::u64",
4079
+ kind: "key"
4080
+ },
4081
+ {
4082
+ name: "prize_id",
4083
+ type: "core::integer::u64",
4084
+ kind: "key"
4085
+ },
4086
+ {
4087
+ name: "payout_position",
4088
+ type: "core::integer::u32",
4089
+ kind: "data"
4090
+ },
4091
+ {
4092
+ name: "token_address",
4093
+ type: "core::starknet::contract_address::ContractAddress",
4094
+ kind: "data"
4095
+ },
4096
+ {
4097
+ name: "token_type",
4098
+ type: "game_components_interfaces::prize::TokenTypeData",
4099
+ kind: "data"
4100
+ },
4101
+ {
4102
+ name: "sponsor_address",
4103
+ type: "core::starknet::contract_address::ContractAddress",
4104
+ kind: "data"
4105
+ }
4106
+ ]
4107
+ },
4108
+ {
4109
+ type: "event",
4110
+ name: "budokan::events::RewardClaimed",
4111
+ kind: "struct",
4112
+ members: [
4113
+ {
4114
+ name: "tournament_id",
4115
+ type: "core::integer::u64",
4116
+ kind: "key"
4117
+ },
4118
+ {
4119
+ name: "reward_type",
4120
+ type: "budokan_interfaces::budokan::RewardType",
4121
+ kind: "data"
4122
+ },
4123
+ {
4124
+ name: "claimed",
4125
+ type: "core::bool",
4126
+ kind: "data"
4127
+ }
4128
+ ]
4129
+ },
4130
+ {
4131
+ type: "event",
4132
+ name: "budokan::events::QualificationEntriesUpdated",
4133
+ kind: "struct",
4134
+ members: [
4135
+ {
4136
+ name: "tournament_id",
4137
+ type: "core::integer::u64",
4138
+ kind: "key"
4139
+ },
4140
+ {
4141
+ name: "qualification_proof",
4142
+ type: "game_components_interfaces::entry_requirement::QualificationProof",
4143
+ kind: "data"
4144
+ },
4145
+ {
4146
+ name: "entry_count",
4147
+ type: "core::integer::u32",
4148
+ kind: "data"
4149
+ }
4150
+ ]
4151
+ },
4152
+ {
4153
+ type: "event",
4154
+ name: "budokan::budokan::Budokan::Event",
4155
+ kind: "enum",
4156
+ variants: [
4157
+ {
4158
+ name: "MetagameEvent",
4159
+ type: "game_components_embeddable_game_standard::metagame::metagame_component::MetagameComponent::Event",
4160
+ kind: "flat"
4161
+ },
4162
+ {
4163
+ name: "ContextEvent",
4164
+ type: "game_components_embeddable_game_standard::metagame::extensions::context::context::ContextComponent::Event",
4165
+ kind: "flat"
4166
+ },
4167
+ {
4168
+ name: "SRC5Event",
4169
+ type: "openzeppelin_introspection::src5::SRC5Component::Event",
4170
+ kind: "flat"
4171
+ },
4172
+ {
4173
+ name: "LeaderboardEvent",
4174
+ type: "game_components_metagame::leaderboard::leaderboard_component::LeaderboardComponent::Event",
4175
+ kind: "flat"
4176
+ },
4177
+ {
4178
+ name: "OwnableEvent",
4179
+ type: "openzeppelin_access::ownable::ownable::OwnableComponent::Event",
4180
+ kind: "flat"
4181
+ },
4182
+ {
4183
+ name: "UpgradeableEvent",
4184
+ type: "openzeppelin_upgrades::upgradeable::UpgradeableComponent::Event",
4185
+ kind: "flat"
4186
+ },
4187
+ {
4188
+ name: "RegistrationEvent",
4189
+ type: "game_components_metagame::registration::registration_component::RegistrationComponent::Event",
4190
+ kind: "flat"
4191
+ },
4192
+ {
4193
+ name: "EntryFeeEvent",
4194
+ type: "game_components_metagame::entry_fee::entry_fee_component::EntryFeeComponent::Event",
4195
+ kind: "flat"
4196
+ },
4197
+ {
4198
+ name: "EntryRequirementEvent",
4199
+ type: "game_components_metagame::entry_requirement::entry_requirement_component::EntryRequirementComponent::Event",
4200
+ kind: "flat"
4201
+ },
4202
+ {
4203
+ name: "PrizeEvent",
4204
+ type: "game_components_metagame::prize::prize_component::PrizeComponent::Event",
4205
+ kind: "flat"
4206
+ },
4207
+ {
4208
+ name: "TournamentCreated",
4209
+ type: "budokan::events::TournamentCreated",
4210
+ kind: "nested"
4211
+ },
4212
+ {
4213
+ name: "TournamentRegistration",
4214
+ type: "budokan::events::TournamentRegistration",
4215
+ kind: "nested"
4216
+ },
4217
+ {
4218
+ name: "LeaderboardUpdated",
4219
+ type: "budokan::events::LeaderboardUpdated",
4220
+ kind: "nested"
4221
+ },
4222
+ {
4223
+ name: "PrizeAdded",
4224
+ type: "budokan::events::PrizeAdded",
4225
+ kind: "nested"
4226
+ },
4227
+ {
4228
+ name: "RewardClaimed",
4229
+ type: "budokan::events::RewardClaimed",
4230
+ kind: "nested"
4231
+ },
4232
+ {
4233
+ name: "QualificationEntriesUpdated",
4234
+ type: "budokan::events::QualificationEntriesUpdated",
4235
+ kind: "nested"
4236
+ }
4237
+ ]
4238
+ }
4239
+ ];
4240
+
4241
+ // src/rpc/budokan.ts
4242
+ function wrapRpcCall2(fn, contractAddress) {
4243
+ return fn().catch((error) => {
4244
+ throw new RpcError(
4245
+ error instanceof Error ? error.message : "RPC call failed",
4246
+ contractAddress
4247
+ );
4248
+ });
4249
+ }
4250
+ async function budokanTournamentDistributionShares(contract, tournamentId) {
4251
+ return wrapRpcCall2(async () => {
4252
+ const result = await contract.call("tournament_distribution_shares", [tournamentId]);
4253
+ const arr = Array.isArray(result) ? result : [];
4254
+ return arr.map((v) => Number(v));
4255
+ }, contract.address);
4256
+ }
4257
+
4258
+ // src/client.ts
4259
+ var BudokanClient = class {
4260
+ resolvedConfig;
4261
+ wsManager;
4262
+ connectionStatus;
4263
+ cachedProvider = null;
4264
+ cachedViewerContract = null;
4265
+ cachedBudokanContract = null;
4266
+ constructor(config) {
4267
+ const chainConfig = config.chain ? getChainConfig(config.chain) : void 0;
4268
+ this.resolvedConfig = {
4269
+ ...config,
4270
+ apiBaseUrl: config.apiBaseUrl ?? chainConfig?.apiBaseUrl ?? "",
4271
+ rpcUrl: config.rpcUrl ?? chainConfig?.rpcUrl ?? "",
4272
+ viewerAddress: config.viewerAddress ?? chainConfig?.viewerAddress ?? "",
4273
+ budokanAddress: config.budokanAddress ?? chainConfig?.budokanAddress ?? ""
4274
+ };
4275
+ const wsUrl = config.wsUrl ?? chainConfig?.wsUrl ?? this.resolvedConfig.apiBaseUrl.replace(/^http/, "ws").replace(/\/$/, "") + "/ws";
4276
+ this.wsManager = new WSManager(wsUrl);
4277
+ this.connectionStatus = new ConnectionStatus(
4278
+ this.resolvedConfig.apiBaseUrl,
4279
+ this.resolvedConfig.rpcUrl,
4280
+ config.health
4281
+ );
4282
+ if (this.resolvedConfig.apiBaseUrl && this.resolvedConfig.rpcUrl) {
4283
+ this.connectionStatus.startMonitoring();
4284
+ }
4285
+ }
4286
+ // ---- Configuration ----
4287
+ /** Returns the resolved configuration. */
4288
+ get clientConfig() {
4289
+ return { ...this.resolvedConfig };
4290
+ }
4291
+ /** Whether the WebSocket is currently connected. */
4292
+ get wsConnected() {
4293
+ return this.wsManager.isConnected;
4294
+ }
4295
+ // ---- Connection status ----
4296
+ /** Returns the current connection status (API, RPC, mode). */
4297
+ getConnectionStatus() {
4298
+ return this.connectionStatus.getStatus();
4299
+ }
4300
+ /** Subscribe to connection status changes. Returns an unsubscribe function. */
4301
+ onConnectionStatusChange(listener) {
4302
+ return this.connectionStatus.subscribe(listener);
4303
+ }
4304
+ // ---- Lazy RPC getters ----
4305
+ async getProvider() {
4306
+ if (this.cachedProvider) return this.cachedProvider;
4307
+ if (!this.resolvedConfig.rpcUrl) {
4308
+ throw new RpcError("No rpcUrl configured");
4309
+ }
4310
+ if (this.resolvedConfig.provider) {
4311
+ this.cachedProvider = this.resolvedConfig.provider;
4312
+ return this.cachedProvider;
4313
+ }
4314
+ this.cachedProvider = await createProvider(
4315
+ this.resolvedConfig.rpcUrl,
4316
+ this.resolvedConfig.rpcHeaders
4317
+ );
4318
+ return this.cachedProvider;
4319
+ }
4320
+ async getViewerContract() {
4321
+ if (this.cachedViewerContract) return this.cachedViewerContract;
4322
+ if (!this.resolvedConfig.viewerAddress) {
4323
+ throw new RpcError("No viewerAddress configured. Set viewerAddress in config or use a chain preset with a deployed viewer contract.");
4324
+ }
4325
+ const provider = await this.getProvider();
4326
+ this.cachedViewerContract = await createContract(
4327
+ budokanViewer_default,
4328
+ this.resolvedConfig.viewerAddress,
4329
+ provider
4330
+ );
4331
+ return this.cachedViewerContract;
4332
+ }
4333
+ async getBudokanContract() {
4334
+ if (this.cachedBudokanContract) return this.cachedBudokanContract;
4335
+ if (!this.resolvedConfig.budokanAddress) {
4336
+ throw new RpcError("No budokanAddress configured. Set budokanAddress in config or use a chain preset with a deployed Budokan contract.");
4337
+ }
4338
+ const provider = await this.getProvider();
4339
+ this.cachedBudokanContract = await createContract(
4340
+ budokan_default,
4341
+ this.resolvedConfig.budokanAddress,
4342
+ provider
4343
+ );
4344
+ return this.cachedBudokanContract;
4345
+ }
4346
+ // ---- API context ----
4347
+ get apiCtx() {
4348
+ return {
4349
+ retryAttempts: this.resolvedConfig.retryAttempts,
4350
+ retryDelay: this.resolvedConfig.retryDelay,
4351
+ timeout: this.resolvedConfig.timeout
4352
+ };
4353
+ }
4354
+ // ---- Tournament Queries ----
4355
+ /**
4356
+ * Fetch a paginated list of tournaments with optional filtering.
4357
+ * Supports RPC fallback when API is unavailable.
4358
+ */
4359
+ async getTournaments(params) {
4360
+ const rpcFallback = async () => {
4361
+ const contract = await this.getViewerContract();
4362
+ const offset = params?.offset ?? 0;
4363
+ const limit = params?.limit ?? 20;
4364
+ let filterResult;
4365
+ if (params?.phase) {
4366
+ filterResult = await viewerTournamentsByPhase(contract, params.phase, offset, limit);
4367
+ } else if (params?.gameAddress) {
4368
+ filterResult = await viewerTournamentsByGame(contract, params.gameAddress, offset, limit);
4369
+ } else if (params?.creator) {
4370
+ filterResult = await viewerTournamentsByCreator(contract, params.creator, offset, limit);
4371
+ } else {
4372
+ filterResult = await viewerTournaments(contract, offset, limit);
4373
+ }
4374
+ let data = [];
4375
+ if (filterResult.tournamentIds.length > 0) {
4376
+ data = await viewerTournamentsBatch(contract, filterResult.tournamentIds);
4377
+ if (params?.includePrizeSummary) {
4378
+ const prizePromises = data.map(
4379
+ (t) => viewerPrizes(contract, t.id).catch(() => [])
4380
+ );
4381
+ const allPrizes = await Promise.all(prizePromises);
4382
+ data = data.map((t, i) => {
4383
+ const prizes = allPrizes[i];
4384
+ if (prizes.length === 0) return t;
4385
+ const tokenMap = /* @__PURE__ */ new Map();
4386
+ for (const p of prizes) {
4387
+ const key = p.tokenAddress;
4388
+ const existing = tokenMap.get(key);
4389
+ if (existing) {
4390
+ existing.totalAmount += BigInt(p.amount ?? "0");
4391
+ if (p.tokenType === "erc721") existing.nftCount += 1;
4392
+ } else {
4393
+ tokenMap.set(key, {
4394
+ tokenAddress: p.tokenAddress,
4395
+ tokenType: p.tokenType,
4396
+ totalAmount: BigInt(p.amount ?? "0"),
4397
+ nftCount: p.tokenType === "erc721" ? 1 : 0
4398
+ });
4399
+ }
4400
+ }
4401
+ return {
4402
+ ...t,
4403
+ prizeAggregation: Array.from(tokenMap.values()).map((v) => ({
4404
+ tokenAddress: v.tokenAddress,
4405
+ tokenType: v.tokenType,
4406
+ totalAmount: v.totalAmount.toString(),
4407
+ nftCount: v.nftCount
4408
+ }))
4409
+ };
4410
+ });
4411
+ }
4412
+ }
4413
+ return { data, total: filterResult.total, limit, offset };
4414
+ };
4415
+ if (this.resolvedConfig.primarySource === "rpc") {
4416
+ return rpcFallback();
4417
+ }
4418
+ return withFallback(
4419
+ () => getTournaments(this.resolvedConfig.apiBaseUrl, params, this.apiCtx),
4420
+ rpcFallback,
4421
+ this.connectionStatus
4422
+ );
4423
+ }
4424
+ /**
4425
+ * Fetch a single tournament by its ID.
4426
+ * Supports RPC fallback when API is unavailable.
4427
+ *
4428
+ * On the RPC-fallback path, Custom distribution shares are populated via
4429
+ * a follow-up call to `tournament_distribution_shares(id)` so callers see
4430
+ * the same shape regardless of data source (the API/indexer path fills
4431
+ * shares from the `TournamentCreated` event).
4432
+ */
4433
+ async getTournament(tournamentId) {
4434
+ const rpcFallback = async () => {
4435
+ const contract = await this.getViewerContract();
4436
+ const tournament = await viewerTournamentDetail(contract, tournamentId);
4437
+ if (tournament) {
4438
+ await this.fillCustomSharesIfEmpty(tournament);
4439
+ }
4440
+ return tournament;
4441
+ };
4442
+ if (this.resolvedConfig.primarySource === "rpc") {
4443
+ return rpcFallback();
4444
+ }
4445
+ try {
4446
+ return await getTournament(this.resolvedConfig.apiBaseUrl, tournamentId, this.apiCtx);
4447
+ } catch {
4448
+ try {
4449
+ this.connectionStatus.markApiUnavailable();
4450
+ return await rpcFallback();
4451
+ } catch {
4452
+ return null;
4453
+ }
4454
+ }
4455
+ }
4456
+ /**
4457
+ * If the tournament's entry-fee distribution is `Custom` with an empty
4458
+ * shares array (the on-chain `tournament()` view returns empty spans by
4459
+ * design to keep the hot path small), fetch the shares via the
4460
+ * dedicated view and graft them back onto the distribution object.
4461
+ *
4462
+ * Detection is tolerant: the Distribution shape may appear as
4463
+ * `{ variant: { Custom: [] } }` or a flattened `{ Custom: [] }`
4464
+ * depending on the starknet.js version / serialization path.
4465
+ */
4466
+ async fillCustomSharesIfEmpty(tournament) {
4467
+ const dist = tournament.entryFee?.distribution;
4468
+ if (!dist || typeof dist !== "object") return;
4469
+ const bag = dist.variant ?? dist;
4470
+ const customValue = bag.Custom ?? bag.custom;
4471
+ if (!Array.isArray(customValue) || customValue.length > 0) return;
4472
+ try {
4473
+ const shares = await this.getTournamentDistributionShares(tournament.id);
4474
+ if (shares.length > 0) {
4475
+ bag.Custom = shares;
4476
+ }
4477
+ } catch {
4478
+ }
4479
+ }
4480
+ /**
4481
+ * Fetch the Custom distribution shares for a tournament via the Budokan
4482
+ * contract's `tournament_distribution_shares(id)` view.
4483
+ *
4484
+ * Returns an empty array for tournaments configured with
4485
+ * `Linear` / `Exponential` / `Uniform` distributions (those don't have a
4486
+ * shares array), and for tournaments without an entry fee.
4487
+ *
4488
+ * This is a direct RPC call — consumers going through the primary API
4489
+ * path typically don't need it, since the indexer sources Custom shares
4490
+ * from the `TournamentCreated` event and exposes them via
4491
+ * `getTournament()`'s `entryFee.distribution`. Use this when you need a
4492
+ * fresh on-chain read or you're operating in RPC-only mode.
4493
+ */
4494
+ async getTournamentDistributionShares(tournamentId) {
4495
+ const contract = await this.getBudokanContract();
4496
+ return budokanTournamentDistributionShares(contract, tournamentId);
2566
4497
  }
2567
4498
  /**
2568
4499
  * Fetch the leaderboard for a tournament.