rwadurian/backend/services/wallet-service/docs/ARCHITECTURE.md

21 KiB
Raw Blame History

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 (钱包账户聚合)

钱包账户是核心聚合根,管理用户的所有资产状态:

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 模式,不可修改,确保审计追溯:

LedgerEntry {
  entryType: LedgerEntryType  // 流水类型
  amount: Money               // 金额 (正入账/负支出)
  assetType: AssetType        // 资产类型
  balanceAfter: Money?        // 操作后余额快照
  refOrderId?: string         // 关联订单号
  refTxHash?: string          // 关联交易哈希
  memo?: string               // 备注
}

4. 流水类型枚举

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. 领域事件

所有聚合操作都会产生领域事件,可用于:

  • 异步通知
  • 事件溯源
  • 跨服务通信
wallet.deposit(amount, chainType, txHash);
// 产生 DepositCompletedEvent

wallet.deduct(amount, reason);
// 产生 BalanceDeductedEvent

2. 仓储接口

基础设施层实现可替换:

  • 当前Prisma + PostgreSQL
  • 可扩展Redis 缓存、MongoDB 等

3. 消息队列集成

预留事件发布接口,可集成:

  • RabbitMQ
  • Kafka
  • Redis Pub/Sub