# Turbostars – Sportsbook Modules

The **Turbostars Sportsbook Modules** integration provides seamless access to Sportsbook functionality through the [Operator Games API SDK](/developer-docs/operator-sdks/operator-games-api-sdk.md).\
It uses **automatic parameter injection**, where the `getModules()` API leverages a JavaScript Proxy to automatically include `host`, `cid`, and `token` in all module method calls.&#x20;

This design keeps the integration **simple**, **future-proof**, and **type-safe,** as developers only need to provide parameters specific to their use case, while new Sportsbook methods are supported automatically without requiring any SDK updates.

***

### How It Works?

When you call `provider.getModules()`, the SDK returns a proxied version of `window.Sportsbook`.\
This proxy **automatically** **injects shared parameters** (`host`, `cid`, and `token`) from your SDK configuration into every method call, leaving you to focus only on game- or event-specific logic.

**Auto-Injection Flow**

{% @mermaid/diagram content="sequenceDiagram
participant Op as Operator
participant SDK as SDK Proxy
participant SB as window\.Sportsbook

```
Op->>SDK: modules.initBetslipCount({ onChange })
SDK->>SDK: Inject host, cid, token
SDK->>SB: initBetslipCount({ host, cid, token, onChange })
SB-->>Op: Returns result" %}
```

***

## Usage

#### Basic Setup

{% code overflow="wrap" lineNumbers="true" %}

```javascript
// Initialize the SDK
const sdk = await Hub88Games.init({
  provider_token: 'YOUR_TOKEN',
  partner_key: 'YOUR_PARTNER_KEY',
  launcher_base_url: 'https://launcher.example.com'
});

// Get the provider instance
const provider = sdk.getProviderInstance();

// Retrieve modules with auto-injection enabled
const modules = provider.getModules();
```

{% endcode %}

***

### Available Module Methods

#### 1. Bet slip Count Tracking

Tracks the number of bets in the user’s bet slip.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
await modules.initBetslipCount({
  onChange: (count) => {
    console.log('Betslip count:', count);
    updateBetslipBadge(count);
  }
});
```

{% endcode %}

| **Parameter** | **Type**   | **Required** | **Description**                                             |
| ------------- | ---------- | ------------ | ----------------------------------------------------------- |
| `onChange`    | `function` | Yes          | Callback function triggered when the betslip count changes. |

**Auto-Injected Parameters:** `host`, `cid`, `token`

***

#### 2. Categorizer Data Subscription

Subscribes to updates in the categorizer data (sports/esports navigation).

{% code overflow="wrap" lineNumbers="true" %}

```javascript
await modules.subscribeOnCategorizerData({
  onChange: (categorizerData) => {
    console.log('Categorizer data:', categorizerData);
    renderNavigationMenu(categorizerData);
  },
  sportsbookPath: '/betting',
  isShowCategorizerInSportsbook: false,
  lang: 'en'
});
```

{% endcode %}

| Parameter                       | Type       | Required |                                                                |
| ------------------------------- | ---------- | -------- | -------------------------------------------------------------- |
| `onChange`                      | `function` | Yes      | Callback receiving categorizer data updates.                   |
| `sportsbookPath`                | `string`   | No       | Current sportsbook route for contextual data.                  |
| `isShowCategorizerInSportsbook` | `boolean`  | No       | Keep categorizer visible within sportsbook (default: `false`). |
| `lang`                          | `string`   | No       | Language code (ISO 639-1), e.g., `en`, `es`.                   |

**Auto-Injected Parameters:** `host`, `cid`, `token`

***

#### 3. Get Tournaments by Discipline

Retrieves tournament data for a specific discipline (e.g., Dota 2, CS:GO, LoL).

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const tournaments = await modules.getTournamentsByDiscipline({
  disciplineId: 'dota2',
  sportsbookPath: '/betting',
  lang: 'en'
});

console.log('Dota 2 tournaments:', tournaments);
```

{% endcode %}

| Parameter        | Type     | Required | Description                                     |
| ---------------- | -------- | -------- | ----------------------------------------------- |
| `disciplineId`   | `string` | Yes      | The discipline ID (`dota2`, `csgo`, `lol`).     |
| `sportsbookPath` | `string` | No       | Optional route path for correct URL generation. |
| `lang`           | `string` | No       | Language code for data localization.            |

**Auto-Injected Parameters:** `host`, `cid`, `token`

***

### Future Method Support

The SDK uses dynamic proxying, so any new Sportsbook module methods introduced by Turbostars or future providers will work automatically, no SDK upgrade required.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
// Example of a potential future feature
await modules.subscribeToLiveScores({
  onChange: (scores) => console.log(scores),
  sportTypes: ['football', 'basketball']
});
// The SDK automatically injects host, cid, token
```

{% endcode %}

***

### TypeScript Types

{% code overflow="wrap" lineNumbers="true" %}

```typescript
// User-facing params (host/cid/token omitted - auto-injected)
interface BetslipCountUserParams {
  onChange: (count: number) => void
}

interface CategorizerDataUserParams {
  onChange: (data: any) => void
  sportsbookPath?: string
  isShowCategorizerInSportsbook?: boolean
  lang?: string
}

interface TournamentsByDisciplineUserParams {
  disciplineId: string
  sportsbookPath?: string
  lang?: string
}

interface SportsbookModules {
  initBetslipCount(config: BetslipCountUserParams): Promise<void>
  subscribeOnCategorizerData(config: CategorizerDataUserParams): Promise<void>
  getTournamentsByDiscipline(config: TournamentsByDisciplineUserParams): Promise<any>
  // Any future methods will be typed as 'any' but still work
}
```

{% endcode %}

***

### Best Practices

#### Call `getModules()` After Initialization

Ensure the SDK and provider are fully initialized before requesting modules.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const sdk = await Hub88Games.init(config);
const provider = sdk.getProviderInstance();
const modules = provider.getModules(); // ✅ Modules are ready
```

{% endcode %}

{% hint style="warning" %}
Don't call the getModules() method before initialisation as this will return a null.&#x20;
{% endhint %}

#### Reuse the Same Modules Instance

Avoid redundant `getModules()` calls for better performance.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
// Good - store for reuse
const modules = provider.getModules();
await modules.initBetslipCount({ onChange: handleCount });
await modules.subscribeOnCategorizerData({ onChange: handleCategorizer });

// Less efficient - multiple getModules calls
await provider.getModules().initBetslipCount({ onChange: handleCount });
await provider.getModules().subscribeOnCategorizerData({ onChange: handleCategorizer });
```

{% endcode %}

#### Handle Errors Gracefully

Use `try/catch` to capture initialization or communication errors.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
try {
  const modules = provider.getModules();

  if (!modules) {
    console.error('Modules not available');
    return;
  }

  await modules.initBetslipCount({
    onChange: (count) => console.log(count)
  });
} catch (error) {
  console.error('Module initialization failed:', error);
}
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hub88.io/developer-docs/operator-sdks/operator-games-api-sdk/turbostars-sportsbook-modules.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
