@provable-games/budokan-sdk 0.1.13 → 0.1.16

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