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