7-Day Play Streak — Mobile Mid-fi Blueprint

PRD-driven behavioral prototype for the reusable Streak experience, wired to the backend contract of challenge.getStreak and challenge.confirmCompletedStreak. Fixed mobile baseline: 360 px. Every scenario shows the payload the endpoint actually returns and the FE logic that derives the screen from it.
PRD-driven / non-final UI

How the 7-Day Play Streak works

Place at least one qualifying real-money bet during each UTC calendar day. Your personal seven-day streak is anchored to the day of your first qualifying bet. One missed day per reward week can be covered by your single Streak Saver. A second missed day ends the streak without advancing the reward week and without giving the Saver back. Collect the required days to earn the reward for your current VIP Level and reward week. Bonus rewards are issued to My Bonuses with a limited lifetime; Raffle Tickets and VIP Points are credited automatically.

Backend response & FE logic
state

Endpoint contract

Read the widget

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "challenge.getStreak",
  "params": { "langId": 3 }
}

Put out a completion notice

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "challenge.confirmCompletedStreak",
  "params": { "streak_id": 918 }
}

{ "result": { "success": true } }

Auth & availability

  • langId is required on getStreak and must be a positive integer — it resolves the translated bonus name. A call without it fails param validation.
  • confirmCompletedStreak takes streak_id — snake_case, unlike every other param on this module.
  • Authenticated players only. A guest call returns a JSON-RPC error (unauthorized), not a result — the widget must not be mounted for guests.
  • With the CHALLENGES_ENABLED flag off, getStreak returns {"state":"unavailable"} and confirmCompletedStreak returns {"success":false}.

Field availability by state

field            unavail preview idle running
state               •       •      •      •
rotationLength      –       •      •      •
ruleset             –       •      •      •
rewardWeek          –       –      •      •
requiredDays        –       –      •      –
reward              –       –    •|null •|null
rewards[]           –       •      –      –
cta                 –       •      –      –
streak{}            –       –      –      •
completedStreak     –       –     opt    opt

Reward object shapes

bonus   { type, bonusId, bonusName }   bonusName may be null
tickets { type, amount }
points  { type, vipPointsRewardId }    no amount, no name

Refresh model

  • Day marks are written by the streak cron (/api/v2/cron/process-streak-challenges, Redis lock TTL 900 s), which walks bet transactions in batches. A bet is not reflected in the payload synchronously — plan for up to one cron cycle of latency.
  • Drive countdowns locally from secondsToDayEnd / secondsToStreakEnd, and refetch when either reaches 0 instead of polling on a fixed timer.
  • All day boundaries are computed against UTC on the server; never recompute them from the device timezone.