Take & Settlement Test Cases
File: backend/tests/integration/sanity/08-transfer-settle.test.ts
Total: 20 tests, all passing
Runs against: Real Postgres DB, real settlement service, real transferSettleService
Setup
Hierarchy: Admin → Agent (CL=10000) → Player (CL varies per test)
Commission: 2% on exchange markets (betfair-ex)
Provider: 5000 USD × 100 exchangeRate = 500,000 FP
A. Basic Direction Tests (Transfer & Settle formulas)
A1: Player loses, agent settles full amount
- Setup: Player CL=1000, places back bet stake=500 odds=2.0, loses
- Action: Agent settles full amount (|take|)
- Assertions:
- Player balance (AC) unchanged after settlement
- Player credit limit (CL) decreased by settle amount
- Player take = 0 after settlement
A2: Player wins, agent settles full amount
- Setup: Player reset to CL=1000 BP=1000, places back bet stake=200 odds=3.0, wins
- Action: Agent settles full amount
- Assertions:
- Player balance decreased by settle amount (got paid cash off-platform)
- Player CL unchanged
- Agent balance increased by settle amount (paid cash, gets on-platform credit)
- Player take = 0 after settlement
A3: Partial settle (loss)
- Setup: Player CL=1000, places back bet stake=300 odds=2.0, loses
- Action: Agent settles 100 of ~300 owed
- Assertions:
- CL decreased by 100 (partial)
- Take moved toward 0 by exactly 100
A4: Partial settle (win)
- Setup: New player CL=1000, places back bet stake=100 odds=4.0, wins
- Action: Agent settles 100 of the win
- Assertions:
- Player balance decreased by 100
- Agent balance increased by 100
- Take moved toward 0 by exactly 100
B. Anti-Recycling Enforcement
B1: Player cannot bet after CL zeroed by settlement
- Setup: Player CL=500, places back bet stake=500 odds=2.0, loses all
- Action: Agent settles full amount → CL goes to 0
- Assertions:
- CL = 0
- Balance = 0
- Attempt to place bet → rejected (insufficient balance)
C. Hierarchy Chain Settlement
C1: Full chain settlement zeroes out all takes
- Setup: MA → Sub-Agent → Player hierarchy, player places back bet stake=400 odds=2.0, loses
- Action:
- Sub-agent settles player (full amount)
- MA settles sub-agent (full amount)
- Assertions:
- Player take = 0 after step 1
- Sub-agent take ≈ 0 after step 2
D. Validation Guards
D1: Settle amount > |take| is rejected
- Setup: Player loses 200
- Action: Attempt to settle |take| + 100
- Assertion: Throws error
D2: Settle when take is 0 is rejected
- Setup: Fresh player with no bets (take = 0)
- Action: Attempt to settle 100
- Assertion: Throws error
D3: Negative amount is rejected
- Action: Attempt to settle -50
- Assertion: Throws error
E. PnL-Based Take (Bet Placement vs Settlement)
E1: Open bet does NOT change currentTake
- Setup: Fresh player (take = 0)
- Action: Place back bet stake=300 odds=2.5
- Assertion: Take still = 0 (no PnL event on bet placement)
E2: After bet settles, currentTake reflects profitLoss delta
- Setup: From E1, open bet exists
- Action: Settle bet as loss
- Assertion: Take = -300 (profitLoss applied as delta)
F. Commission Per-User
F1: User A commission processes even when User B has unsettled orders
- Setup: Two players bet on same market (same fixtureId + marketId)
- Player 1: back stake=100 odds=3.0
- Player 2: back stake=100 odds=2.0
- Action: Settle player 1 as win, player 2 stays unsettled
- Assertions:
- Player 1 has commission record (2% of 200 profit = 4)
- Player 2 has NO commission record (still unsettled)
- Action: Settle player 2 as loss
- Assertion: Player 2 still no commission (net PnL <= 0)
H. Settlement History Audit Trail
H1: Settlement record has correct takeBefore/takeAfter
- Setup: Player places back bet stake=300 odds=2.0, loses
- Action: Settle full amount with notes
- Assertions:
- TransferSettlement record exists
takeBeforematches actual take before settlementtakeAfter≈ 0notes= 'Test settlement note'
T. Take Calculation Correctness
T1: Commission deducted from take
- Setup: Fresh player CL=1000, places back bet stake=200 odds=3.5, wins
- Calculation: return=700, profitLoss=500, commission=500×0.02=10
- Assertion: take = 500 - 10 = 490
T2: Commission NOT double-counted in BETS API path (regression)
- Setup: Fresh player CL=1000, two bets in same market settled one-by-one
- Bet 1: back stake=100 odds=3.0 → wins (profitLoss=200)
- Bet 2: back stake=100 odds=2.0 → loses (profitLoss=-100)
- Action: Settle bet 1 (commission not triggered), then settle bet 2 (triggers commission)
- Calculation: Net market PnL=100, commission=100×0.02=2
- Assertions:
- take = 200 + (-100) + (-2) = 98
- Commission record exists exactly once (not duplicated)
T3: No commission on bookmaker market
- Setup: Fresh player CL=1000, bookmaker (bifrost) back bet stake=100 odds=2.5, wins
- Calculation: profitLoss=150, no commission (bookmaker market)
- Assertions:
- take = 150 (raw profitLoss, no commission deduction)
- No commission record exists for this market
T6: Lay bet win — take += stake minus commission
- Setup: Fresh player CL=1000, lay bet stake=100 odds=3.0, wins
- Calculation: profitLoss=+100 (lay win = stake), commission=100×0.02=2
- Assertion: take = 100 - 2 = 98
T7: Void bet — take unchanged
- Setup: Fresh player CL=1000, places back bet stake=300 odds=2.0
- Action: Settle as void
- Assertion: take = 0 (void = zero profitLoss = zero delta)
T11: Transfer & Settle does NOT propagate to agent take
- Setup: Fresh player CL=500, places back bet stake=200 odds=2.0, loses
- Action: Agent settles player (full 200)
- Assertions:
- Player take = 0
- Agent take unchanged (settlement doesn't propagate up)
T12: cumulativePnl tracks PnL only, settledAmount tracks settlements
- Setup: Fresh player CL=500, places back bet stake=300 odds=2.0, loses
- After PnL event:
- cumulativePnl = -300
- settledAmount = 0
- currentTake = -300
- Action: Settle 200
- After settlement:
- cumulativePnl = -300 (unchanged — PnL doesn't change on settlement)
- settledAmount = 200
- currentTake = -100 (-300 + 200)
Take Touch Points Verified
| Event | Take changes? | Tests covering it |
|---|---|---|
| Entity creation | No (initialized at 0) | E1 (implicit) |
| Bet placement | No | E1 |
| Back bet loss settlement | Yes (+profitLoss delta) | E2, A1, A3, T12 |
| Back bet win settlement | Yes (+profitLoss delta) | A2, A4, T1, T2 |
| Lay bet win settlement | Yes (+profitLoss delta) | T6 |
| Void settlement | No (zero delta) | T7 |
| Commission deduction | Yes (-commission delta) | T1, T2 |
| No commission on bookmaker | Verified | T3 |
| Commission per-user isolation | Verified | F1 |
| Commission not double-counted | Verified | T2 |
| Transfer & Settle (loss direction) | Yes (toward 0, CL decreases) | A1, A3, B1 |
| Transfer & Settle (win direction) | Yes (toward 0, BP decreases) | A2, A4 |
| Transfer & Settle does NOT propagate up | Verified | T11 |
| Chain settlement (MA→Agent→Player) | Verified | C1 |
| Over-settle rejected | Verified | D1 |
| Zero take settle rejected | Verified | D2 |
| Negative amount rejected | Verified | D3 |
| Anti-recycling (CL=0 blocks betting) | Verified | B1 |
| Audit trail (takeBefore/takeAfter/notes) | Verified | H1 |
| Audit columns (cumulativePnl, settledAmount) | Verified | T12 |