Hold the payout when a bonus turns into a withdrawal without play
A player claimed a deposit bonus twenty minutes ago, placed one small bet and has just requested a withdrawal. The pattern is plain in the sequence of events, and the review that reads it usually runs on a schedule, so the first pass lands after the payment has cleared. Signals has the minutes since the bonus and the bets placed since the deposit at the moment the request arrives, which is when the hold has to be decided.
minutes_since_bonus- Minutes since this player's last bonus was credited
bets_24h- Bets placed in the last 24 hours
stake_24h- Total amount staked in the last 24 hours
Holds the withdrawal for review when the request arrives inside the window your team sets after a bonus and the bets since then fall under the floor your rules name. A player who has played the bonus through goes to the normal payout queue.
from datetime import timedelta
from snowplow_signals import (
Attribute, Event, EventProperty, StreamAttributeGroup, user_id,
)
bonus_claimed = Event(name="bonus_claimed", vendor="com.example", version="1-0-0")
bet_placed = Event(name="bet_placed", vendor="com.example", version="1-0-0")
minutes_since_bonus = Attribute(
name="minutes_since_bonus",
type="double",
events=[bonus_claimed],
aggregation="time_since_last",
time_unit="min",
)
bets_24h = Attribute(
name="bets_24h",
type="int32",
events=[bet_placed],
aggregation="counter",
period=timedelta(hours=24),
default_value=0,
)
stake_24h = Attribute(
name="stake_24h",
type="double",
events=[bet_placed],
aggregation="sum",
property=EventProperty(vendor="com.example", name="bet_placed", major_version=1, path="stake"),
period=timedelta(hours=24),
default_value=0,
)
# Players are logged in at the cashier, so the group keys on the player id your platform sets.
game_promos_withdrawal = StreamAttributeGroup(
name="game_promos_withdrawal",
version=1,
attribute_key=user_id,
owner="you@example.com",
attributes=[minutes_since_bonus, bets_24h, stake_24h],
)// In the handler that receives a withdrawal request
const player = await signals.getServiceAttributes({
name: "game_promos_withdrawal",
attribute_key: "user_id",
identifier: playerId,
});
// { minutes_since_bonus: 22.4, bets_24h: 1, stake_24h: 5 }
if (player.minutes_since_bonus < rules.bonusWindowMinutes && player.bets_24h <= rules.minBetsAfterBonus) {
risk.hold({ withdrawal: withdrawalId, reason: "bonus_without_play" });
}