资产负债表和钱包:多钱包体系结构
1)为什么要使用多钱包,目标是什么
一个"平衡=数字"条目不涵盖iGaming的现实。我们需要单独的钱包/子账户:真实现金(现金),奖金,花瓶池,飞盘,复合,有时是货币钱包(EUR/USD/BRL)。
体系结构目标:- 金钱的准确性(双入门,可审核性)。
- 注销政策(例如,首先是奖金/旅行者,然后是现金)。
- 速度(p95 API ≤ 250-400毫秒,实时投注/设置)。
- 安全性和合规性(KYC/AML,负责任的游戏限制,监管机构)。
- 规模:高峰→数万个操作/秒,数十亿个职位/月。
2)数据模型: "Ledger+Subwallets"
最小实体
帐户:玩家/品牌/市场。
示例表(简化)
sql
-双入账账户(包括办公室)
accounts(id, owner_user_id, type, currency, status,...)
-接线(双重记录,业务操作链接)
ledger_entries(id, posting_id, debit_account_id, credit_account_id,        amount_minor, currency, category, operation_id, created_at)
-丘陵(储备)
holds(id, account_id, amount_minor, currency, reason, expires_at, state,    operation_id, created_at)
-注销政策(优先事项)
spend_policies(id, market, wallet_priority jsonb, updated_at)
- 跨汇率fx_rates(ccy_from、ccy_to、率、精确、valid_from)规则:真相生活在布线日志中("ledger_entries")。当前余额是聚合(实例化截面)或从日志中计算(价格昂贵,但唯一正确)。
3)钱包的类型及其行为
4)注销政策和优先次序
明确地形式化资金来源算法: 示例(插槽/赌场):1.首先从WAGER中注销(如果有wager活动)。
2.然后从BONUS,直到用尽。
3.余额来自CASH。
示例(体育):1.首先是CASH(监管机构/税收)。
2.然后BONUS(freebet),翻译成WAGER。
在Postings中保留"策略解决方案"作为属性,以使札幌和审计看到"为什么会注销"。
5)金钱和运营的生命周期
存款
1. "POST/wallet/deposit" →创建一个贴纸记录(PSP香肠收件箱)。
2.PSP webhook(HMAC签名,"operation_id"的幂等)→ credit CASH,category="DEPOSIT"。
3.我们发布"wallet_updated"事件。
投注
1. "POST/bet/place" →在源帐户(CASH/BONUS/WAGER)上创建保留(备份)。
2.在确认费率时,→转移来源的保管→借款,这是提供商服务"结算"帐户的信用。
3.取消时为release hold。
设置(结果)
获胜:debit提供商的"结算"帐户→ credit CASH或政策WAGER→BONUS→CASH。
损失:我们关闭提供商的"支出"布线→没有向玩家贷款。
1.KYC/AML验证,负责任的游戏限制。
2.保持输出总和。
3.PSP的成功→最后的借款CASH →信用"付款"。
4.PSP故障→释放保留。
6)相似性和"意义上"的异常性"
具有唯一索引的"operation_id"(UUID/增强的 ULID)无处不在。重新查询→过去操作的状态。
PSP/游戏提供商 webhooks:收件箱表,从dedupe到"event_id+signature"。加工是Idempotent Worker(Outbox模式)。
客户端的HTTP上的Idempotency-Key;TTL存储≥ 24-72小时。
7)储备和丘陵(holds)
冷却不是注销,而是可用余额的"冻结"。
规则:- 霍尔寿命:seconds→minutes(费率)或时间(输出)。
- 冷藏可以部分或全部偿还(部分设置)。
- expire-自动释放和事件。
- 存储链接"hold_id" ↔ "bet_id/withdraw_id"。
8)货币,外汇和四舍五入
现金金额为小单位(cents),类型为整数。
四舍五入的银行(从头到尾)或T&C。
FX:"现金(EUR)"↔"现金(USD)"最好分开钱包。作为单独的操作进行转换:- "debit EUR,credit FX_EURUSD'和'debit FX_EURUSD,credit USD"-对审计透明。
- 在争议中,自动机"拉近"课程被禁止;所有规则都在FX政策中。
9)负责任的游戏和限制
Deposit/Bet/Loss/Session限制(每天/每周/每月),"cooling-off",自我释放。
在hold/debit之前实现为预检查。
故障日志包含在单独的审计日志中,sapport和监管机构可以使用。
10)钱包周围的反亲信号
设备/ASN集群,频繁的少量存款→主要推断,洗涤模式。
通过BIN/国家/设备在 "deposit/withdraw"上限为Velocity。
收件人的清单(钱包/IBAN),"mu子"列表。
钱包事件在功能性评分商店(登录/存款/投注)中→。
11)一致性和性能
真相vs缓存
真相在于ledger。对于API,"取得平衡"-保持实例化快照('user_id+ wallet_type → balance_minor,版本')。
写作:DB中的事务→使缓存失效。
在"重型"flow(实时)中,短的TTL 1-5与+在输出/大赌注之前必须进行真相检查是适当的。
攀岩
通过"user_id"(模块/排名)进行缓存,在CASH vs BONUS下进行单独的缓存池。
Hot Keys (VIP/bots)-通过"user_id"进行查询。
异步聚合(在背景中加上"posting" → "snapshot-updater")。
12) API合同(伪)
平衡
http
GET /v1/wallets?types=CASH,BONUS
→ 200 {"wallets":[
{"type":"CASH","currency":"EUR","available":12050,"hold":500,"version":1942},  {"type":"BONUS","currency":"EUR","available":3000,"wager_req":15000}
]}投注(持股)
http
POST /v1/bets/place
{"bet_id":"b_123","amount":500,"currency":"EUR","source_policy":"casino_default", "idempotency_key":"ik_abc"}
→ 201 {"status":"HELD","hold_id":"h_789","expires_in":30}定居点
http
POST /v1/bets/settle
{"bet_id":"b_123","result":"WIN","payout":1250}
→ 200 {"status":"SETTLED","cash_delta":+1250}http
POST /v1/withdrawals
{"withdraw_id":"w_456","amount":10000,"currency":"EUR","method":"sepa", "idempotency_key":"ik_def"}
→ 202 {"state":"PENDING","next_check_sec":2,"status_url":"/v1/withdrawals/w_456"}13)接线示例(双入口)
100欧元押金(PSP fee 1, commis.帐户是单独的)
Debit: PSP_Settlements(EUR)   10000
Credit: User.CASH(EUR)         10000
Debit: User.CASH (EUR) 100 (fee transfers)
Credit: PSP_Fees(EUR)          100BONUS出价5欧元(翻译成WAGER)
Debit: User.BONUS(EUR)       500
Credit: User.WAGER(EUR)500(移至"vager")
Debit: User.WAGER(EUR)       500
Credit: Provider.Settlement (EUR) 500(注销费率)赢得12欧元。5 →在CASH
Debit: Provider.Settlement(EUR)  1250
Credit: User.CASH(EUR)         1250持有的注销(通过HOLD服务帐户实现)
Debit: User.CASH(EUR)       500
Credit: User.HOLD (EUR) 500(已创建)
-在settle中
Debit: User.HOLD(EUR)       500
Credit: Provider.Settlement(EUR)   500
-取消后
Debit: User.HOLD(EUR)       500
Credit: User.CASH(EUR)         50014)审核、不变性和合规性
用于日志的WORM/immutability(对象存储/WAL归档)。
登机记录:谁阅读/更改限制,谁进行手动调整(仅通过带有理由的"调整")。
GDPR/监管机构:保存5-10年的交易(根据管辖权),玩家计算的透明度(注销/旅行者的历史)。
15)容错和DR
Multi-AZ是必需的;钱包的DR区域:区域中的同步复制,async到区域;PITR包括在内。
Promote standby-仅通过支票单手动进行(不包括split-brain)。
恢复每周检查(测试还原),核对校验报告的金额。
16)钱包的可观察性
SLI: `deposit_success_ratio`, `withdraw_success_ratio`, `bet_hold_latency_p95`, `settlement_latency_p95`.
Тех: `ledger_postings_rate`, `db_connections_saturation`, `queue_lag_seconds`, `hold_expired_rate`.
Alerts: PSP在市场上的成功率下降,"hold_expired_rate"的增长,游戏提供商的rassinchron(没有确认>N min)。
17)测试和质量控制
与PSP/游戏提供商的合同测试(webhooks/签名)。
基于财产的货币测试:借方总和==每个邮政的贷款总和。
Fuzz/chaos: PSP/提供程序延迟, webhook重播,network flappy。
负载:爆破投注(60-120秒),soaks(4-8小时),控制"queue_lag"和p99。
18)生产就绪支票清单
- 双重录音ledger,所有通过Posting的操作均带有"operation_id"。
- 清晰的间谍政策和优先顺序(随帖子一起进行)。
- Holds with TTL/partial settle/expiry, bet/withdraw链接。
- Inbox/Outbox,HMAC webhooks,在所有边界上均具有等效性。
- 个别钱包CASH/BONUS/WAGER/FS/POINTS;按货币划分。
- 小单位的FX和四舍五入;转换是一个单独的操作。
- 负责任的游戏限制为hold/debit;故障审核。
- 读取缓存(简称TTL)+在关键行动之前强制检查真相。
- PITR/备份/DR脚本;手动promote,定期DR演习。
- Dashbords/Alerts SLI+技术;WORM逻辑和访问日志。
- 负载/混沌测试;与PSP/提供商重新联系的报告。
二.总结
多钱包体系结构不是"很多资产负债表数字",而是具有双重记录,支出策略,保留和透明跟踪的财务系统,用于审计和玩家。在日志中保持真相,使用冰雹和偶然性,分开钱包和货币,自动重新计算和DR。因此,钱包对于UX来说将是快速的,对金钱来说是准确的,并且可以抵抗高峰负荷和监管检查。
