# Wallet Service 架构设计文档 ## 概述 Wallet Service 是 RWA (Real World Assets) 榴莲认种平台的核心钱包与账本服务,负责管理用户资产、处理充值/提现、记录交易流水、管理奖励结算等功能。 ## 技术栈 | 组件 | 技术选型 | 版本 | |------|---------|------| | 运行时 | Node.js | 20.x | | 框架 | NestJS | 10.x | | 语言 | TypeScript | 5.x | | ORM | Prisma | 5.x | | 数据库 | PostgreSQL | 15.x | | 认证 | JWT (passport-jwt) | - | | 精度计算 | Decimal.js | 10.x | | API文档 | Swagger | 7.x | ## 架构模式 本服务采用 **领域驱动设计 (DDD)** + **CQRS** 架构模式: ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Presentation Layer │ │ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────┐ │ │ │ WalletController │ │ LedgerController │ │ DepositController │ │ │ │ /wallet/* │ │ /wallet/ledger │ │ /wallet/deposit │ │ │ └────────┬─────────┘ └────────┬─────────┘ └──────────┬───────────┘ │ └───────────┼─────────────────────┼──────────────────────┼────────────────┘ │ │ │ ┌───────────┼─────────────────────┼──────────────────────┼────────────────┐ │ │ Application Layer (CQRS) │ │ │ ▼ ▼ ▼ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ WalletApplicationService │ │ │ │ ┌─────────────────────┐ ┌─────────────────────────────┐ │ │ │ │ │ Commands │ │ Queries │ │ │ │ │ │ - HandleDeposit │ │ - GetMyWallet │ │ │ │ │ │ - DeductForPlanting │ │ - GetMyLedger │ │ │ │ │ │ - AddRewards │ │ │ │ │ │ │ │ - ClaimRewards │ │ │ │ │ │ │ │ - SettleRewards │ │ │ │ │ │ │ └─────────────────────┘ └─────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────┼───────────────────────────────────────┐ │ Domain Layer │ │ │ ┌──────────────────────────────┼──────────────────────────────────┐ │ │ │ Aggregates │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │ WalletAccount │ │ DepositOrder │ │ SettlementOrder │ │ │ │ │ │ (聚合根) │ │ │ │ │ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ │ │ │ │ │ ┌──────┴──────────────────────────────────────────────────┐ │ │ │ │ │ LedgerEntry │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ Value Objects │ │ │ │ Money │ Balance │ Hashpower │ UserId │ WalletId │ Enums │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ Domain Events │ │ │ │ DepositCompleted │ BalanceDeducted │ RewardAdded │ etc. │ │ │ └───────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────┼───────────────────────────────────────┐ │ Infrastructure Layer │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ Repository Implementations │ │ │ │ WalletAccountRepository │ LedgerEntryRepository │ etc. │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ Prisma Service │ │ │ │ (Database Connection Pool) │ │ │ └────────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────┐ │ PostgreSQL │ │ Database │ └──────────────────┘ ``` ## 目录结构 ``` src/ ├── api/ # 表示层 (Presentation Layer) │ ├── controllers/ # HTTP 控制器 │ │ ├── wallet.controller.ts # 钱包相关接口 │ │ ├── ledger.controller.ts # 流水查询接口 │ │ ├── deposit.controller.ts # 充值入账接口 (内部) │ │ └── health.controller.ts # 健康检查 │ ├── dto/ │ │ ├── request/ # 请求 DTO │ │ └── response/ # 响应 DTO │ └── api.module.ts │ ├── application/ # 应用层 (Application Layer) │ ├── commands/ # 命令 (写操作) │ │ ├── handle-deposit.command.ts │ │ ├── deduct-for-planting.command.ts │ │ ├── add-rewards.command.ts │ │ ├── claim-rewards.command.ts │ │ └── settle-rewards.command.ts │ ├── queries/ # 查询 (读操作) │ │ ├── get-my-wallet.query.ts │ │ └── get-my-ledger.query.ts │ └── services/ │ └── wallet-application.service.ts │ ├── domain/ # 领域层 (Domain Layer) │ ├── aggregates/ # 聚合 │ │ ├── wallet-account.aggregate.ts │ │ ├── ledger-entry.aggregate.ts │ │ ├── deposit-order.aggregate.ts │ │ └── settlement-order.aggregate.ts │ ├── value-objects/ # 值对象 │ │ ├── money.vo.ts │ │ ├── balance.vo.ts │ │ ├── hashpower.vo.ts │ │ ├── user-id.vo.ts │ │ ├── wallet-id.vo.ts │ │ └── [各种枚举].enum.ts │ ├── events/ # 领域事件 │ │ ├── deposit-completed.event.ts │ │ ├── balance-deducted.event.ts │ │ └── [其他事件].ts │ └── repositories/ # 仓储接口 │ ├── wallet-account.repository.interface.ts │ └── [其他接口].ts │ ├── infrastructure/ # 基础设施层 │ ├── persistence/ │ │ ├── prisma/ │ │ │ └── prisma.service.ts │ │ └── repositories/ # 仓储实现 │ │ ├── wallet-account.repository.impl.ts │ │ └── [其他实现].ts │ └── infrastructure.module.ts │ ├── shared/ # 共享模块 │ ├── decorators/ # 装饰器 │ ├── filters/ # 异常过滤器 │ ├── guards/ # 守卫 │ ├── interceptors/ # 拦截器 │ ├── strategies/ # 认证策略 │ └── exceptions/ # 自定义异常 │ ├── app.module.ts # 根模块 └── main.ts # 入口文件 ``` ## 核心领域模型 ### 1. WalletAccount (钱包账户聚合) 钱包账户是核心聚合根,管理用户的所有资产状态: ```typescript WalletAccount { // 标识 walletId: WalletId userId: UserId // 多币种余额 balances: { usdt: Balance { available, frozen } dst: Balance { available, frozen } bnb: Balance { available, frozen } og: Balance { available, frozen } rwad: Balance { available, frozen } } // 算力 hashpower: Hashpower // 奖励状态机 rewards: { pending -> 待领取 (24小时内必须领取) settleable -> 可结算 (可兑换为其他币种) settled -> 已结算累计 expired -> 已过期累计 } // 状态 status: ACTIVE | FROZEN } ``` ### 2. 奖励状态机 ``` ┌──────────────────┐ │ addReward() │ └────────┬─────────┘ ▼ ┌──────────────────┐ ┌─────────│ PENDING │─────────┐ │ │ (待领取, 有过期) │ │ │ └──────────────────┘ │ │ │ │ expire() │ claim() │ │ │ │ ▼ ▼ │ ┌──────────────────┐ ┌──────────────────┐ │ │ EXPIRED │ │ SETTLEABLE │ │ │ (已过期累计) │ │ (可结算) │ │ └──────────────────┘ └────────┬─────────┘ │ │ │ settle() │ │ │ ▼ │ ┌──────────────────┐ │ │ SETTLED │ │ │ (已结算累计) │ │ └──────────────────┘ │ ``` ### 3. LedgerEntry (账本流水) 采用 **Append-Only** 模式,不可修改,确保审计追溯: ```typescript LedgerEntry { entryType: LedgerEntryType // 流水类型 amount: Money // 金额 (正入账/负支出) assetType: AssetType // 资产类型 balanceAfter: Money? // 操作后余额快照 refOrderId?: string // 关联订单号 refTxHash?: string // 关联交易哈希 memo?: string // 备注 } ``` ### 4. 流水类型枚举 ```typescript enum LedgerEntryType { // 充值相关 DEPOSIT_KAVA = 'DEPOSIT_KAVA' // KAVA链充值 DEPOSIT_BSC = 'DEPOSIT_BSC' // BSC链充值 // 认种相关 PLANT_PAYMENT = 'PLANT_PAYMENT' // 认种支付 // 奖励相关 REWARD_PENDING = 'REWARD_PENDING' // 奖励待领取 REWARD_TO_SETTLEABLE = 'REWARD_TO_SETTLEABLE' // 奖励转可结算 REWARD_SETTLED = 'REWARD_SETTLED' // 奖励已结算 REWARD_EXPIRED = 'REWARD_EXPIRED' // 奖励已过期 // 其他 WITHDRAWAL = 'WITHDRAWAL' // 提现 ADMIN_ADJUST = 'ADMIN_ADJUST' // 管理员调整 } ``` ## 数据库设计 ### ER 图 ``` ┌─────────────────────┐ ┌─────────────────────┐ │ wallet_accounts │ │ wallet_ledger_ │ │ │ │ entries │ ├─────────────────────┤ ├─────────────────────┤ │ wallet_id (PK) │───┐ │ entry_id (PK) │ │ user_id (UK) │ │ │ user_id (FK) │ │ usdt_available │ └──▶│ entry_type │ │ usdt_frozen │ │ amount │ │ dst_available │ │ asset_type │ │ dst_frozen │ │ balance_after │ │ bnb_available │ │ ref_order_id │ │ bnb_frozen │ │ ref_tx_hash │ │ og_available │ │ memo │ │ og_frozen │ │ payload_json │ │ rwad_available │ │ created_at │ │ rwad_frozen │ └─────────────────────┘ │ hashpower │ │ pending_usdt │ ┌─────────────────────┐ │ pending_hashpower │ │ deposit_orders │ │ pending_expire_at │ ├─────────────────────┤ │ settleable_usdt │ │ order_id (PK) │ │ settleable_hashpower│ │ user_id (FK) │ │ settled_total_usdt │ │ chain_type │ │ settled_total_hp │ │ amount │ │ expired_total_usdt │ │ tx_hash (UK) │ │ expired_total_hp │ │ status │ │ status │ │ confirmed_at │ │ created_at │ │ created_at │ │ updated_at │ └─────────────────────┘ └─────────────────────┘ ┌─────────────────────┐ │ settlement_orders │ ├─────────────────────┤ │ order_id (PK) │ │ user_id (FK) │ │ usdt_amount │ │ settle_currency │ │ swap_tx_hash │ │ received_amount │ │ status │ │ settled_at │ │ created_at │ └─────────────────────┘ ``` ### 精度处理 所有金额字段使用 `Decimal(20, 8)` 存储: - 20位总精度,8位小数 - 支持最大 999,999,999,999.99999999 - 使用 `decimal.js` 库进行计算,避免浮点数精度问题 ## 安全设计 ### 认证与授权 ``` ┌────────────────┐ │ JWT Token │ │ (Bearer) │ └───────┬────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ JwtAuthGuard │ │ - 验证 Token 签名 │ │ - 检查 Token 过期 │ │ - 提取 userId 和 seq │ └───────────────────────────┬─────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ @Public() 装饰器 │ │ - 标记为公开接口,跳过认证 │ │ - 用于内部服务调用 (如 /deposit) │ └─────────────────────────────────────────────────────┘ ``` ### 内部服务调用 充值入账接口 (`POST /wallet/deposit`) 使用 `@Public()` 装饰器,跳过 JWT 认证,仅供内部链监控服务调用。生产环境应通过网络隔离保护。 ## 扩展点 ### 1. 领域事件 所有聚合操作都会产生领域事件,可用于: - 异步通知 - 事件溯源 - 跨服务通信 ```typescript wallet.deposit(amount, chainType, txHash); // 产生 DepositCompletedEvent wallet.deduct(amount, reason); // 产生 BalanceDeductedEvent ``` ### 2. 仓储接口 基础设施层实现可替换: - 当前:Prisma + PostgreSQL - 可扩展:Redis 缓存、MongoDB 等 ### 3. 消息队列集成 预留事件发布接口,可集成: - RabbitMQ - Kafka - Redis Pub/Sub