Crypto Casino Bonus System Development
The bonus system is a key tool for attracting and retaining crypto casino players. Welcome bonuses, reload bonuses, free spins — all of this requires accurate wagering requirement accounting and protection from abuse.
Types of Bonuses
Welcome Bonus — bonus for first deposit. Standard formula: 100% match up to 1 BTC + X free spins. Wagering requirement: 35-40x of the bonus amount.
Reload Bonus — regular bonuses on repeat deposits. Smaller amount, encourages activity.
No-Deposit Bonus — bonus without deposit for new users. Marketing tool, strict wagering requirements.
Cashback — a percentage of losses is returned to the player. Reduces risk, increases loyalty.
Data Model
class Bonus(BaseModel):
id: str
user_id: str
template_id: str # reference to bonus type
type: str # 'DEPOSIT_MATCH', 'FREE_SPINS', 'CASHBACK', 'NO_DEPOSIT'
status: str # 'PENDING', 'ACTIVE', 'WAGERING', 'COMPLETED', 'EXPIRED', 'CANCELLED'
# Amounts
bonus_amount: Decimal # issued bonus
deposit_amount: Decimal # deposit amount (for match bonuses)
wagering_requirement: Decimal # how much needs to be wagered
wagered_amount: Decimal # how much has been wagered
locked_funds: Decimal # bonus funds locked until wagering completion
# Restrictions
eligible_games: list[str] # list of games where wagering counts
contribution_pct: dict[str, float] # {'slots': 100, 'blackjack': 10, 'roulette': 20}
max_bet_while_bonus: Decimal # maximum bet during active bonus
expires_at: datetime
# Source
triggered_by: str # 'DEPOSIT', 'PROMO_CODE', 'REFERRAL', 'VIP_REWARD'
promo_code: Optional[str]
Wagering Tracking
class WageringTracker:
async def on_bet_settled(self, bet: BetResult):
"""Called on each closed bet"""
# Get user's active bonuses
active_bonuses = await self.bonus_repo.get_active_bonuses(bet.user_id)
for bonus in active_bonuses:
if not self.is_bet_eligible(bet, bonus):
continue
# Calculate this bet's contribution to wagering
contribution_pct = bonus.contribution_pct.get(bet.game_type, 100.0)
wagered = bet.amount * Decimal(str(contribution_pct / 100))
# Check bet limit
if bonus.max_bet_while_bonus and bet.amount > bonus.max_bet_while_bonus:
# Bet exceeded limit — terms violation
await self.cancel_bonus_for_violation(bonus, reason="MAX_BET_EXCEEDED")
continue
async with self.db.transaction():
bonus.wagered_amount += wagered
if bonus.wagered_amount >= bonus.wagering_requirement:
await self.complete_bonus(bonus)
else:
await self.bonus_repo.update_wagered(bonus.id, bonus.wagered_amount)
async def complete_bonus(self, bonus: Bonus):
"""Complete wagering requirement — unlock funds"""
async with self.db.transaction():
# Unlock bonus funds
await self.balance_service.unlock_funds(
user_id=bonus.user_id,
currency="BTC",
amount=bonus.locked_funds,
reference=f"BONUS_COMPLETE:{bonus.id}",
)
bonus.status = "COMPLETED"
await self.bonus_repo.save(bonus)
await self.notifier.send_bonus_complete(bonus.user_id, bonus.locked_funds)
Protection from Bonus Abuse
Bonus hunters are a real problem for casinos. They take bonuses, complete wagering with minimal risk (even bets on black/red in roulette) and withdraw funds.
Game Restrictions — prohibit wagering in low-edge games. Only slots (100% contribution), table games with high house edge.
Max bet rule — cannot bet more than €5-10 with active bonus.
IP/Device fingerprinting — multiple accounts from one IP/device — block bonuses.
Velocity checks — too fast wagering completion requires verification.
Linked account detection — detection of linked accounts for multiple welcome bonuses.
| Violation Type | Action |
|---|---|
| Max bet exceeded | Bonus cancellation |
| Multiple accounts | Block all accounts |
| Eligible game abuse | Recalculate wagering contribution |
| Chargeback | Cancel all bonuses + block account |







