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