# ThrillTech Jackpots SDK

{% hint style="info" %}
To **access this SDK**, please **contact** your **Account Manager** or **Technical Operations Specialist** for configuration.
{% endhint %}

The **ThrillTech Jackpots SDK** is a TypeScript library that connects your casino frontend to **Hub88’s** ThrillTech Jackpot platform. **ThrillTech jackpots are opt-in, player-funded side-bet jackpot systems designed to enhance player engagement and retention through real-time, customizable jackpot experiences.** This SDK gives operators access to real-time jackpot functionality, player engagement tools, and seamless integration with existing game lobbies.

**With this SDK, you can:**

* **Authenticate** **players** to **participate** in **jackpots**,
* Subscribe to **real-time jackpot events** (updates, wins, opt-in changes),
* Allow players to **opt-in or opt-out** of jackpots with optional contribution values,
* Fetch **leaderboards, sources, currencies, and jackpot metadata,**
* Display **jackpots** **dynamically** in your lobby and games,
* Trigger **animations for jackpot wins** using the ThrillTech animation driver

The SDK lets operators focus on **custom UI and player experience**, while jackpot logic, event streaming, and payout handling are managed by **Hub88 and ThrillTech**.

### Architecture

* **Hub88** provides authentication and event distribution via SDK init token.
* **ThrillTech (TT)** manages jackpot creation, payout configuration, and animations.
* **Operator backend** authenticates players and passes init payload to the frontend.
* **Casino frontend** initialises SDK, listens to events, and updates UI accordingly.&#x20;

{% hint style="success" %}
For front-end UI ThrillTech provides a separate driver including **wheel spin and jackpot celebration animations.** This can be embedded in your Jackpot widget to improve player engagement during wins.

Access it through the CDN, available at <https://cdn.hub88.io/thrilltech-sdk/thrilltech-driver-v1.0.1.js> .
{% endhint %}

#### Communication Flow&#x20;

<div data-with-frame="true"><figure><img src="https://1089485291-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FF8iFPgdqAwxIxP5oQMvU%2Fuploads%2F8W5jj7XovY6lobCEuv2X%2F%5BHub88%5D%20Documentation%20working%20board%20-%20ThrillTech%20Agnostic%20(2).jpg?alt=media&#x26;token=64cb4b70-4a6b-4bbc-8dec-24e39f4eede3" alt=""><figcaption><p>SDK key communication flow</p></figcaption></figure></div>

***

## Integration Steps

**Prerequisites**

* Node.js (v14 or later is recommended)
* npm or yarn&#x20;

{% hint style="info" %}
To **access this SDK**, please contact your **Account Manager** or **Technical Operations Specialist** for preliminary setup configuration.
{% endhint %}

{% hint style="info" %}
**Access the SDK library from:**\
[**https://cdn.hub88.io/thrilltech-sdk/hub88thrillconnect-0.0.10.js**](https://cdn.hub88.io/thrilltech-sdk/hub88thrillconnect-0.0.10.js)
{% endhint %}

#### Architecture Overview

The SDK consists of the following main components:

* **Hub88 ThrillTech Connect**: Core client class that handles WebSocket connections and event management;
* **Request Factory**: Handles API requests for jackpot operations, opt-in/out, and leaderboard data
* **Event System**: Pub/sub pattern for handling real-time events from the ThrillTech server.

***

### Step 1: Authenticate Player (Backend)

Your backend must authenticate players with Hub88 before initialising the SDK.

**Endpoint:**

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

```json
POST /operator/generic/v2/agnostic-jackpot/user/authenticate
```

{% endcode %}

**Sample Request:**

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

```json
{
  "user": "john12345",
  "token": "f562a685-a160-4d17-876d-ab3363db331c",
  "operator_id": 10,
  "sub_partner_id": null,
  "currency": "EUR",
  "country": "EE"
}
```

{% endcode %}

**Sample Response:**

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

```json
{
  "optin": false,
  "sdk_init_token": {
    "token": "QTEyOEdDTQ...", // encoded JSON string
    "attributes": "eyJ1c2VyIjoiMTc0OTYyNzk==" // base64 encoded JSON string
  }
}
```

{% endcode %}

Return this response securely to the frontend.

### Step 2: Initialise SDK Client

#### Client Initialisation

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

```typescript
import {
  Hub88ThrillConnect,
  Hub88ConnectArg,
  Connect,
  ConnectEvents
} from 'hub88-thrilltech-connect'

// Authenticate with the casino server -- The above is expected to run on your
// server and payload to be exposed to your casino frontend via API
const url = `${api_url}/operator/generic/agnostic-jackpot/user/authenticate`

const response = await fetch(url, {
  method: 'POST',
  body: JSON.stringify(gamesLauncherURLParams),
  headers: { 'Content-Type': 'application/json' }
})
const responseData: Hub88ConnectArg = await response.json()
return responseData

// On the Casino frontend, the responseData is expected to be available
// We can then create the client like so

// Very important to subscribe to the events; otherwise, the web socket will disconnect after a certain period
const events: ConnectEvents = [
  ConnectEvents.JackpotUpdateEvent,
  ConnectEvents.JackpotWinEvent,
  ConnectEvents.OptInEvent
]

// This ensures events are subscribed to
const settings = { ...responseData, events: events }

// Create client instance
// Client reconnection is handled by the client class
const client: Hub88ThrillConnect = Connect(settings)

```

{% endcode %}

#### Event Handling

| Event                              | Description                                        |
| ---------------------------------- | -------------------------------------------------- |
| `ConnectEvents.Connected`          | Triggered when WebSocket connection is established |
| `ConnectEvents.Disconnected`       | Triggered when WebSocket connection is closed      |
| `ConnectEvents.ConnectionFailed`   | Triggered when WebSocket connection fails          |
| `ConnectEvents.Message`            | Triggered when any message is received             |
| `ConnectEvents.JackpotUpdateEvent` | Triggered when jackpot values are updated          |
| `ConnectEvents.JackpotWinEvent`    | Triggered when a jackpot is won                    |
| `ConnectEvents.OptInEvent`         | Triggered when opt-in status changes               |

{% hint style="success" %}
After the client is initialised, opt-in, leaderboard, and other API calls become available.
{% endhint %}

### Step 3: Opt-in / Opt-out

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

```typescript
// Opt-in with default contribution
await client.request().optIntoJackpot()

// Opt-in with contribution of 100
await client.request().optIntoJackpot(100)

// Opt-out
await client.request().optOutOfJackpot()
```

{% endcode %}

**Signature**

```typescript
client.request().optIntoJackpot(contribution_value: number | undefined = undefined)
client.request().optOutOfJackpot(contribution_value: number | undefined = undefined)
```

**Sample response**

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

```json
{
  "status": "success"
}
```

{% endcode %}

### Step 4: Leaderboard and Jackpot Queries

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

```typescript
// Get latest winners (default brand returned from the authenticated user)
await client.request().getLeaderboardinfo()

// Limit results to 10. Default value is 5. Value can range from 1-20.
await client.request().getLeaderboardinfo({ limit: 10 })

// Fetch across all brands
await client.request().getLeaderboardinfo({ all_brands: true })

// Fecth a specific brand
await client.request().getLeaderboardinfo({ brand_id: "test_brand" }) 

```

{% endcode %}

**Signature**

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

```typescript
client.request().getLeaderboardinfo({
  all_brands?: boolean
  instance_id?: string
  brand_id?: string
  limit?: number
})
```

{% endcode %}

**Sample Leaderboard Response**

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

```json
[
  {
    "win_pot_id": "Major", // 'Minor' | 'Major' | 'Mega'
    "win_amount": 500,
    "jackpot_currency": "USD",
    "player_id": "john12345", // operator_user
    "timestamp": 1748551660, // unix timestamp 
    "brand_id": "hub88:testing"
  }
]
```

{% endcode %}

***

### Step 5: Fetch Jackpot Metadata

#### **Get Source for Current Brand**

```typescript
client.request().getSources()
```

**Signature**

```typescript
getSources()
```

**Sample Response**

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

```json
[
  {
    "owner_id": "string",
    "source_name": "string",
    "source_id": "string",
    "jackpots": [
      {
        "priority": 0,
        "owner_id": "string",
        "instance_id": "string"
      }
    ]
  }
]
```

{% endcode %}

#### **Get Currencies**

```typescript
client.request().getCurrencies()
```

**Signature**

```typescript
client.request().getCurrencies()
```

**Sample Response**

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

```json
[
  {
    "brand_id": "string",
    "base_currency": "string",
    "multipliers": {
      "property1": 0.1,
      "property2": 0.1
    }
  }
]
```

{% endcode %}

#### **Get Jackpot for Default Source (Specific Player)**

```typescript
client.request().getJackpotInstance()
client.request().getJackpotInstance(player_id: 'john12345')
```

**Signature**

```typescript
client.request().getJackpotInstance(player_id?: string)
```

**Sample Response**

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

```json
[
  {
    "brand_id": "string",
    "base_currency": "string",
    "multipliers": {
      "property1": 0.1,
      "property2": 0.1
    }
  }
]
```

{% endcode %}

***

### Full Example

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

```typescript
import {
  Hub88ThrillConnect,
  Hub88ConnectArg,
  Connect,
  ConnectEvents
} from 'hub88-thrilltech-connect'

// Authenticate with the casino server -- The above is expected to run on your
// server and payload to be exposed to your casino frontend via API
const url = `${api_url}/operator/generic/agnostic-jackpot/user/authenticate`

const response = await fetch(url, {
  method: 'POST',
  body: JSON.stringify(gamesLauncherURLParams),
  headers: { 'Content-Type': 'application/json' }
})
const responseData: Hub88ConnectArg = await response.json()
return responseData

// On the Casino frontend, the responseData is expected to be available
// We can then create the client like so

// Very important to subscribe to the events; otherwise, the web socket will disconnect after a certain period
const events: ConnectEvents = [
  ConnectEvents.JackpotUpdateEvent,
  ConnectEvents.JackpotWinEvent,
  ConnectEvents.OptInEvent
]

// This ensures events are subscribed to
const settings = { ...responseData, events: events }

// Create client instance
// Client reconnection is handled by the client class
const client: Hub88ThrillConnect = Connect(settings)

// Event event handling
client.on(ConnectEvents.Connected, () => {
  console.log('WS Connected!')
})

client.on(ConnectEvents.Message, (data) => {
  console.log('Message received:', data)
})

client.on(ConnectEvents.JackpotUpdateEvent, (updateEvent) => {
  console.log('Jackpot update event:', updateEvent)
})
client.on(ConnectEvents.JackpotWinEvent, (winEvent) => {
  console.log('Jackpot win event:', winEvent)
})

// Handle one-time events
client.once(ConnectEvents.Disconnected, () => {
  console.log('Disconnected - this handler will only run once')
})

// Unsubscribe from events
const messageHandler = (data) => console.log(data)
client.on(ConnectEvents.Message, messageHandler)
client.off(ConnectEvents.Message, messageHandler) // Remove specific handler
client.off(ConnectEvents.Connected) // Remove all handlers for this event

// Clean up when done or when need to switch the player from demo mode to
// real mode
function cleanup() {
  client.destroy()
}
```

{% endcode %}

***

## TypeScript Types

The SDK provides comprehensive TypeScript definitions for all features:

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

```typescript
// Core interfaces
interface Hub88ConnectArg {
  sdk_init_token: {
    token: string
    attributes: string // base64 encoded JSON
  }
  events?: ConnectEvents[]
  dev?: {
    log?: boolean
    secure?: boolean
  }
}

// Event data types
interface JackpotUpdateEvent {
  instance_id: string
  tiers: {
    name: string
    value: number
  }[]
}

// Request parameters
interface LeaderboardFilterArgs {
  all_brands?: boolean
  operator_runtime_id?: string
  instance_id?: string
  limit?: number // 1-20, default: 5
}
```

{% endcode %}

***

## Troubleshooting

#### WebSocket Connection Issues

If you're experiencing connection issues:

1. Verify that the provided token is valid,
2. Check that the player currency is properly set (cannot be 'XXX'),
3. Ensure the WebSocket URL is accessible from your environment.

#### Opt-In Not Working

If player opt-in is failing:

1. Verify the player is properly authenticated,
2. Check that the `source_id` or `instance_id` is valid,
3. Ensure the WebSocket connection is established before making opt-in requests.

## Error Codes  During Authentication

| HTTP Code | Message                                                                      | Potential Cause                                                                                                                                                                              | Action                                                                 |
| --------- | ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| 400       | `A parameter <param> is missing or invalid`                                  | A required request parameter is missing, empty, or invalid. Check: `user`, `token`, `country`, `currency`, `platform` (`GPL_DESKTOP`/`GPL_MOBILE`), `operator_id` (integer), `jackpot_uuid`. | Verify request payload includes all required fields with valid values. |
| 400       | `Operator game is disabled`                                                  | Operator game is disabled in configuration.                                                                                                                                                  | Enable the operator game in the system.                                |
| 400       | `Agnostic jackpot with uuid <jackpot_uuid> is not allowed for this operator` | Jackpot exists but not linked to operator.                                                                                                                                                   | Link jackpot to operator.                                              |
| 400       | `Agnostic jackpot with uuid <jackpot_uuid> is disabled`                      | Jackpot is disabled.                                                                                                                                                                         | Enable jackpot before requesting.                                      |
| 404       | `Operator was not found`                                                     | Operator ID does not exist.                                                                                                                                                                  | Check operator ID.                                                     |
| 404       | `Operator game was not found`                                                | No game linked to operator.                                                                                                                                                                  | Ensure operator is assigned the game.                                  |
| 404       | `Contract was not found`                                                     | Contract ID missing or invalid.                                                                                                                                                              | Verify operator–contract mapping.                                      |
| 404       | `Currency was not found`                                                     | Currency code not valid in Hub88.                                                                                                                                                            | Use valid ISO currency code.                                           |
| 404       | `Agnostic jackpot with uuid <jackpot_uuid> was not found`                    | Jackpot UUID not recognized.                                                                                                                                                                 | Confirm jackpot UUID is correct.                                       |
| 404       | `Country was not found`                                                      | Country code not valid in Hub88.                                                                                                                                                             | Use valid ISO country code.                                            |
| 404       | `Supplier game was not found`                                                | Supplier game record missing.                                                                                                                                                                | Ensure supplier game exists and is configured.                         |
| 500       | `Game code for agnostic jackpot should exist but is missing`                 | Thrilltech game code could not be retrieved.                                                                                                                                                 | Confirm that a valid jackpot game code exists for the request.         |
| 500       | `Game code for agnostic jackpot is not valid`                                | An invalid/unrecognized game code was supplied.                                                                                                                                              | Ensure the game code matches an eligible Thrilltech game.              |
| 500       | `Game should exist but was not found`                                        | The requested game does not exist in cache or DB.                                                                                                                                            | Verify game exists and is configured correctly.                        |
| 500       | `Contract is improperly configured`                                          | Contract linked to operator/supplier is misconfigured.                                                                                                                                       | Review Hub88 back office contract setup.                               |
| 500       | `Invalid response from ThrillTech`                                           | Thrilltech backend returned invalid/unexpected response.                                                                                                                                     | Retry or contact support if persistent.                                |

***

## Managing ThrillTech Jackpots in Operator Backoffice

Since Thrilltech operates as a **Supplier** within Hub88, all **bets and wins** related to Thrilltech Jackpots are logged and visible in the [**Backoffice**](https://app.gitbook.com/s/MTWFNZ1g2QuImiZFIO1o/operator-backoffice). You can view and filter these transactions by following the steps below.

1. Navigate to **Backoffice →** [**Transactions**](https://app.gitbook.com/s/MTWFNZ1g2QuImiZFIO1o/operator-backoffice/transactions-management#transactions).
2. Choose one of the following filtering options:

**Option 1: Filter by User**

* Select a specific user to see **all transactions linked to that player**.
* The Backoffice records both:
  * **Supplier requests** (bet and win), and
  * **Thrilltech Jackpot requests** (bet and win).
* This means you’ll see paired logs for each transaction.

**Option 2: Filter by Supplier / Product Code**

* Select **Thrilltech** as the supplier to view **only Thrilltech Jackpot transactions**.
* For each transaction, you’ll see both the bet and win entries related to Thrilltech Jackpots.

#### Understanding Amount Values

In the **Transactions view**, the **Amount** column reflects Thrilltech’s jackpot bet and win logic:

* **Bet transaction** → Shows the contribution amount defined during the Opt-In process.
* **Win transaction** →
  * Shows zero (0) indicating the player did not win the jackpot in this round.
  * Shows jackpot amount if the bet resulted in a win.
