Example Games
Reference

Real examples showing how each primitive is used. Copy any of these as a starting point for your own game.

Which Primitive?

Dice / Slots / Roulette

one-shot

Single bet → instant result

Mines / Towers

path

Pick tiles, avoid hazards

Crash / Rocket

multiplier

Rising multiplier, cash out in time

Rock Paper Scissors

pvp-lobby

Multiplayer with lobby matchmaking

Blackjack / Hi-Lo

state-machine

Multi-step with branching

Plinko / Wheel

one-shot

Single spin → weighted outcome

Dice Game (one-shot)

Simple dice roll. Player bets, platform picks a random outcome from the multiplier table.

1<!DOCTYPE html>
2<html>
3<head><title>Dice</title></head>
4<body>
5 <div id="dice">🎲</div>
6 <button onclick="roll()">ROLL</button>
7
8 <script>
9 // 6 multipliers — platform auto-calculates probabilities for 97% RTP
10 window.GAME_CONFIG = {
11 primitive: 'one-shot',
12 multipliers: [0, 0.5, 1, 2, 5, 10]
13 };
14
15 // id-based communication (same pattern all games use)
16 var pendingRequests = new Map();
17 var requestId = 0;
18
19 function sendToParent(data) {
20 return new Promise(function(resolve, reject) {
21 var id = ++requestId;
22 pendingRequests.set(id, { resolve: resolve, reject: reject });
23 var payload = Object.assign({}, data, { id: id });
24 if (window.TEST_MODE) {
25 payload.gameConfig = window.GAME_CONFIG_FOR_API;
26 }
27 parent.postMessage(payload, '*');
28 setTimeout(function() {
29 if (pendingRequests.has(id)) {
30 pendingRequests.delete(id);
31 reject(new Error('Timeout'));
32 }
33 }, 30000);
34 });
35 }
36
37 window.addEventListener('message', function(e) {
38 if (e.data && e.data.id && pendingRequests.has(e.data.id)) {
39 var h = pendingRequests.get(e.data.id);
40 pendingRequests.delete(e.data.id);
41 if (e.data.error) h.reject(new Error(e.data.error));
42 else h.resolve(e.data);
43 }
44 });
45
46 async function roll() {
47 try {
48 var resp = await sendToParent({
49 type: 'bet',
50 stake: window.GAME_STAKE || 1,
51 currency: window.GAME_CURRENCY || 'USDT'
52 });
53 // resp.result.multiplier = the winning multiplier (e.g. 5)
54 // resp.result.result = 'WIN' | 'PUSH' | 'LOSS'
55 var r = resp.result;
56 if (r.error) return alert(r.error);
57 document.getElementById('dice').textContent =
58 r.result === 'LOSS'
59 ? '🎲 Lost!'
60 : '🎲 Won ' + r.multiplier + 'x!';
61 } catch (err) {
62 alert(err.message);
63 }
64 }
65
66 parent.postMessage({ type: 'gameReady' }, '*');
67 </script>
68</body>
69</html>
One-shot is purely random — the player doesn't choose a number or target. The platform picks one of the multipliers based on calculated probabilities. Use continuous mode if you want the player to choose their own target multiplier (see One Shot docs).

Coin Flip (one-shot)

50/50 coin flip — two multipliers, one wins 1.94x, one loses.

1window.GAME_CONFIG = {
2 primitive: 'one-shot',
3 multipliers: [0, 1.94]
4 // Platform calculates: ~50% chance of 0x, ~50% of 1.94x
5 // RTP = 0.5 * 0 + 0.5 * 1.94 = 0.97 (97%)
6};
7
8// Bet:
9parent.postMessage({
10 type: 'bet',
11 id: Date.now(),
12 stake: window.GAME_STAKE,
13 currency: window.GAME_CURRENCY
14}, '*');
15
16// Result: e.data.result.multiplier = 0 (loss) or 1.94 (win)
17// e.data.result.result = 'WIN' or 'LOSS'

Mines (path)

5×5 grid with 3 mines. Click tiles, avoid mines, cash out anytime.

1window.GAME_CONFIG = {
2 primitive: 'path',
3 totalChoices: 25,
4 losingChoices: 3,
5 replacement: false
6};
7
8// Start → pathStart (include id for response matching)
9// Click tile → pathReveal with id + position (0-24)
10// Cash out → pathCashout with id
11// See "Path" docs for full template with sendToParent helper

Crash (multiplier)

Multiplier rises from 1.00x. Cash out before it crashes.

1window.GAME_CONFIG = {
2 primitive: 'multiplier',
3 curve: 'exponential', // 'linear' or 'exponential'
4 growthRate: 1, // 0.01 – 10
5 maxMultiplier: 1000 // hard cap
6};
7
8// Start → multiplierStart (places bet, starts round)
9// Cash → multiplierCashout
10// Listen for 'serverCrash' push event when round ends
11// Listen for 'serverSync' for clock calibration
12// Animate multiplier locally using growthRate + curve from start response
13// See "Multiplier" docs for full response shapes

Rock Paper Scissors (pvp-lobby)

Two players, matchmade lobby, winner takes all.

1window.GAME_CONFIG = {
2 primitive: 'pvp',
3 rakePercent: 0.01,
4 minPlayers: 2,
5 maxPlayers: 2,
6 visibility: 'matchmade',
7 payoutMode: 'winner_takes_all'
8};
9
10// Create/join → pvpCreateLobby (matchmaking or new lobby)
11// Play round → pvpAction with action: { move: 'rock' }
12// Resolve → pvpResolve with winnerId
13// Leave → pvpLeaveLobby
14// Push events → pvpLobbyUpdate (status changes, actions, resolution)
15// See "PVP Lobby" docs for full response shapes

Common Patterns

Listening for Messages

1// All games use id-based request/response matching
2var pendingRequests = new Map();
3var requestId = 0;
4
5function sendToParent(data) {
6 return new Promise(function(resolve, reject) {
7 var id = ++requestId;
8 pendingRequests.set(id, { resolve, reject });
9 var payload = Object.assign({}, data, { id: id });
10 // In preview mode, include gameConfig so the platform can
11 // validate your game without an upload
12 if (window.TEST_MODE) {
13 payload.gameConfig = window.GAME_CONFIG_FOR_API;
14 }
15 parent.postMessage(payload, '*');
16 setTimeout(() => {
17 if (pendingRequests.has(id)) {
18 pendingRequests.delete(id);
19 reject(new Error('Timeout'));
20 }
21 }, 30000);
22 });
23}
24
25window.addEventListener('message', (e) => {
26 const data = e.data;
27
28 // id-based response routing (from your sendToParent calls)
29 if (data.id && pendingRequests.has(data.id)) {
30 const h = pendingRequests.get(data.id);
31 pendingRequests.delete(data.id);
32 if (data.error) h.reject(new Error(data.error));
33 else h.resolve(data);
34 return;
35 }
36
37 // Stake update (user changed bet amount in parent UI)
38 if (data.type === 'stakeUpdate') {
39 state.stake = data.stake;
40 state.stakeUsd = data.stakeUsd;
41 state.currency = data.currency;
42 }
43
44 // Session restore (active path/multiplier/state-machine game)
45 if (data.type === 'sessionResume') {
46 // data.primitive = 'path' | 'multiplier' | 'state-machine'
47 // data.session = { sessionId, ... }
48 // Restore your UI to match the saved state
49 }
50
51 // Push events (multiplier crash, PVP updates, etc.)
52 if (data.type === 'serverCrash') { /* round crashed */ }
53 if (data.type === 'pvpLobbyUpdate') { /* lobby state changed */ }
54});

Sending gameReady

Always send gameReady when your game loads. This tells the platform your iframe is ready to receive config and active session data:

1// Send this at the end of your script
2parent.postMessage({ type: 'gameReady' }, '*');
All games are just HTML files. Use any framework, library, or plain vanilla JS. The only requirement is the postMessage API for communication.