Skip to content

Crash game responses ​

Crash is a live game. The engine commits its bust point before the round starts. Server time controls the curve and all cashouts.

Implement the shared frontend requirements. Use the Crash transport for requests and broadcasts on one connection. SDK 0.2.18 enableWebSockets discards these broadcasts.

Opening a Round ​

Validate each stake and the complete debit. Check whether the jurisdiction permits multiple simultaneous bets and automatic cashout targets.

The following fragments assume an open GameSocket named socket. Its event handler must exist before the first request.

typescript
import { crashPlaceBetData, type IPlaceBetReply } from '@hizi.io/engine-sdk';

const bets = [
  { stake: 100, autoCashOutMultiplier: 2.5 },
  { stake: 100 },
];
const response = await socket.request<IPlaceBetReply>({
  op: 'placeBet', token,
  ...crashPlaceBetData(bets),
});
if (!response.success) {
  // Disable opening bets. Reconcile the session before another action.
}

crashPlaceBetData returns { bets }. SDK additionalData normally flattens this field into the request. With the raw transport, spread the helper directly.

The total debit is the sum of the bet stakes. autoCashOutMultiplier must exceed 1. Omit it for a manual bet. Do not implement automatic cashout by watching local animation ticks.

A single manual bet can instead use { op: 'placeBet', token, stake: 100 }. Lock the opening action before sending it. Enable the next round only after confirmed settlement and required cycle timing.

Listening to the Curve ​

The transport calls your handler with (event, payload). Validate payloads against the exported TCrashEvent union before using them.

EventPayload and action
roundStartedroundHash, betHashes in submission order, currentMultiplier: 0, and optional balance. Bind the new round.
roundResumedroundHash, startTime, currentMultiplier, betsSubmitted, and totalWinValue. Replace local state with the restored state.
roundTickcurrentMultiplier. Update the visual curve.
betCashedOutbetHashes, matching winValues, winValue, cumulative totalWinValue, multiplier, and isAuto. Mark those bets settled.
roundEndedcurrentMultiplier, plus revealedServerSeed on a provably fair round. currentMultiplier is absent when the round closes externally. The SDK's ICrashRoundEndedPayload does not declare revealedServerSeed, so read it from the raw frame. Stop the live curve and disable cashout.
balanceUpdatedCumulative totalWinValue and winValues: { hash, value }[]. Reconcile settled bets and refresh the authoritative balance.

Each event name also exists in CRASH_EVENTS. betCashedOut can occur several times. Replace cumulative totalWinValue; do not add it repeatedly.

Most events do not include a round hash. Bind them to the active connection and round established by roundStarted or roundResumed. Ignore callbacks from an old connection after reconnecting. Events can arrive before the request reply.

Do not reveal the bust point before roundEnded. Local interpolation estimates presentation only. It cannot establish a payable multiplier.

Manual Cashout ​

Use an unsettled bet hash from the server. Mark its request as pending before sending it. Prevent a second cashout request for the same bet.

typescript
import { crashCollectData, type ICollectReply } from '@hizi.io/engine-sdk';

const response = await socket.request<ICollectReply>({
  op: 'collect', token,
  ...crashCollectData(betHash),
});

The helper accepts one hash or an array. The engine selects the multiplier when the request arrives. It rejects cashout after bust with GAMEROUNDNOTACTIVE.

A successful manual cashout produces betCashedOut with isAuto: false. Reconcile both the reply and the event without displaying two credits. A lost reply does not authorize another cashout request without checking the bet state.

Reconnecting Mid-Round ​

The curve continues while the frontend is disconnected. Disable cashout and opening bets during recovery. Close the old transport and register the replacement handler.

Refresh credentials when required. Load the authoritative round before deciding whether a live resume is necessary. For a confirmed open Crash round, send no new stake or bets:

typescript
const response = await socket.request<IPlaceBetReply>({ op: 'placeBet', token });

The engine returns the existing scenario and emits roundResumed. Restore settled bets, pending bets, the curve position, and cumulative winnings. Resume normal event handling.

ResponseRequired recovery
GAMEROUNDALREADYSTARTEDThe live round can already be settled. Reload its result and balance before allowing another player-requested opening.
GAMEROUNDNOTACTIVEThe live state is unavailable. Reconcile through loadConfig, history, or the operator. Do not assume wallet settlement.
DATASTRUCTUREWRONGState cannot be interpreted. Keep play blocked and report the operator error.
Network error or timeoutPreserve uncertainty. Reconnect and reconcile; do not send another opening bet.

A resume can itself produce final settlement events. Continue receiving them during recovery. If state remains ambiguous, keep new play blocked.

Scenario Shape ​

typescript
interface ICrashScenario {
  startTime: string;
  betsSubmitted: ICrashBet[];
  betsCollected?: Record<string, { multiplier: number; amount: number }>;
}
interface ICrashBet {
  hash: string;
  stake: number;
  autoCashOutMultiplier?: number;
  multiplierCollected?: number;
  amountCollected?: number;
  collected?: boolean;
  inProgress?: boolean;
  collectedAtinMS?: number;
}

startTime is an ISO timestamp. collectedAtinMS measures milliseconds since that time. Stakes and collected amounts use minor currency units. Multipliers are decimal factors.

The scenario describes accepted bets and cashouts. Do not reconstruct it from the currently displayed curve.

Configuration ​

Read config.loadConfig as the exported ICrashLoadConfig after validating its shape.

FieldMeaning
startMultiplierVisual multiplier at curve start.
timerIntervalMsServer broadcast interval in milliseconds.
startGameDelayMsDelay before the curve rises.
gameRtpReturn to player as a fraction, such as 0.95.
minMultiplier, maxMultiplierConfigured bounds on the drawn multiplier. minMultiplier is also the base factor of the curve itself. A config that raises minMultiplier rescales the whole curve.
growthExponential growth per second.
postCashoutSpeedMultiplierPresentation speed factor after all bets cash out.

The engine can accelerate the remaining flight after every bet has settled. This does not create additional winnings. Do not confuse the configured maxMultiplier cap with the hidden bust point of a live round.

Game Flow ​

text
validated player opening → request on the event connection
                        → roundStarted → ticks → cashout events
                                                ↓
                           roundEnded → balanceUpdated → balance reconciliation
                                                ↓
                            timing and input gates → next player opening

Operator pause can block new actions. It cannot pause server time. Do not freeze the screen while presenting a cashout button as live. Agree the wrapper's behavior for active real-time rounds.

The release checklist includes disconnection before cashout, events before replies, and repeated settlement messages.

Provably Fair Verification ​

Crash has one seed-derived surface: the committed maxMultiplier, which is the curve's bust point. (A seed-derived surface is the part of the outcome that the provably fair seeds determine.) Everything else is not derivable from the seeds. This includes the curve interpolation, the player's manual cashout time, and auto-cashout settlement. The engine tracks these by wall-clock time or by operator audit. Use pfVerify to confirm that the engine fixed the bust point before the round started.

Cashouts are not PF-derived

A passing pfVerify call proves the engine could not have moved the bust point after it committed to that point. It does not verify that the engine settled your bet at the right multiplier. That check is a separate operator-audit concern (timestamps, multiplier-at-cashout reconciliation).

Request ​

This request needs no actions and no bets. The seeds alone determine the round's maxMultiplier.

typescript
import { pfVerify } from '@hizi.io/engine-sdk';

const reply = await pfVerify({
  backendURL,
  token,
  serverSeed: revealedServerSeed,   // from the ROUND_ENDED broadcast
  clientSeed: pf.clientSeed,
});

Reading the response ​

This is a one-shot check: steps has one entry.

  • rngData: one double row (the entropy that derives the multiplier). Compare it as an array against the live pf.rngData.
  • steps[0].scenario.maxMultiplier: equals the multiplier where the curve crashed on the live ROUND_ENDED event.
typescript
if (!reply.success) return;
const { rngData, steps } = reply.result;
const rngOk = deepEqual(rngData, pf.rngData);
const bustOk = steps[0].scenario.maxMultiplier === liveCrashPoint;

If both values match, the engine committed to the bust point before the player placed any bets.

Next Steps ​

  • Response Handling: the IGameResult structure and engineData fields.
  • Blackjack Responses: a rules-based game with a richer action tree.
  • Types Reference: ICrashScenario, ICrashBet, ICrashLoadConfig, TCrashEvent, CRASH_EVENTS, crashPlaceBetData, crashCollectData.