Designing games around providers
The Rollerz SDK connects your game to a provider — a backend math engine (RGS) that determines bet outcomes. Your game's theme, mechanics, and animations should be designed around the data your chosen provider returns.
This guide helps you pick the right provider and shows how to turn its result fields into compelling game experiences.
What is a bet type?
A bet type is a hint sent with every bet that tells the math server which math model to use for the round. Different bet types control volatility, max payout, and potentially the valid bet amounts.
The full resolution and validation rules live in the bet types section of the API reference — here, the design question is simply: how do you want the player to choose his bet type?
Note that the framework's default bet selector renders whatever provider.getBetTypes() returns as a segmented control.
General design tips
- Map every result field to something visual. If a field exists, show it. Players should see the data reflected in what happens on screen.
- Animate the reveal. Don't just show the final state — build anticipation. Stagger rock breaks, flip cards one by one, show the multiplier climbing.
- Make the common fields the core mechanic.
count/multiplier/cardPacksare the main event.hasBonus/crashed/rarity summaries are the twist. - Use the session data.
currencyfor formatting,chipLevelsfor bet options,defaultBetfor sensible defaults. The framework's bet selector handles this out of the box. - Treat bet types as a player-facing choice. See the section above — surface them in your UI, don't bury them in a settings menu.
- All amounts are raw (in cents). Every monetary value from the SDK — balance, bet amounts, payouts, win amounts — is in the smallest currency unit (e.g.
10000= $100.00). Never divide or scale these yourself. UseformatAmount()from the framework whenever you display a monetary value to the player. - Test with dev mode. Every predefined provider — GO3, Stepper, Rippin Rumble, and GP — ships with a
devConfig. Drop them all into a single dev panel and you get per-provider domain controls (counts, multipliers, crash points, card combos, raw math overrides) that force specific outcomes without hitting the real RGS.
Choosing a provider
| Provider | Flow | Best for |
|---|---|---|
| GO3 | Bet → instant result → collect | Games where the outcome is revealed all at once |
| Stepper | Bet → step → step → ... → collect or crash | Games where the player pushes their luck |
| Rippin Rumble | Bet → cards dealt → collect | Games built around revealing or collecting items |
| GP (General Purpose) | Bet → result (raw math) → collect | Games connecting to an external or custom math server |
Explore providers in the Playground
Switch between Go3, Stepper, Rippin Rumble, and GP in the SDK Provider Playground. Trying each provider there — open a session, place bets, use step/collect where it applies — is the quickest way to get a feel for how the flows and responses differ before you commit your game design.
The key question: how does your game deliver its result?
- If the player bets and immediately sees what they won → GO3
- If the player makes repeated risk/reward decisions after betting → Stepper
- If the player receives a set of items to reveal → Rippin Rumble
- If you're connecting to your own math server or a third-party RGS → GP
Need custom math?
If none of the built-in providers fit your game concept, the Rollerz team can build a custom math server for you. See Adding a new math server for details.
GO3: instant-reveal games
GO3 returns everything in a single bet result: how many items were hit, whether a bonus was triggered, and the win multiplier. Design your game around revealing these fields.
Key result fields (see Go3BetResult for all fields):
| Field | Type | Design role |
|---|---|---|
count | number[0,1,2,3] | How many things the player hit/broke/matched |
hasBonus | boolean | Whether a bonus or rare event occurred |
multiplier | number | The win multiplier |
Bet types: BASE (default) and BOOSTED. The boosted list is the session's chip levels multiplied by the math server's boosted multiplier (typically 2×), and the math model pays out more aggressively. Surface boost as a clear "risk it for higher stakes" toggle — the sample smash game uses a fiery visual shift when the player flips to BOOSTED. You can also use the legacy { boosted: true } sugar on placeBet if it reads better in your code.
Game idea
Vault CrackerBe the first to build this game!Heist / ThrillerYou're a safecracker on a heist. Pick one of three vault dials to turn, and see how well you crack the code.
Field mapping
countTumblers cracked — 0 = jammed, 1 = one click, 2 = two clicks, 3 = vault openshasBonusDiamond stash inside — vault glows, jewels spill outmultiplierPayout based on how many tumblers crackedDesign notes
- The dial pick is purely cosmetic — the math result is the same regardless. But it gives the player agency and lets you animate a satisfying dial-turn sequence.
- Animate the crack attempt in stages: hand on dial, slow turn, tumbler clicks one by one.
- Jammed (0) should still feel dramatic — dial resists, alarm almost triggers, tension sting.
- Diamond stash deserves a full celebration: vault door swings open, jewels cascade, spotlight glint.
Stepper: risk-reward games
Stepper is unique — after placing a bet, the player repeatedly chooses to step (increase their multiplier) or collect (cash out). But each step risks a crash that loses the bet. Design your game around this tension.
Key result fields (see StepperBetResult for all fields):
| Field | Type | Design role |
|---|---|---|
currentStep | number | How far the player has climbed |
currentPayout | number | What the player wins if they cash out now |
steps | StepperStep[] | The full ladder — each step has a payout and outcome (SAFE, CRASH, UNDECIDED) |
roundEnded | boolean | Whether the round ended (crash or cash out) |
difficulty | string | The risk level (BEGINNER, EASY, MEDIUM, HARD, INSANE) |
Bet types: the five difficulty levels above. Each is a separate math model with its own step count and max multiplier — BEGINNER has 24 steps and caps at 20× while INSANE has 16 steps and caps at 10000×. This isn't a cosmetic choice: it fundamentally reshapes the risk curve, so treat it as a first-class game decision, not a settings-menu afterthought. The framework's bet selector renders all five as a segmented control automatically. Stepper does not support the boosted: true sugar — pass { betType: 'HARD' } (etc.) explicitly.
Design-wise, theme the difficulty labels to match your game — BEGINNER/INSANE might read as "Stroll" vs. "Apocalypse" in a zombie game, or "Rookie" vs. "Champion" in a combat gauntlet. The result.difficulty field echoes whatever the player chose back to you, so you can use it to drive visual intensity (louder music, faster heartbeat, heavier particle effects on INSANE).
Game idea
Zombie CrashBe the first to build this game!Survival / HorrorMove through a zombie-infested zone, mowing down undead along the way. When a close encounter hits, time slows — fight on or bail with your winnings.
Field mapping
currentPayoutPayout amount — grows with each step, cash out anytimeroundEndedBitten — the run is over, bet loststepsThe path ahead — each step shows payout and outcome (SAFE/CRASH/UNDECIDED)Core loop
- Player bets and enters the zone.
- Between encounters, the player moves through the environment killing zombies freely — this is gameplay filler that builds atmosphere. Track a kill count and accuracy as fun stats (cosmetic only, no effect on payout).
- A close encounter triggers — time slows down. The player decides: fight (
step()) or bail (collect). - Safe step — encounter survived, RGS returns the new multiplier, and the player keeps moving until the next encounter.
- Crash — caught and bitten. Round over.
Design notes
- The decision moment is everything. Slow-motion, heartbeat audio, visual tension.
- Between encounters, let the player enjoy the zombie-killing gameplay — it's the "filler" that makes the encounter moments feel earned.
- On a safe step: satisfying encounter kill. On a crash: quick, brutal — no slow-mo escape.
- Layer a narrative goal on top — fighting toward a rescue point or saving a survivor gives the "keep going" choice emotional weight beyond the multiplier.
- This pattern works for other combat themes: FPS corridor, sword fight gauntlet, martial arts tournament.
Rippin Rumble: card-reveal games
Rippin Rumble deals one or more card packs per round. Each pack has 5 cards, each with a rarity (COMMON / UNCOMMON / RARE / LEGENDARY), plus per-rarity summary objects that give a pre-computed payout breakdown per tier. Design your game around the reveal of these cards and pack-level payouts.
Key result fields (see RippinRumbleBetResult for all fields):
| Field | Type | Design role |
|---|---|---|
cardPacks | CardPack[] | 1 pack for BASE/BOOSTED, 11 packs for BASE_BUNDLE |
cardPacks[].cards | Card[] | The 5 cards dealt in that pack |
cardPacks[].{common,uncommon,rare,legendary} | CardPackRaritySummary | Per-rarity count / valuePerCard / multiplier / totalValue |
cardPacks[].totalPayout | number | Sum of totalValue across rarities for this pack |
Bet types: BASE (default), BOOSTED, and BASE_BUNDLE. Boosted chip levels are base chips × boostedMultiplier (default 2, env RIPPINRUMBLE_BOOSTED_MULTIPLE). Base-bundle chip levels are base chips × baseBundleMultiplier (default 10, env RIPPINRUMBLE_BASE_BUNDLE_MULTIPLE). Bundles return 11 packs per round — good framing for "open a box of 11 packs" mechanics.
Game idea
Shadow ContractBe the first to build this game!Sniper / HitmanYou're an assassin on a rooftop with a contract. A group emerges from a building — scope in, pick your mark, collect the bounty.
Field mapping
cardPacks[0].cardsPeople in the group — each card is a person with a rolecardPacks[0].rare.totalValue / .legendary.totalValueBounty totals for high-value groupingscardPacks[0].totalPayoutTotal bounty for this contractCore loop
- Player bets. Briefing screen shows the target and location.
- A group emerges — people revealed one at a time through the scope.
- Player picks who to assassinate. The choice is cosmetic — payout comes from the group composition — but it adds to a persistent hit list.
- High-value rarity tiers trigger bonus totals — rare pairs, legendary groups.
- Collect the bounty.
Design notes
- Reveal people one at a time with a scope sweep. Build tension as each steps into view.
- Rarity highlights: the scope lights up high-value targets, a "HIGH VALUE" banner appears.
- Vary settings each round — different rooftop, weapon skin, city. Use
storageto persist the hit list across sessions. - Legendary pack: an entire group of high-value targets. Dramatic music, slow-mo scope pan.
GP: generic math server
The GP (Generic Provider) is a passthrough provider that connects your game to any external math server. Unlike the providers above, GP does not define game-specific result fields — the SDK handles session management and betting, but the math result structure depends entirely on the connected server.
When to use GP:
- You have your own math server or are connecting to a third-party RGS
- You want to use the SDK's session and bet infrastructure without being locked into a specific result format
- You're prototyping with a custom math backend
Key result fields (see GPBetResult for all fields):
| Field | Type | Design role |
|---|---|---|
math | Record<string, unknown> | Raw response from the math server — structure varies by server |
totalWinAmount | number | Total win amount |
roundId | string | Round ID for collecting winnings |
Since the math field is a passthrough, your game must extract and map the fields it needs. For example, if your math server returns GO3-style results:
const result = await sdk.gp.placeBet(100, { betType: 'BASE' });
const details = result.math?.details || {};
const rocksCrushed = details.rocksCrushed || 0;
const multiplier = details.multiplier || 0;Bet types: unlike the other providers, GP ships with no predefined bet types — the set your math server understands depends entirely on your deployment. You have two options:
- Register a fixed set at startup via
sdk.gp.configureBetTypes([...], options?). After this, GP behaves exactly like the predefined providers:getBetTypes()returns your list, the bet selector renders it, and any unknownbetTypepassed toplaceBetthrows client-side before hitting the network. - Leave it unconfigured and pass arbitrary
betTypestrings straight through. No client-side allow-list; whatever you send is forwarded to the math server verbatim. This is the right choice for experimental setups or when the set changes at runtime.
// Option 1 — recommended for games shipping to players.
sdk.gp.configureBetTypes(['BASE', 'BOOSTED'], {
defaultBetType: 'BASE',
boostedBetType: 'BOOSTED', // enables the `{ boosted: true }` sugar
});
// Option 2 — unconfigured pass-through.
await sdk.gp.placeBet(100, { betType: 'WHATEVER' });Without configureBetTypes, placeBet() with no opts (and placeBet({ boosted: true })) throws — there's no default to fall back to. See gp.configureBetTypes for the full API.
See it in practice
The GP variant of the smash game example walks through a real hosting app wiring GP up against a GO3-compatible math server — including the configureBetTypes(['BASE', 'BOOSTED'], { ... }) call that makes the bet selector and boosted sugar work.
Custom endpoint path
By default, the SDK appends /gameevent to the server URL. If your math server uses a different path, pass the path parameter when opening the game:
await sdk.gp.openGame({
serverUrl: 'https://math.example.com',
internalClientCode: 'go3',
path: '/gameevent/v2',
});See API reference — gp.openGame for details.
Server URL precedence
GP accepts serverUrl from two places: the launch URL (?server=…) or the explicit openGame({ serverUrl }) argument. The URL parameter wins when both are present — host-driven launches must be able to override in-code defaults. openGame() only throws if neither source provides a serverUrl. internalClientCode is always required from openGame() options — the launch URL doesn't carry it.