bb-api-platforma 0.1.191 → 0.1.205

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.
@@ -61,6 +61,7 @@ const languageIdsRemote = {
61
61
  // cr: 6,
62
62
  // ru: 0,
63
63
  // }
64
+ const MAX_TIME_EXECUTION_MS = 25000;
64
65
  const stringify = (obj) => {
65
66
  return JSON.stringify(obj, null, 2);
66
67
  };
@@ -109,11 +110,25 @@ export class BetBoosterApi {
109
110
  this.LANG_DEFAULT = 'en';
110
111
  this.LOCALE_DEFAULT = 'en-EN';
111
112
  this.LANG_ID_DEFAULT = 1;
112
- this.maxTimeExecutionMs = 15000;
113
+ this.maxTimeExecutionMs = MAX_TIME_EXECUTION_MS;
113
114
  this.liveTimestamp = 0;
114
115
  this._liveTimestampReset = false;
115
116
  this.liveRecivedIsFullPackage = false;
116
117
  this.isNotActive = false;
118
+ /** Приоритетные виды спорта для сортировки и отображения на странице [VidSportaRating]*/
119
+ this.primarySports = [5, 1, 3, 4, 8, 6, 263, 265, 2, 16, 17, 18];
120
+ /** Приоритетные страны по видам спорта для сортировки и отображения */
121
+ this.priorityCountries = {
122
+ "1": [14, 8, 54],
123
+ "5": [8, 14, 1, 2, 5, 4, 3, 43, 44, 42, 11, 54],
124
+ "6": [14, 8, 54],
125
+ "8": [8, 14, 54],
126
+ "27": [45, 187],
127
+ };
128
+ /** Приоритетные турниры по видам спорта*/
129
+ this.priorityTournaments = {
130
+ "5": [201, 361, 199, 410, 200, 423, 1141, 1142, 47, 2408, 1688, 2511, 129, 193, 919, 1693, 1134, 2157, 147, 212, 1, 185, 2, 2379, 286, 1216, 99, 1266, 4, 290, 735, 1059, 1100, 1268, 5, 292, 1210, 1366, 700, 1217, 3, 186, 2209, 2431, 288, 1410, 6, 540, 1062, 1223, 1061, 1237, 40, 1235, 2230, 2370, 209, 1278, 470, 1373, 35, 1386, 2229, 2373, 737, 1383, 1412, 1857, 1505, 1858, 11, 1853, 2231, 742, 1382, 49, 1236, 1060, 2364, 624, 15, 1896, 1409, 1493, 1918, 1925, 2283, 1612, 86, 149, 2337, 8, 1213, 19, 1387],
131
+ };
117
132
  // const uri = new URL(baseUrl)
118
133
  IS_DEV_MODE = isDev;
119
134
  // this._ENDPOINT_DOMAIN = uri.origin;
@@ -465,6 +480,89 @@ export class BetBoosterApi {
465
480
  // return `${this._baseUrl}${this._APIv1}${apiPath}`
466
481
  }
467
482
  }
483
+ /**
484
+ * Сортирует данные по приоритету, указанному в массиве priorityIDs.
485
+ *
486
+ * @template T - Тип объектов в массиве данных
487
+ * @param {Array<T>} data - Массив объектов данных для сортировки.
488
+ * @param {Array<number|string>} priorityIDs - Массив приоритетных ID для сортировки.
489
+ * @param {keyof T} sortField - Поле объекта, по которому будет производиться сортировка.
490
+ * @returns {Array<T>} - Новый массив отсортированных данных.
491
+ *
492
+ * @example
493
+ * ```typescript
494
+ * interface Tournament {
495
+ * Id: number;
496
+ * Name: string;
497
+ * SportID: number;
498
+ * }
499
+ *
500
+ * const tournaments: Tournament[] = [
501
+ * { Id: 1, Name: 'Premier League', SportID: 5 },
502
+ * { Id: 2, Name: 'La Liga', SportID: 5 },
503
+ * { Id: 3, Name: 'Serie A', SportID: 5 }
504
+ * ];
505
+ *
506
+ * const sortedTournaments = api.sortDataByPriority(
507
+ * tournaments,
508
+ * [3, 1, 2],
509
+ * 'Id'
510
+ * );
511
+ * // Result: [Serie A, Premier League, La Liga]
512
+ * ```
513
+ */
514
+ sortDataByPriority(data, priorityIDs, sortField) {
515
+ const priorityIndex = new Map();
516
+ // Создаем объект для быстрого доступа к индексам приоритетных ID
517
+ priorityIDs.forEach((id, index) => {
518
+ priorityIndex.set(id, index);
519
+ });
520
+ // Сортируем данные, используя объект индексов приоритетов
521
+ return data.slice().sort((a, b) => {
522
+ const aPriority = priorityIndex.has(a[sortField])
523
+ ? priorityIndex.get(a[sortField])
524
+ : Infinity;
525
+ const bPriority = priorityIndex.has(b[sortField])
526
+ ? priorityIndex.get(b[sortField])
527
+ : Infinity;
528
+ return aPriority - bPriority;
529
+ });
530
+ }
531
+ /**
532
+ * Сортирует массив значений по приоритету, указанному в массиве priorityIDs.
533
+ *
534
+ * @template T - Тип элементов массива (number | string)
535
+ * @param {Array<T>} array - Массив значений для сортировки.
536
+ * @param {Array<T>} priorityIDs - Массив приоритетных ID для сортировки.
537
+ * @returns {Array<T>} - Новый массив отсортированных значений.
538
+ *
539
+ * @example
540
+ * ```typescript
541
+ * const sportIds = [1, 5, 3, 8, 2];
542
+ * const prioritySports = [5, 1, 3];
543
+ *
544
+ * const sortedSports = api.sortArrayByPriority(sportIds, prioritySports);
545
+ * // Result: [5, 1, 3, 8, 2]
546
+ * // Elements 5, 1, 3 are sorted by priority, others remain in original order
547
+ * ```
548
+ */
549
+ sortArrayByPriority(array, priorityIDs) {
550
+ const priorityIndex = new Map();
551
+ // Создаем объект для быстрого доступа к индексам приоритетных ID
552
+ priorityIDs.forEach((id, index) => {
553
+ priorityIndex.set(id, index);
554
+ });
555
+ // Сортируем массив, используя объект индексов приоритетов
556
+ return array.slice().sort((a, b) => {
557
+ const aPriority = priorityIndex.has(a)
558
+ ? priorityIndex.get(a)
559
+ : Infinity;
560
+ const bPriority = priorityIndex.has(b)
561
+ ? priorityIndex.get(b)
562
+ : Infinity;
563
+ return aPriority - bPriority;
564
+ });
565
+ }
468
566
  // #endregion Handlers --------------------------------------------------------------------
469
567
  // #region AXIOS --------------------------------------------------------------------------
470
568
  /**
@@ -528,19 +626,48 @@ export class BetBoosterApi {
528
626
  ;
529
627
  };
530
628
  const now = Date.now() + Math.random();
531
- let abortController = new AbortController();
532
- let signal = setTimeout(() => {
533
- abortController.abort();
534
- }, this.maxTimeExecutionMs);
629
+ /**
630
+ * Создает локальный AbortController с автоматическим таймаутом.
631
+ *
632
+ * @param customTimeout - Пользовательский таймаут в миллисекундах. Если не указан, используется значение по умолчанию.
633
+ * @returns Объект с сигналом AbortSignal для отмены запроса.
634
+ *
635
+ * @example
636
+ * ```typescript
637
+ * const { signal } = setupLocalAbortController(5000);
638
+ * const response = await fetch(url, { signal });
639
+ * ```
640
+ */
641
+ const setupLocalAbortController = (customTimeout) => {
642
+ var _a;
643
+ const timeout = (_a = customTimeout !== null && customTimeout !== void 0 ? customTimeout : this.maxTimeExecutionMs) !== null && _a !== void 0 ? _a : MAX_TIME_EXECUTION_MS;
644
+ // const abortControllerTimeout = (timeout * this.maxRetryGotRequests) + 1000;
645
+ const localAbortController = new AbortController();
646
+ const signalTimeout = setTimeout(() => {
647
+ if (!localAbortController.signal.aborted) {
648
+ localAbortController.abort();
649
+ }
650
+ }, timeout);
651
+ const originalClearSignal = () => clearTimeout(signalTimeout);
652
+ localAbortController.signal.addEventListener('abort', () => {
653
+ clearTimeout(signalTimeout);
654
+ }, { once: true });
655
+ return {
656
+ signal: localAbortController.signal,
657
+ clearSignal: originalClearSignal,
658
+ get isAborted() { return localAbortController.signal.aborted; },
659
+ };
660
+ };
661
+ let { signal, clearSignal } = setupLocalAbortController(this.maxTimeExecutionMs);
535
662
  const requestConfig = {
536
663
  url,
537
664
  method: 'GET',
538
665
  params: { _: now },
539
666
  headers: Object.assign({}, (this.token ? { 'X-Token': this.token } : {})),
540
667
  responseType: 'json',
541
- timeout: this.maxTimeExecutionMs,
668
+ // timeout: this.maxTimeExecutionMs, // убираем, потому, что есть signal
542
669
  timeoutErrorMessage: `Request timed out after ${this.maxTimeExecutionMs} ms`,
543
- signal: abortController.signal,
670
+ signal: signal,
544
671
  };
545
672
  return {
546
673
  /**
@@ -566,15 +693,12 @@ export class BetBoosterApi {
566
693
  delete requestConfig.headers;
567
694
  return this;
568
695
  },
569
- setTimeout(timeout = 15000) {
570
- clearTimeout(signal);
571
- abortController = new AbortController();
572
- signal = setTimeout(() => {
573
- abortController.abort();
574
- }, timeout);
575
- requestConfig.timeout = timeout;
696
+ setTimeout(timeout = MAX_TIME_EXECUTION_MS) {
697
+ clearSignal(); // Очищаем signal потому, что переназначаем его.
698
+ ({ signal, clearSignal } = setupLocalAbortController(timeout));
699
+ // requestConfig.timeout = timeout; // убираем, потому, что есть signal
576
700
  requestConfig.timeoutErrorMessage = `Request timed out after ${timeout} ms`;
577
- requestConfig.signal = abortController.signal;
701
+ requestConfig.signal = signal;
578
702
  requestConfig.withXSRFToken = true;
579
703
  return this;
580
704
  },
@@ -634,7 +758,7 @@ export class BetBoosterApi {
634
758
  return response;
635
759
  })
636
760
  .catch(axiosErrorHandler)
637
- .finally(() => clearTimeout(signal));
761
+ .finally(() => clearSignal());
638
762
  const { data, status, statusText } = await response;
639
763
  statusHandler(status, statusText);
640
764
  return { data, status, statusText };
@@ -753,6 +877,7 @@ export class BetBoosterApi {
753
877
  *
754
878
  * @param minutes The number of minutes to consider for the data retrieval. Defaults to 0.
755
879
  * @returns {Promise<Array<any>>} A promise that resolves to an array of line sports data.
880
+ * @deprecated - use this.getLineSportsMain();
756
881
  */
757
882
  async getLineSports(minutes = 0) {
758
883
  var _a;
@@ -781,6 +906,7 @@ export class BetBoosterApi {
781
906
  * @param sportId - Идентификатор спорта.
782
907
  * @param minutes - Опциональный параметр, количество минут.
783
908
  * @returns Промис, который разрешается в массив объектов типа ICountry.
909
+ * @deprecated - use this.getCountriesListMain();
784
910
  */
785
911
  async getCountriesList(sportId, minutes = 0) {
786
912
  var _a;
@@ -794,6 +920,7 @@ export class BetBoosterApi {
794
920
  * @param countryId - The ID of the country.
795
921
  * @param minutes - The number of minutes ago for which data is to be retrieved.
796
922
  * @returns A promise that resolves to an array of prematch tournaments.
923
+ * @deprecated - use this.getPrematchTournamentsMain();
797
924
  */
798
925
  async getPrematchTournaments(sportId, countryId, minutes = 0) {
799
926
  var _a;
@@ -2420,6 +2547,201 @@ export class BetBoosterApi {
2420
2547
  rawData.size = payload.LIMIT.size;
2421
2548
  return this.responseHandlerData(rawData, status, statusText);
2422
2549
  }
2550
+ /**
2551
+ * Retrieves aggregated dictionary data from Redis using FT.AGGREGATE command.
2552
+ * Groups and counts items by specified dictionary type (sport, country, or tournament).
2553
+ *
2554
+ * @param payload - The search parameters for dictionary aggregation
2555
+ * @param payload.locale - Language locale code for filtering results
2556
+ * @param payload.sportId - Sport ID(s) to include in search
2557
+ * @param payload.countryId - Country ID(s) to include in search
2558
+ * @param payload.tournamentId - Tournament ID(s) to include in search
2559
+ * @param payload.dictionary - Dictionary type to group by ('sport' | 'country' | 'tournament')
2560
+ * @param payload.notsport - Sport ID(s) to exclude from search
2561
+ * @param payload.notcountry - Country ID(s) to exclude from search
2562
+ * @param payload.nottournament - Tournament ID(s) to exclude from search
2563
+ * @param payload.LIMIT - Maximum number of results to return
2564
+ * @param payload.minTime - Minimum time filter for events
2565
+ * @param payload.maxTime - Maximum time filter for events
2566
+ *
2567
+ * @returns Promise resolving to aggregated results with total count and grouped items,
2568
+ * or error object with total: 0 and empty results array on failure
2569
+ *
2570
+ * @example
2571
+ * ```typescript
2572
+ * // Get sport dictionary with counts
2573
+ * const sportDict = await redisDb.getDictionary({
2574
+ * locale: 'en',
2575
+ * dictionary: 'sport',
2576
+ * LIMIT: { from: 0, size: 10 },
2577
+ * minTime: 1640995200,
2578
+ * maxTime: 1641081600
2579
+ * });
2580
+ *
2581
+ * // Get country dictionary excluding specific sports
2582
+ * const countryDict = await redisDb.getDictionary({
2583
+ * locale: 'ru',
2584
+ * dictionary: 'country',
2585
+ * notsport: [1, 2, 3],
2586
+ * LIMIT: { from: 0, size: 50 }
2587
+ * });
2588
+ *
2589
+ * // Get tournament dictionary for specific sport and country
2590
+ * const tournamentDict = await redisDb.getDictionary({
2591
+ * locale: 'en',
2592
+ * dictionary: 'tournament',
2593
+ * sportId: [1],
2594
+ * countryId: [225],
2595
+ * LIMIT: { from: 0, size: 100 }
2596
+ * });
2597
+ * ```
2598
+ */
2599
+ async getDictionaryNv20(payload) {
2600
+ var _a, _b, _c, _d, _e;
2601
+ const url = this.url(`/stats/pm/dictionary`, api.NV20);
2602
+ (_a = payload.locale) !== null && _a !== void 0 ? _a : (payload.locale = this.locale);
2603
+ const { data: rawData, status, statusText } = await this.request(url).POST(payload).exec();
2604
+ rawData.from = (_c = (_b = payload === null || payload === void 0 ? void 0 : payload.LIMIT) === null || _b === void 0 ? void 0 : _b.from) !== null && _c !== void 0 ? _c : null;
2605
+ rawData.size = (_e = (_d = payload === null || payload === void 0 ? void 0 : payload.LIMIT) === null || _d === void 0 ? void 0 : _d.size) !== null && _e !== void 0 ? _e : null;
2606
+ return this.responseHandlerData(rawData, status, statusText);
2607
+ }
2608
+ /**
2609
+ * Retrieves a list of sports from the NV20 API endpoint with optional time filtering.
2610
+ *
2611
+ * @param {number} [minutes=0] - Optional time window in minutes to filter sports data.
2612
+ * If greater than 0, filters results to include only data
2613
+ * from the current time to the specified minutes in the future.
2614
+ * @param {number} [timeout=MAX_TIME_EXECUTION_MS] - Optional request timeout in milliseconds.
2615
+ * @returns {Promise<I.ISport[]>} A promise that resolves to an array of sports objects sorted by priority.
2616
+ * Each sport contains an ID, Name, and count (cnt) property.
2617
+ *
2618
+ * @example
2619
+ * // Get all available sports
2620
+ * const sports = await betBoosterApi.getLineSportsNv20();
2621
+ *
2622
+ * @example
2623
+ * // Get sports updated in the last 30 minutes with a custom timeout
2624
+ * const sports = await betBoosterApi.getLineSportsNv20(30, 5000);
2625
+ */
2626
+ async getLineSportsNv20(minutes = 0, timeout = MAX_TIME_EXECUTION_MS) {
2627
+ var _a;
2628
+ const url = this.url(`/stats/pm/dictionary`, api.NV20);
2629
+ const payload = Object.assign({ locale: this.locale, dictionary: 'sport' }, (minutes > 0 ? { minTime: Date.now(), maxTime: Date.now() + minutes * 60 * 1000 } : {}));
2630
+ const { data: rawData, status, statusText } = await this.request(url).POST(payload).setTimeout(timeout).exec();
2631
+ const handledData = this.responseHandlerData(rawData, status, statusText);
2632
+ const preparedSports = (((_a = handledData === null || handledData === void 0 ? void 0 : handledData.data) === null || _a === void 0 ? void 0 : _a.results) || []).filter((v) => v.sport && v.sName).map((v) => ({ ID: +v.sport, Name: v.sName, cnt: +v.cnt }));
2633
+ return this.sortDataByPriority(preparedSports, this.primarySports, 'ID');
2634
+ }
2635
+ /**
2636
+ * Retrieves the main line sports data with fallback mechanism.
2637
+ *
2638
+ * Attempts to fetch line sports data from the NV20 endpoint first with a 2000ms timeout.
2639
+ * If no sports data is returned, falls back to the standard getLineSports endpoint.
2640
+ *
2641
+ * @param minutes - Optional. The number of minutes to look back for sports data. Defaults to 0.
2642
+ * @param timeout - Optional. The timeout duration in milliseconds for the NV20 API request. Defaults to 1500.
2643
+ * @returns A promise that resolves to an array of sports objects containing line sports data.
2644
+ * @example
2645
+ * // Get current line sports
2646
+ * const sports = await getLineSportsMain();
2647
+ *
2648
+ * @example
2649
+ * // Get line sports from the last 30 minutes
2650
+ * const sports = await getLineSportsMain(30);
2651
+ */
2652
+ async getLineSportsMain(minutes = 0, timeout = 1500) {
2653
+ let sports = await this.getLineSportsNv20(minutes, timeout);
2654
+ if (sports.length === 0) {
2655
+ sports = await this.getLineSports(minutes);
2656
+ }
2657
+ return sports;
2658
+ }
2659
+ /**
2660
+ * Retrieves countries for a given sport using the NV20 API.
2661
+ * @param sportId - The sport ID to filter countries by.
2662
+ * @param minutes - Optional time window in minutes for the query. Defaults to 0 (no time filter).
2663
+ * @returns A promise that resolves to the response data containing countries or null if the request fails.
2664
+ */
2665
+ async getCountriesBySportNv20(sportId, minutes = 0, timeout = MAX_TIME_EXECUTION_MS) {
2666
+ var _a;
2667
+ const url = this.url(`/stats/pm/dictionary`, api.NV20);
2668
+ const payload = Object.assign({ locale: this.locale, sportId, dictionary: 'country' }, (minutes > 0 ? { minTime: Date.now(), maxTime: Date.now() + minutes * 60 * 1000 } : {}));
2669
+ const { data: rawData, status, statusText } = await this.request(url).POST(payload).setTimeout(timeout).exec();
2670
+ const handledData = this.responseHandlerData(rawData, status, statusText);
2671
+ const preparedCounties = (((_a = handledData === null || handledData === void 0 ? void 0 : handledData.data) === null || _a === void 0 ? void 0 : _a.results) || []).sort((a, b) => a.cName.localeCompare(b.cName)).map((v) => ({ ID: +v.country, Name: v.cName, cnt: +v.cnt }));
2672
+ const priorityCountries = this.priorityCountries[sportId];
2673
+ if (priorityCountries) {
2674
+ return this.sortDataByPriority(preparedCounties, priorityCountries, 'ID');
2675
+ }
2676
+ return preparedCounties;
2677
+ }
2678
+ /**
2679
+ * Retrieves a list of countries for a given sport, with fallback behavior.
2680
+ *
2681
+ * Attempts to fetch countries using the NV20 API with a 5-second timeout.
2682
+ * If no results are returned, falls back to the standard countries list endpoint.
2683
+ *
2684
+ * @param sportId - The unique identifier of the sport
2685
+ * @param minutes - Optional. The number of minutes to use as a filter criteria. Defaults to 0.
2686
+ * @param timeout - Optional. The timeout duration in milliseconds for the NV20 API request. Defaults to 3000.
2687
+ * @returns A promise that resolves to an array of countries for the specified sport
2688
+ *
2689
+ * @example
2690
+ * ```typescript
2691
+ * const countries = await this.getCountriesListMain(1, 30);
2692
+ * ```
2693
+ */
2694
+ async getCountriesListMain(sportId, minutes = 0, timeout = 3000) {
2695
+ let sports = await this.getCountriesBySportNv20(sportId, minutes, timeout);
2696
+ if (sports.length === 0) {
2697
+ sports = await this.getCountriesList(sportId, minutes);
2698
+ }
2699
+ return sports;
2700
+ }
2701
+ /**
2702
+ * Retrieves tournaments from the NV20 API for a specific sport and optional country.
2703
+ * @param sportId - The sport ID to filter tournaments by
2704
+ * @param countryId - Optional country ID to filter tournaments by
2705
+ * @param minutes - Optional time window in minutes for tournament data (default: 0, no time filter)
2706
+ * @returns A promise that resolves to the response data containing tournaments or null
2707
+ */
2708
+ async getPrematchTournamentsNv20(sportId, countryId, minutes = 0, timeout = MAX_TIME_EXECUTION_MS) {
2709
+ var _a, _b;
2710
+ const url = this.url(`/stats/pm/dictionary`, api.NV20);
2711
+ const payload = Object.assign({ locale: this.locale, sportId,
2712
+ countryId, dictionary: 'tournament' }, (minutes > 0 ? { minTime: Date.now(), maxTime: Date.now() + minutes * 60 * 1000 } : {}));
2713
+ const { data: rawData, status, statusText } = await this.request(url).POST(payload).setTimeout(timeout).exec();
2714
+ const handledData = this.responseHandlerData(rawData, status, statusText);
2715
+ const preparedTournaments = (((_a = handledData === null || handledData === void 0 ? void 0 : handledData.data) === null || _a === void 0 ? void 0 : _a.results) || []).sort((a, b) => a.tName.localeCompare(b.tName)).map((v) => ({ Id: +v.tournament, Name: v.tName, cnt: +v.cnt, sId: +v.sport, sName: v.sName, cId: +v.country, cName: v.cName }));
2716
+ const priorityTournaments = (_b = this.priorityTournaments[sportId]) !== null && _b !== void 0 ? _b : null;
2717
+ if (priorityTournaments) {
2718
+ return this.sortDataByPriority(preparedTournaments, priorityTournaments, 'Id');
2719
+ }
2720
+ return preparedTournaments;
2721
+ }
2722
+ /**
2723
+ * Retrieves prematch tournaments for a given sport and country.
2724
+ *
2725
+ * Attempts to fetch tournaments using the NV2.0 API first. If no tournaments are returned,
2726
+ * falls back to the standard API as a failover mechanism.
2727
+ *
2728
+ * @param sportId - The sport identifier (number or string)
2729
+ * @param countryId - The country identifier (number or string)
2730
+ * @param minutes - The time window in minutes for prematch tournaments (default: 0)
2731
+ * @param timeout - The request timeout in milliseconds (default: 3000)
2732
+ * @returns A promise that resolves to an array of tournament objects
2733
+ * @throws May throw an error if both API calls fail
2734
+ *
2735
+ * @example
2736
+ * const tournaments = await betBoosterApi.getPrematchTournamentsMain(1, 'US', 30, 5000);
2737
+ */
2738
+ async getPrematchTournamentsMain(sportId, countryId, minutes = 0, timeout = 3000) {
2739
+ let tournaments = await this.getPrematchTournamentsNv20(sportId, countryId, minutes, timeout);
2740
+ if (tournaments.length === 0) {
2741
+ tournaments = await this.getPrematchTournaments(sportId, countryId, minutes);
2742
+ }
2743
+ return tournaments;
2744
+ }
2423
2745
  async searchPrematchTournametsEventsNv20(searchString, options = {}) {
2424
2746
  var _a, _b, _c;
2425
2747
  const { data, status, statusText } = await this.searchPrematchEventsNv20(searchString, options);
@@ -2576,6 +2898,9 @@ export class BetBoosterApi {
2576
2898
  async test3() {
2577
2899
  return 'test3 Ok';
2578
2900
  }
2901
+ /**
2902
+ * @deprecated sellBet - Not implemented
2903
+ */
2579
2904
  async sellBet(data) {
2580
2905
  // !TODO sellBet - Not implemented
2581
2906
  // ! Нет реализации в BC