← BACK · 返回原型集
LIVE FLOWS 06 / TECH FLOWS v1.0
CORE TECH FLOWS · 核心技术流程

三张时序图把"为啥需要这些服务"讲透 DEPOSIT · BUY-TICKET-AND-DRAW · WITHDRAW

跟着一笔票的生命周期走一遍。 chain-service 监听链上事件、wallet-service 记账、game-service 编排开奖、 sign-service 独占私钥负责签名提现。 开奖时根据 one.draw.mode 进入 FULL_CHAINVRF_ONLY 分支。
Walk through a single round's life cycle: deposit confirms on-chain, ticket buy debits the ledger, round fills and triggers draw, prize gets paid on-chain via the isolated sign-service.

01
充值入账流程 DEPOSIT FLOW · USER TRC20 / ERC20 → LEDGER

用户从外部钱包转入用户专属充值地址;chain-service 监听到 tx → 等待 N 个确认 → wallet-service 入账 → Bot 推送回执。地址由 user-service 在用户首次绑定钱包时分配并持久化。

USER USER-SVC 查询我的充值地址
用户打开"充值"页面,前端调 GET /api/wallet/deposit-address?chain=BSC。 user-service 返回该用户在指定链的专属充值地址(首次访问时即时分配并入库)。
User opens Deposit screen; frontend asks user-service for the per-user / per-chain deposit address.
USER CHAIN (BSC / TRON) 从外部钱包转出 USDT
用户用 MetaMask / TronLink / 其他外部钱包向充值地址发送 USDT。 这笔 tx 完全发生在链上,平台此刻还不知道。
User sends USDT from external wallet to the deposit address. Off-platform tx, no backend involvement yet.
CHAIN-SVC 📡 轮询新区块 / 监听 ERC20 Transfer 事件
chain-service 通过 ChainAdapter 监听用户充值地址命中的 Transfer 事件。 两个 ChainAdapter 实现(BSC · TRON)封装自己的 RPC 调用细节,对上层透明。
chain-service polls / subscribes to Transfer events touching the user's deposit address per-chain.
CHAIN-SVC KAFKA · deposit.detected 发出 deposit-detected 事件
tx hash、from、to、amount、executionChain、blockNumber 落 Kafka topic。 等待 N 个区块确认(按链分配置,BSC ≈ 15、TRON ≈ 19)后才推进。
Detected tx emitted to Kafka with chain context; downstream waits N confirmations per chain config.
KAFKA PAY-SVC 入账:用户余额 += amount
wallet-service 消费事件,在 MySQL 内事务里写入账本流水余额变更。 幂等键 = executionChain + txHash + logIndex
wallet-service consumes event, writes ledger entry + balance update in a transaction; idempotency by chain+txhash.
PAY-SVC KAFKA · balance.credited TG BOT 推送充值到账
message-service 消费 balance.credited 事件 → 调 Bot API 推送给用户。模板:「✅ 充值 100 USDT 已到账 · tx: 0xabc...」。 用户可在 TG Mini App / Bot 内直接查看。
Bot pushes credit confirmation with tx hash; user can verify on block explorer.
边界 / Edge 用户用了错的链(比如往 BSC 地址转了 ERC20-USDT)→ chain-service 不会监听到,资金不会入账; wallet-service 提供「异常入账申诉」入口,运营后台人工挂账后由 sign-service 单独签名退款。
02
购票 + 开奖(双轨:FULL_CHAIN vs VRF_ONLY) BUY TICKET → ROUND FILL → DRAW · TWO ENGINES

余额够 → 锁号 → 扣账本 → 写订单。活动满号 → 触发 DrawEngine(运行时按 one.draw.mode 决定走哪个分支)。 中奖号码定下来 → wallet-service 派奖 → Bot 推送中奖。

USER GATEWAY GAME-SVC POST /api/ticket/buy {roundId, numbers[]}
gateway 校验 JWT / TG initData,转给 game-service。 game-service 把所选号码在 Redis 加分布式锁,避免并发抢同号。
Auth at gateway → game-service locks selected numbers in Redis to prevent double-allocation.
GAME-SVC PAY-SVC 扣余额:用户账本 -= price × count
wallet-service 在事务里检查余额 → 扣减 → 落账本流水 → 返回成功。 余额不足 → 整个 buy 流程回滚,号码锁释放。
wallet-service debits balance in a transaction; on failure, lock is released and order rolls back.
GAME-SVC 写订单 + 标记号码已售 + 释放锁
ticket 表写一笔订单(user, round, numbers, paid);号码池中对应号码标 SOLD。 发 ticket.bought 事件到 Kafka 供下游消费(统计、推送)。
Ticket persisted; round's number pool marked SOLD; Kafka event for downstream consumers.
GAME-SVC 检查开奖条件 → 若满足 → 触发 DrawEngine
每次售出后检查:号码池是否全部售完?或满足 PRD 第 8 节的开奖触发条件? 满足 → 进入 DrawEngine。三种引擎在这里分叉
After each buy, check fill condition; if met, route to the active DrawEngine implementation.

▸ FULL_CHAIN 分支 · 全链上开奖

A1 GAME-SVC SIGN-SVC 请求签名 LotteryRound.draw() tx
sign-service 校验请求合法性(mTLS + IP 白名单 + nonce 防重放),用热钱包私钥签名,返回 raw tx。
A2 CHAIN-SVC LotteryRound 广播 tx
chain-service 把 raw tx 上链;合约内执行抽奖逻辑(区块哈希取数 → 计算中奖号),发出 DrawCompleted(winnerNumber, prize) 事件。
A3 CHAIN-SVC KAFKA · draw.completed 监听 DrawCompleted 事件 → 回流
chain-service 监听到事件 → 推 Kafka。中奖号码完全由链上决定,平台只是消费者。

▸ VRF_ONLY 分支 · 链上随机 + 链下结算

B1 GAME-SVC SIGN-SVC 请求签名 VRFConsumer.requestRandomness() tx
构造调用 Chainlink VRF 的请求 tx,由 sign-service 签名。
B2 CHAIN-SVC VRFConsumer 广播 tx → Chainlink VRF 回调
Chainlink VRF Coordinator 异步回调合约的 fulfillRandomWords(), 发出 RandomnessDelivered(requestId, randomness) 事件。
B3 CHAIN-SVC GAME-SVC 回流 randomness → 链下计算中奖号
game-service 收到 randomness 后,按公开算法映射到号码池中的中奖号。 折中:随机数来自链上 VRF(可验证),结算在链下(省 gas)。
GAME-SVC PAY-SVC 派奖:中奖用户余额 += prize
wallet-service 在事务里给中奖者加余额,写流水。 扣 5% 平台手续费(按 PRD 第 15 节"钱怎么分"分配)。
GAME-SVC KAFKA · round.drawn TG BOT 推送中奖通知 + 区块浏览器链接
中奖用户收到 Bot 私聊:「🎉 你中了第 #00428 期!中奖号 1024,奖金 100 USDT。tx: 0xabc... · 区块浏览器验证 →
降级 / Fallback 链堵 / VRF 长时间无响应 → 运维触发 Nacos 切到 BACKEND 模式(链下 RNG,凭证仍写区块浏览器可查的 anchor tx)。 所有切换都有审计日志,需要运维 + 安全二人复核。
03
提现 + 签名隔离 WITHDRAW FLOW · SIGN-SERVICE BOUNDARY

sign-service唯一持有热钱包私钥的服务,业务服务永远不直接接触私钥。 所有提现 tx 都通过 mTLS 内部 API 让 sign-service 签名后广播。Phase 2 切换到多签时这条路径不变,只是签名变成 m-of-n。

本节定位 工程细节版 —— 完整 7 步带参数、nonce、限额、异步事件。 想看老板向的视觉动画版?看 prototype-mechanics.html 04 出款原理 →

USER PAY-SVC POST /api/withdraw {chain, address, amount}
用户在 TG Mini App 提交提现申请。wallet-service 校验:余额够吗?日提现额度够吗?地址在黑名单? 通过后锁定金额(账本上标为 PENDING_OUT),写一笔 withdraw 记录。
User submits withdrawal; wallet-service validates balance, daily cap, blacklist; locks amount and creates record.
PAY-SVC 人工审核(高额)/ 自动放行(小额)
按 PRD 第 10 节:小额(< 100 USDT)自动放行;高额 → 运营后台审批队列。 审批通过后才进入下一步。
Small amounts auto-approved; large amounts route to ops review queue per PRD 10.
PAY-SVC SIGN-SVC 请求签名 TRC20 transfer tx
调用 sign-service 内部 API(mTLS,IP 白名单):「请帮我签一笔从热钱包向 0xUSER100 USDT 的 tx」。 私钥永远不离开 sign-service 子网
wallet-service calls sign-service over mTLS with the unsigned tx params; key never leaves the isolated subnet.
SIGN-SVC 🔒 校验 + 签名 + 返回 raw tx
sign-service 内部检查:调用方在白名单?请求 nonce 防重?单笔限额?日累计限额? 全通过 → 从 AWS KMS 读出 key 完成签名 → 返回 raw tx。所有请求和决策都进审计日志
sign-service: caller allowlist + nonce + per-tx limit + daily limit → KMS-backed signing → audited.
PAY-SVC CHAIN-SVC 广播 raw tx
chain-service 把 raw tx 推到链上。返回 txHash 后立即写入 withdraw 记录。
chain-service broadcasts raw tx and returns txHash; wallet-service persists it on the withdraw record.
CHAIN-SVC 📡 KAFKA · withdraw.confirmed 监听确认 → 推 Kafka
chain-service 监听 tx 确认数;达到阈值 → 推送 withdraw-confirmed 事件。 失败(gas 不够 / nonce 冲突)→ withdraw-failed 事件,wallet-service 解锁余额。
Waits for confirmations; emits confirmed or failed; on fail wallet-service unlocks user balance.
PAY-SVC TG BOT 通知提现完成 + 区块浏览器链接
推送:「💸 提现 100 USDT 已发送 · tx: 0xabc... · 查看链上确认 →」。 用户也可在 TG Mini App 内查看提现记录和 tx hash。
Phase 2 / 多签 sign-service 内部签名逻辑从「单签热钱包」切换到「m-of-n 多签门限」。 调用者(wallet-service)的 API 契约不变,多签复杂度全部封装在 sign-service 内部。
角色图例 ACTOR LEGEND
USER终端用户
GATEWAYAPI 网关
USER-SVC账户 / 钱包绑定
GAME-SVC期次 / 开奖 / 订单
PAY-SVC充提 / 账本
CHAIN-SVC链上广播 / 监听
SIGN-SVC私钥隔离 / 签名
KAFKA事件总线
CONTRACT链上 Solidity 合约
TG BOT消息推送
内部 RPC / HTTP 调用
链上交易 / 事件
sign-service mTLS 签名调用
EDGE 边界 / 降级注释