docs: 平台全景架构大纲 + 预种计划实施方案
新增两份项目核心文档: 1. platform-overview.md — 平台全景架构大纲(551 行) - RWADurian 1.0 认种分配系统 + 2.0 算力挖矿系统完整梳理 - 13 个微服务架构、核心业务流程、CDC 数据桥梁 - 推荐层级体系、代币与链上体系、安全运维要点 - 可作为开发、运维、新成员 onboarding 的单一事实来源 2. pre-planting-implementation-plan.md — 3171 预种计划实施方案(745 行) - 核心原则:纯新增,零侵入(现有代码文件一行不改) - 架构决策:planting-service 内独立模块,非新服务 - 完整的事件流、数据模型、API 设计 - 六大服务的实现步骤与变更文件清单 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b3a3652f21
commit
c3e43b81e9
|
|
@ -0,0 +1,551 @@
|
||||||
|
# RWADurian 榴莲认种平台 — 全景架构大纲
|
||||||
|
|
||||||
|
> 本文档是对 RWADurian 1.0(认种分配系统)与 2.0(算力挖矿系统)的完整业务与技术梳理。
|
||||||
|
> 可作为开发、运维、新成员 onboarding 的单一事实来源。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
1. [平台定位与核心概念](#1-平台定位与核心概念)
|
||||||
|
2. [系统全局拓扑](#2-系统全局拓扑)
|
||||||
|
3. [1.0 认种分配系统](#3-10-认种分配系统)
|
||||||
|
- 3.1 基础设施层
|
||||||
|
- 3.2 后端服务清单(13 个微服务)
|
||||||
|
- 3.3 前端应用
|
||||||
|
- 3.4 核心业务流程
|
||||||
|
4. [2.0 算力挖矿系统](#4-20-算力挖矿系统)
|
||||||
|
- 4.1 部署模式
|
||||||
|
- 4.2 后端服务清单(7 个微服务 + 1 前端)
|
||||||
|
- 4.3 核心业务流程
|
||||||
|
5. [跨系统数据桥梁 — CDC](#5-跨系统数据桥梁--cdc)
|
||||||
|
6. [推荐层级体系](#6-推荐层级体系)
|
||||||
|
7. [认种与分配流程(1.0 核心)](#7-认种与分配流程10-核心)
|
||||||
|
8. [算力与挖矿流程(2.0 核心)](#8-算力与挖矿流程20-核心)
|
||||||
|
9. [代币与链上体系](#9-代币与链上体系)
|
||||||
|
10. [安全加固与运维要点](#10-安全加固与运维要点)
|
||||||
|
11. [关键文件索引](#11-关键文件索引)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 平台定位与核心概念
|
||||||
|
|
||||||
|
| 概念 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| **RWADurian** | 一个以真实榴莲果树为底层资产的 RWA(Real World Asset)认种参与平台 |
|
||||||
|
| **认种(Planting)** | 用户花费 USDT 认种一棵果树,每棵树价格 15,831 USDT |
|
||||||
|
| **推荐关系(Referral)** | 用户通过推荐码邀请新用户,形成无限层级的树形结构 |
|
||||||
|
| **分配(Reward)** | 每笔认种产生的资金按 10 种权益类型分配给系统账户和上级链路用户 |
|
||||||
|
| **授权层级(Authorization)** | 根据团队业绩(认种量、省市占比)授予社区/省公司/市公司等经营资格 |
|
||||||
|
| **算力(Contribution)** | 1.0 认种行为通过 CDC 同步到 2.0,转化为用户的算力值 |
|
||||||
|
| **挖矿(Mining)** | 2.0 系统按算力占比进行每秒级 Share Token 分配,模拟"挖矿"收益 |
|
||||||
|
| **eUSDT / fUSDT** | 链上 ERC-20 代币,分别代表"积分股"和"积分值",可在 2.0 交易市场流通 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 系统全局拓扑
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 用户端 │
|
||||||
|
│ mobile-app (Flutter) mining-app (Flutter) │
|
||||||
|
│ admin-web (Next.js 14) mining-admin-web (Next.js 14) │
|
||||||
|
└──────────────┬─────────────────────────────┬────────────────────────────┘
|
||||||
|
│ HTTPS / Kong Gateway │ HTTPS
|
||||||
|
▼ ▼
|
||||||
|
┌──────────────────────────────┐ ┌──────────────────────────────────────┐
|
||||||
|
│ 1.0 认种分配系统 │ │ 2.0 算力挖矿系统 │
|
||||||
|
│ docker-compose.yml │ │ docker-compose.2.0.yml │
|
||||||
|
│ │ │ │
|
||||||
|
│ 13 NestJS 微服务 │ │ 7 NestJS 微服务 + 1 前端 │
|
||||||
|
│ ┌─────────────────────────┐ │ │ ┌──────────────────────────────┐ │
|
||||||
|
│ │ identity │ referral │ │ │ │ auth │ contribution │ │
|
||||||
|
│ │ wallet │ reward │ │ │ │ mining │ trading │ │
|
||||||
|
│ │ planting │ authorize │ │ │ │ mining-admin│ mining-wallet │ │
|
||||||
|
│ │ blockchain │ admin │ │ │ │ mining-blockchain │ │
|
||||||
|
│ │ mpc │ backup │ │ │ └──────────────────────────────┘ │
|
||||||
|
│ │ leaderboard│ presence │ │ │ │
|
||||||
|
│ │ reporting │ │ │ │ mining-admin-web (Next.js) │
|
||||||
|
│ └─────────────────────────┘ │ └──────────────────────────────────────┘
|
||||||
|
│ │ ▲
|
||||||
|
│ ┌─────────────────────────┐ │ │ CDC (Debezium → Kafka)
|
||||||
|
│ │ PostgreSQL 16 (13 DB) │─┼────────┘
|
||||||
|
│ │ Redis 7 (DB 0-11) │ │
|
||||||
|
│ │ Kafka 7.5 (单 Broker) │ │ ┌──────────────────────────────────────┐
|
||||||
|
│ │ Debezium 2.5.4 │ │ │ 独立模式额外基础设施 │
|
||||||
|
│ │ Zookeeper 7.5 │ │ │ postgres-2 / redis-2 / debezium-2 │
|
||||||
|
│ └─────────────────────────┘ │ └──────────────────────────────────────┘
|
||||||
|
│ │
|
||||||
|
│ MPC System (Go, 9 服务) │ KAVA 主网 / BSC
|
||||||
|
└──────────────────────────────┘ 智能合约 (DurianUSDT, eUSDT, fUSDT)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 1.0 认种分配系统
|
||||||
|
|
||||||
|
### 3.1 基础设施层
|
||||||
|
|
||||||
|
| 组件 | 版本 | 端口 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| PostgreSQL | 16-alpine | 127.0.0.1:5432 | 13 个独立数据库,WAL logical 模式 |
|
||||||
|
| Redis | 7-alpine | 6379 | AOF 持久化,20 个 DB(DB 0-11 分配给各服务) |
|
||||||
|
| Kafka | 7.5.0 | 9092/9093/29092 | 单 Broker,auto-create topics |
|
||||||
|
| Zookeeper | 7.5.0 | 2181 | Kafka 协调 |
|
||||||
|
| Debezium | 2.5.4.Final | 127.0.0.1:8084 | CDC 连接器,ExtractNewRecordState SMT |
|
||||||
|
|
||||||
|
**关键配置:**
|
||||||
|
- `max_slot_wal_keep_size=10GB` — 防止 WAL 无限积压(历史事故:305GB)
|
||||||
|
- `max_replication_slots=20` / `max_wal_senders=20`
|
||||||
|
- Kafka 9093 端口为远程 MPC 访问预留(192.168.1.111)
|
||||||
|
|
||||||
|
### 3.2 后端服务清单
|
||||||
|
|
||||||
|
| 服务 | 端口 | Redis DB | 核心职责 |
|
||||||
|
|------|------|----------|----------|
|
||||||
|
| **identity-service** | 3000 | 0 | 用户注册/登录、KYC、SMS、头像、钱包地址创建 |
|
||||||
|
| **wallet-service** | 3001 | 1 | 钱包余额、冻结/解冻、充值/提现、区域账户 |
|
||||||
|
| **backup-service** | 3002 | — | 钱包私钥加密备份与恢复(限速 3次/天) |
|
||||||
|
| **planting-service** | 3003 | 2 | 认种订单创建 → 选省市 → 确认 → 支付 → 合同签署 |
|
||||||
|
| **referral-service** | 3004 | 3 | 推荐关系树、团队统计、龙虎榜分值计算 |
|
||||||
|
| **reward-service** | 3005 | 4 | 10 类权益分配、奖励待领/已领/过期状态机 |
|
||||||
|
| **mpc-service** | 3006 | 5 | MPC 密钥管理,桥接 Go 版 MPC System |
|
||||||
|
| **leaderboard-service** | 3007 | 6 | 用户排行榜 |
|
||||||
|
| **reporting-service** | 3008 | 7 | 系统账户报表聚合 |
|
||||||
|
| **authorization-service** | 3009 | 8 | 社区/省公司/市公司授权,月度考核评估 |
|
||||||
|
| **admin-service** | 3010 | 9 | 后台管理(版本、用户、CDC) |
|
||||||
|
| **presence-service** | 3011 | 10 | 用户在线状态(180s 窗口,60s 快照) |
|
||||||
|
| **blockchain-service** | 3012 | 11 | KAVA 链交互、充提监控、热钱包管理 |
|
||||||
|
|
||||||
|
**MPC System(Go 语言,独立网络):**
|
||||||
|
- account-service / session-coordinator / message-router / server-party / server-party-api 等 9 个服务
|
||||||
|
- gRPC + WebSocket 通信
|
||||||
|
- TSS(门限签名)实现多方安全计算
|
||||||
|
|
||||||
|
### 3.3 前端应用
|
||||||
|
|
||||||
|
| 应用 | 技术栈 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| **mobile-app** | Flutter (Dart) | 用户端 APP,17 个功能模块(认种/充值/提现/KYC/排行/交易等) |
|
||||||
|
| **admin-web** | Next.js 14 + React | 管理后台(仪表盘、用户管理、订单管理) |
|
||||||
|
| **mobile-upgrade** | Next.js 14 | APP 版本管理 & OTA 更新服务器 |
|
||||||
|
|
||||||
|
### 3.4 核心业务流程概览
|
||||||
|
|
||||||
|
```
|
||||||
|
用户注册 → 获取推荐码 → 被推荐人注册(建立推荐关系)
|
||||||
|
↓
|
||||||
|
用户充值 USDT(链上)
|
||||||
|
↓
|
||||||
|
创建认种订单(选省市 → 支付 → 签合同)
|
||||||
|
↓
|
||||||
|
触发 10 类权益分配(见第 7 章)
|
||||||
|
↓
|
||||||
|
CDC 同步到 2.0(算力 → 挖矿)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 2.0 算力挖矿系统
|
||||||
|
|
||||||
|
### 4.1 部署模式
|
||||||
|
|
||||||
|
| 模式 | 网络 | 基础设施 | 适用场景 |
|
||||||
|
|------|------|----------|----------|
|
||||||
|
| **Shared(默认)** | services_rwa-network | 复用 1.0 的 PG/Redis/Kafka | 同机部署 |
|
||||||
|
| **Standalone** | rwa-2-network | 独立 postgres-2/redis-2 + 远程 Kafka 9093 | 分机部署 |
|
||||||
|
|
||||||
|
### 4.2 后端服务清单
|
||||||
|
|
||||||
|
| 服务 | 端口 | Redis DB | 核心职责 |
|
||||||
|
|------|------|----------|----------|
|
||||||
|
| **contribution-service** | 3020 | 10 | CDC 消费 → 算力计算 → 15 级 + 3 阶梯分配 |
|
||||||
|
| **mining-service** | 3021 | 16 | 按秒分配 Share Token、挖矿账户管理 |
|
||||||
|
| **trading-service** | 3022 | 12 | eUSDT/fUSDT 交易撮合、做市商 |
|
||||||
|
| **mining-admin-service** | 3023 | 13 | 挖矿后台管理、池账户(销毁池/挖矿池) |
|
||||||
|
| **auth-service** | 3024 | 14 | 2.0 认证,CDC 同步 1.0 用户 |
|
||||||
|
| **mining-wallet-service** | 3025 | 15 | KAVA 链钱包管理 |
|
||||||
|
| **mining-blockchain-service** | 3026 | 8 | 链上操作(eUSDT/fUSDT/USDT)、区块扫描 |
|
||||||
|
| **mining-admin-web** | 3100 | — | 挖矿管理后台(Next.js) |
|
||||||
|
|
||||||
|
### 4.3 核心业务流程概览
|
||||||
|
|
||||||
|
```
|
||||||
|
1.0 认种订单 (MINING_ENABLED)
|
||||||
|
↓ Debezium CDC
|
||||||
|
contribution-service 消费 → 算力计算(个人70% + 团队15级7.5% + 奖励3阶7.5%)
|
||||||
|
↓ Outbox Event
|
||||||
|
mining-service 同步算力 → 每秒按占比分配 Share Token
|
||||||
|
↓
|
||||||
|
trading-service 提供 eUSDT/fUSDT 交易市场
|
||||||
|
↓
|
||||||
|
mining-blockchain-service 处理链上充提
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 跨系统数据桥梁 — CDC
|
||||||
|
|
||||||
|
### 5.1 CDC 数据流
|
||||||
|
|
||||||
|
| 源(1.0 表) | Kafka Topic | 消费者(2.0) | 用途 |
|
||||||
|
|---------------|-------------|---------------|------|
|
||||||
|
| identity.user_accounts | `cdc.identity.public.user_accounts` | auth-service, admin-service, contribution-service | 同步用户注册 |
|
||||||
|
| identity.wallet_addresses | `cdc.identity.public.wallet_addresses` | auth-service | 同步钱包地址 |
|
||||||
|
| planting.planting_orders | `cdc.planting.public.planting_orders` | contribution-service | 同步认种订单 → 算力 |
|
||||||
|
| referral.referral_relationships | `cdc.referral.public.referral_relationships` | contribution-service | 同步推荐关系 → 团队算力 |
|
||||||
|
|
||||||
|
### 5.2 CDC 消息格式(ExtractNewRecordState 展平后)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"order_id": 1,
|
||||||
|
"tree_count": 1,
|
||||||
|
"account_sequence": "D25122700015",
|
||||||
|
"status": "MINING_ENABLED",
|
||||||
|
"__op": "c",
|
||||||
|
"__table": "planting_orders",
|
||||||
|
"__source_ts_ms": 1767892060857,
|
||||||
|
"__deleted": "false"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 消费顺序保证(contribution-service)
|
||||||
|
|
||||||
|
contribution-service 采用 **Collect-Sort-Process** 模式:
|
||||||
|
1. **Phase 1**: 消费 `cdc.identity.public.user_accounts`(全量用户)
|
||||||
|
2. **Phase 2**: 消费 `cdc.referral.public.referral_relationships`(全量推荐关系)
|
||||||
|
3. **Phase 3**: 消费 `cdc.planting.public.planting_orders`(收集 → 按 order_id 排序 → 顺序处理)
|
||||||
|
|
||||||
|
**严格顺序的原因**:计算团队算力必须先有推荐关系数据,否则分配错误。
|
||||||
|
|
||||||
|
### 5.4 幂等性保证
|
||||||
|
|
||||||
|
```
|
||||||
|
每条 CDC 消息 → INSERT ProcessedCdcEvent(topic, offset)
|
||||||
|
→ 若 UNIQUE 冲突则跳过
|
||||||
|
→ 业务逻辑在同一事务内执行
|
||||||
|
→ Serializable 隔离级别
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 推荐层级体系
|
||||||
|
|
||||||
|
### 6.1 数据模型
|
||||||
|
|
||||||
|
```
|
||||||
|
ReferralRelationship(不可变)
|
||||||
|
├── userId / accountSequence(唯一标识)
|
||||||
|
├── referrerId(直接推荐人,null = 根节点)
|
||||||
|
├── ancestorPath: BigInt[](从直接推荐人到根的链路)
|
||||||
|
├── depth(链路深度,0 = 根节点)
|
||||||
|
├── myReferralCode / usedReferralCode
|
||||||
|
└── directReferralCount / activeDirectCount
|
||||||
|
|
||||||
|
TeamStatistics(实时更新)
|
||||||
|
├── selfPlantingCount / selfPlantingAmount
|
||||||
|
├── totalTeamPlantingCount / totalTeamPlantingAmount
|
||||||
|
├── maxSingleTeamPlantingCount(最大单腿)
|
||||||
|
├── effectivePlantingCountForRanking(龙虎榜分值)
|
||||||
|
└── provinceCityDistribution: JSON
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 推荐树结构示例
|
||||||
|
|
||||||
|
```
|
||||||
|
Root (depth=0, ancestorPath=[])
|
||||||
|
├── A (depth=1, ancestorPath=[Root])
|
||||||
|
│ ├── B (depth=2, ancestorPath=[A, Root])
|
||||||
|
│ │ └── D (depth=3, ancestorPath=[B, A, Root])
|
||||||
|
│ └── C (depth=2, ancestorPath=[A, Root])
|
||||||
|
└── E (depth=1, ancestorPath=[Root])
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 龙虎榜分值公式
|
||||||
|
|
||||||
|
```
|
||||||
|
effectivePlantingCountForRanking = totalTeamPlantingCount - maxSingleTeamPlantingCount
|
||||||
|
```
|
||||||
|
|
||||||
|
**设计目的**:鼓励均衡发展,防止"单腿烧伤"。
|
||||||
|
|
||||||
|
### 6.4 授权层级与考核
|
||||||
|
|
||||||
|
| 层级 | 要求 | 权益 |
|
||||||
|
|------|------|------|
|
||||||
|
| **社区(Community)** | 直推 ≥5,认种 ≥500 棵 | 社区权益分配 576 USDT/棵 |
|
||||||
|
| **市公司(City)** | 团队 ≥10,000 棵,本市占比 ≥50% | 市团队 288 + 市区域 252 USDT/棵 |
|
||||||
|
| **省公司(Province)** | 团队 ≥20,000 棵,本省占比 ≥60% | 省团队 144 + 省区域 108 USDT/棵 |
|
||||||
|
|
||||||
|
**月度考核**:authorization-service 每月评估,根据阶梯目标判断是否保留/降级授权。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 认种与分配流程(1.0 核心)
|
||||||
|
|
||||||
|
### 7.1 认种订单生命周期
|
||||||
|
|
||||||
|
```
|
||||||
|
CREATED → 选省市 → 确认省市 → PAID(冻结资金)→ 合同签署 → 确认扣款 → 分配触发
|
||||||
|
│ │
|
||||||
|
│ contract.signed ✓
|
||||||
|
│ contract.expired ✗ → 权益归系统
|
||||||
|
│
|
||||||
|
Outbox 发布事件:
|
||||||
|
planting.planting.created → referral-service
|
||||||
|
planting-events → authorization-service
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 三阶段支付安全机制
|
||||||
|
|
||||||
|
| 阶段 | 操作 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| **冻结** | wallet.freezeForPlanting() | 资金不可用但未扣除 |
|
||||||
|
| **合同** | 等待 contract.signed / expired | 24 小时签署窗口 |
|
||||||
|
| **确认** | wallet.confirmPlantingDeduction() | 冻结 → 实际扣款,触发分配 |
|
||||||
|
|
||||||
|
### 7.3 十类权益分配(每棵树 15,831 USDT)
|
||||||
|
|
||||||
|
#### 系统费用(自动分配,10,863 USDT)
|
||||||
|
|
||||||
|
| # | 类型 | 金额 | 目标账户 |
|
||||||
|
|---|------|------|----------|
|
||||||
|
| 1 | 成本费 | 2,800 | S0000000002 |
|
||||||
|
| 2 | 运营费 | 2,100 | S0000000003 |
|
||||||
|
| 3 | 总部基金 | 203 | S0000000001 |
|
||||||
|
| 4 | RWAD 底池 | 5,760 | S0000000004 |
|
||||||
|
|
||||||
|
#### 用户权益(基于推荐链,4,968 USDT + 算力)
|
||||||
|
|
||||||
|
| # | 类型 | 金额 | 分配对象 | 附加 |
|
||||||
|
|---|------|------|----------|------|
|
||||||
|
| 5 | 分享权益 | 3,600 | 直接推荐人 | 无推荐人 → S0000000005 |
|
||||||
|
| 6 | 省团队权益 | 144 | 链路中最近的省公司授权者 | — |
|
||||||
|
| 7 | 省区域权益 | 108 | 被授权省份 | +1% 算力 |
|
||||||
|
| 8 | 市团队权益 | 288 | 链路中最近的市公司授权者 | — |
|
||||||
|
| 9 | 市区域权益 | 252 | 被授权城市 | +2% 算力 |
|
||||||
|
| 10 | 社区权益 | 576 | 链路中最近的社区管理者 | — |
|
||||||
|
|
||||||
|
### 7.4 奖励状态机
|
||||||
|
|
||||||
|
```
|
||||||
|
PENDING(24h 倒计时)
|
||||||
|
├─ 用户再次认种 → SETTLEABLE(可结算)
|
||||||
|
│ └─ 用户主动结算 → SETTLED(已结算,入钱包余额)
|
||||||
|
└─ 24h 超时未领取 → EXPIRED(过期,归总部社区)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.5 Kafka 事件流
|
||||||
|
|
||||||
|
```
|
||||||
|
planting-service ──planting.planting.created──→ referral-service
|
||||||
|
│
|
||||||
|
更新团队统计 + 等待合同
|
||||||
|
│
|
||||||
|
contract.signed / expired
|
||||||
|
│
|
||||||
|
confirmDeduction → wallet
|
||||||
|
│
|
||||||
|
┌─ planting.order.paid ──→ reward-service → distributeRewards()
|
||||||
|
└─ planting.order.expired → reward-service → 权益归系统账户
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 算力与挖矿流程(2.0 核心)
|
||||||
|
|
||||||
|
### 8.1 算力(Contribution)计算
|
||||||
|
|
||||||
|
**触发**:1.0 认种订单状态变为 `MINING_ENABLED` 时,通过 CDC 同步到 contribution-service。
|
||||||
|
|
||||||
|
#### 算力分配比例
|
||||||
|
|
||||||
|
| 来源 | 比例 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| **个人算力(PERSONAL)** | 70% | 认种即生效 |
|
||||||
|
| **团队层级(TEAM_LEVEL)** | 7.5% | 15 级,每级 0.5% |
|
||||||
|
| **团队奖励(TEAM_BONUS)** | 7.5% | 3 阶梯,每阶 2.5% |
|
||||||
|
| **运营费** | 12% | 系统账户 |
|
||||||
|
| **省公司** | 1% | 省区域系统账户 |
|
||||||
|
| **市公司** | 2% | 市区域系统账户 |
|
||||||
|
|
||||||
|
#### 团队算力解锁条件
|
||||||
|
|
||||||
|
| 层级 | 条件 |
|
||||||
|
|------|------|
|
||||||
|
| Level 1-5(2.5%) | 用户自己有认种即可 |
|
||||||
|
| Level 6-10(2.5%) | 直推 ≥3 人且有认种 |
|
||||||
|
| Level 11-15(2.5%) | 直推 ≥5 人且有认种 |
|
||||||
|
| Bonus Tier 1(2.5%) | 用户自己有认种 |
|
||||||
|
| Bonus Tier 2(2.5%) | 直推 ≥2 人且有认种 |
|
||||||
|
| Bonus Tier 3(2.5%) | 直推 ≥4 人且有认种 |
|
||||||
|
|
||||||
|
#### 每棵树算力值
|
||||||
|
|
||||||
|
```
|
||||||
|
contribution_per_tree = 22617 × (1 + currentUnit × 0.003)
|
||||||
|
|
||||||
|
currentUnit 每 100 棵全网认种递增一次:
|
||||||
|
Trees 1-999: unit=0, multiplier=1.000
|
||||||
|
Trees 1000-1099: unit=1, multiplier=1.003
|
||||||
|
Trees 1100-1199: unit=2, multiplier=1.006
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 挖矿(Mining)分配
|
||||||
|
|
||||||
|
**全局参数:**
|
||||||
|
|
||||||
|
| 参数 | 值 |
|
||||||
|
|------|------|
|
||||||
|
| 总份额 | 100.02 亿 Share |
|
||||||
|
| 初始分配池 | 2 亿 Share |
|
||||||
|
| 减半周期 | 2 年(63,072,000 秒) |
|
||||||
|
|
||||||
|
**分配公式:**
|
||||||
|
|
||||||
|
```
|
||||||
|
每秒全网分配量 = secondDistribution(随时代递减)
|
||||||
|
|
||||||
|
用户每秒挖矿 = secondDistribution × (用户有效算力 / 全网总算力)
|
||||||
|
|
||||||
|
有效算力 = 个人算力 + 已解锁的团队算力
|
||||||
|
```
|
||||||
|
|
||||||
|
**挖矿价格:**
|
||||||
|
|
||||||
|
```
|
||||||
|
price = sharePool / (TOTAL_SHARES - blackHole - circulationPool)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.3 交易市场
|
||||||
|
|
||||||
|
- **eUSDT(积分股)**:代表挖矿产出的 Share Token 对应价值
|
||||||
|
- **fUSDT(积分值)**:代表未来价值
|
||||||
|
- trading-service 提供 eUSDT/fUSDT 交易撮合
|
||||||
|
- 做市商账户由 mining-admin-service 管理
|
||||||
|
- **销毁池(Burn Pool)**:100 亿 Token
|
||||||
|
- **挖矿池(Mining Pool)**:200 万 Token
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 代币与链上体系
|
||||||
|
|
||||||
|
### 9.1 链上合约
|
||||||
|
|
||||||
|
| 合约 | 链 | 地址 |
|
||||||
|
|------|------|------|
|
||||||
|
| dUSDT (DurianUSDT) | KAVA | 0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3 |
|
||||||
|
| eUSDT (Energy USDT) | KAVA | 0x7C3275D808eFbAE90C06C7E3A9AfDdcAa8563931 |
|
||||||
|
| fUSDT (Future USDT) | KAVA | 0x14dc4f7d3E4197438d058C3D156dd9826A161134 |
|
||||||
|
| USDT (BSC 备用) | BSC | 0x55d398326f99059fF775485246999027B3197955 |
|
||||||
|
|
||||||
|
### 9.2 MPC 多方计算钱包
|
||||||
|
|
||||||
|
- Go 语言实现,9 个服务组件
|
||||||
|
- TSS(门限签名)保障私钥安全
|
||||||
|
- 用户无需直接管理私钥,通过 MPC 协议完成签名
|
||||||
|
- 热钱包提现由 blockchain-service 调度
|
||||||
|
|
||||||
|
### 9.3 区块扫描
|
||||||
|
|
||||||
|
- 扫描间隔:5 秒
|
||||||
|
- 确认块数:12 块
|
||||||
|
- RPC 故障自动切换(4 个 KAVA RPC 端点,3 分钟切换)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 安全加固与运维要点
|
||||||
|
|
||||||
|
### 10.1 端口安全
|
||||||
|
|
||||||
|
| 服务 | 绑定 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| PostgreSQL | 127.0.0.1:5432 | 仅本地访问 |
|
||||||
|
| Debezium REST | 127.0.0.1:8084 | 防 SSRF(历史事故:3 个恶意连接器注入) |
|
||||||
|
| Redis | 127.0.0.1:6379 | 仅本地访问 |
|
||||||
|
|
||||||
|
### 10.2 WAL 安全
|
||||||
|
|
||||||
|
- `max_slot_wal_keep_size=10GB` — 上限防 WAL 爆盘(历史事故:305GB)
|
||||||
|
- `OFFSET_FLUSH_INTERVAL_MS=10000` — Debezium 偏移刷新加速
|
||||||
|
|
||||||
|
### 10.3 密钥管理
|
||||||
|
|
||||||
|
- JWT_SECRET / SERVICE_JWT_SECRET — 服务间认证
|
||||||
|
- MPC_JWT_SECRET — MPC 系统认证
|
||||||
|
- WALLET_ENCRYPTION_SALT — 钱包加密
|
||||||
|
- SHARE_MASTER_KEY — MPC 主密钥
|
||||||
|
- Aliyun API Keys — SMS / KYC 三方服务
|
||||||
|
|
||||||
|
### 10.4 可靠性模式
|
||||||
|
|
||||||
|
| 模式 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| **Outbox Pattern** | 数据库事务 + 事件发布原子性,指数退避重试(最长 4 小时) |
|
||||||
|
| **Idempotency** | ProcessedEvent + ProcessedCdcEvent 表防重复消费 |
|
||||||
|
| **Compensation** | payment_compensations 表处理冻结失败/确认失败/分配失败 |
|
||||||
|
| **Health Check** | 所有服务 /api/v1/health 或 /api/v2/health,30s 间隔 |
|
||||||
|
| **Restart Policy** | unless-stopped 自动重启 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. 关键文件索引
|
||||||
|
|
||||||
|
### 11.1 编排文件
|
||||||
|
|
||||||
|
| 文件 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| `backend/services/docker-compose.yml` | 1.0 系统全量编排(13 服务 + 基础设施) |
|
||||||
|
| `docker-compose.2.0.yml` | 2.0 系统编排(7 服务 + 前端 + 可选基础设施) |
|
||||||
|
| `backend/mpc-system/docker-compose.yml` | MPC 系统编排 |
|
||||||
|
|
||||||
|
### 11.2 核心业务代码
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `backend/services/planting-service/src/application/` | 认种订单业务逻辑 |
|
||||||
|
| `backend/services/reward-service/src/application/` | 分配计算与奖励状态机 |
|
||||||
|
| `backend/services/referral-service/src/application/` | 推荐关系与团队统计 |
|
||||||
|
| `backend/services/authorization-service/src/application/` | 授权层级与月度考核 |
|
||||||
|
| `backend/services/contribution-service/src/application/` | 算力计算与 CDC 消费 |
|
||||||
|
| `backend/services/mining-service/src/domain/services/` | 挖矿分配算法 |
|
||||||
|
| `backend/services/wallet-service/src/application/` | 钱包操作(冻结/解冻/分配) |
|
||||||
|
| `backend/services/blockchain-service/src/` | 链上交互与区块扫描 |
|
||||||
|
|
||||||
|
### 11.3 数据库 Schema
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `backend/services/*/prisma/schema.prisma` | 各服务 Prisma Schema |
|
||||||
|
| `backend/services/scripts/init-databases.sh` | 13 个数据库初始化脚本 |
|
||||||
|
|
||||||
|
### 11.4 前端入口
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `frontend/mobile-app/lib/main.dart` | Flutter 用户端入口 |
|
||||||
|
| `frontend/mobile-app/lib/features/` | 17 个功能模块 |
|
||||||
|
| `frontend/admin-web/src/app/` | Next.js 管理后台 |
|
||||||
|
| `frontend/mining-admin-web/src/app/` | Next.js 挖矿后台 |
|
||||||
|
|
||||||
|
### 11.5 智能合约
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `contracts/DurianUSDT.sol` | ERC-20 代币合约 |
|
||||||
|
| `contracts/build/DurianUSDT.abi` | 编译后 ABI |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录:账户编号规则
|
||||||
|
|
||||||
|
| 格式 | 示例 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| D + YYMMDD + 5位序号 | D25121400002 | 用户账户 |
|
||||||
|
| S + 10位序号 | S0000000001 | 系统账户(总部/成本/运营/底池) |
|
||||||
|
| 9 + 省代码 | 9440000 | 省级系统账户 |
|
||||||
|
| 8 + 市代码 | 8440100 | 市级系统账户 |
|
||||||
|
| 7 + 省代码 | 7440000 | 省团队默认账户 |
|
||||||
|
| 6 + 市代码 | 6440100 | 市团队默认账户 |
|
||||||
|
|
@ -0,0 +1,745 @@
|
||||||
|
# 3171 预种计划(拼种/团购计划)— 实现方案
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
RWADurian 平台需要新增"3171 预种计划"功能。这本质是一个**拼种团购计划**:用户以 3171 USDT/份(1 棵树的 1/5 价格)参与认种,每购买一份立即享有分配、推荐奖励和算力收益;累计 5 份自动合成 1 棵树,触发合同签署和挖矿开启,同时解除交易和提现限制。此功能需无缝融入现有 1.0 认种分配和 2.0 算力挖矿体系,不破坏任何已有功能。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 架构决策
|
||||||
|
|
||||||
|
### 核心原则:纯新增,零侵入
|
||||||
|
|
||||||
|
**现有代码文件一行不改。** 所有预种逻辑通过以下方式实现:
|
||||||
|
- 新增独立文件(新 controller、新 service、新 handler、新 Guard)
|
||||||
|
- 新增数据库表(不修改现有表结构)
|
||||||
|
- 新增 Kafka Topic(不修改现有 Topic 的生产/消费逻辑)
|
||||||
|
- 唯一的"接触"是在各服务的 `app.module.ts` 中 import 新模块(纯注册,不改现有逻辑)
|
||||||
|
|
||||||
|
### 决策 1:在 planting-service 中新增独立模块(非新服务)
|
||||||
|
|
||||||
|
预种作为 planting-service 内的一个**完全独立的 NestJS Module**:
|
||||||
|
- 有自己的 Controller、Service、Repository、Events
|
||||||
|
- 有自己的 Prisma 表(不触碰现有 planting_orders 等表)
|
||||||
|
- 通过自己的 Kafka Topic 通信(不复用 `planting.planting.created` 等现有 Topic)
|
||||||
|
- 与现有 PlantingOrder 聚合根**零耦合**
|
||||||
|
|
||||||
|
**不创建新微服务的原因**:共享同一 PostgreSQL (rwa_planting) + 同一 Redis + 同一 Kafka,避免新增基础设施和运维成本。
|
||||||
|
|
||||||
|
### 决策 2:预种有自己完整的独立事件流
|
||||||
|
|
||||||
|
预种使用全新的 Kafka Topic(`pre-planting.*`),现有消费者不会收到这些事件,所以:
|
||||||
|
- referral-service 的现有 `planting-created.handler.ts` **完全不受影响**
|
||||||
|
- reward-service 的现有 `reward-calculation.service.ts` **完全不受影响**
|
||||||
|
- contract-signing 的现有流程 **完全不受影响**
|
||||||
|
|
||||||
|
### 决策 3:合并产生的"树"不进入现有 PlantingOrder 表
|
||||||
|
|
||||||
|
5 份合并后,**不创建 PlantingOrder**(避免触发现有分配流程)。而是:
|
||||||
|
- 在预种模块自己的 `pre_planting_merges` 表中记录合并
|
||||||
|
- 预种模块自己处理合同签署(复用签署逻辑但在新文件中)
|
||||||
|
- 预种模块通过自己的事件通知 contribution-service(2.0)
|
||||||
|
- 预种模块直接调用 wallet-service 内部 API 设置 `hasPlanted=true`
|
||||||
|
|
||||||
|
**好处**:现有 PlantingOrder 的整个生命周期管道(事件 → referral → contract → reward → contribution)完全不被触碰。
|
||||||
|
|
||||||
|
### 决策 4:从第 1 份起即产生分配与算力,附带限制条件
|
||||||
|
|
||||||
|
**从第 1 份预种开始,以下功能立即生效:**
|
||||||
|
- 10 类权益分配(1/5 比例)立即触发并入账
|
||||||
|
- 推荐人立即获得 720 推荐奖励
|
||||||
|
- 算力(贡献值)立即产生并参与 2.0 挖矿分配
|
||||||
|
- 团队统计立即更新(预种份额计入团队业绩)
|
||||||
|
|
||||||
|
**附带的限制条件(未累积满 5 份前):**
|
||||||
|
- 不可卖出 eUSDT(只能看,不能卖)
|
||||||
|
- 不可申请/授权社区、市公司、省公司
|
||||||
|
- 不可使用对公账户提现
|
||||||
|
- 若 1 年内未满 5 份 → 算力暂停分配(满 5 份后恢复,恢复起算 2 年后失效)
|
||||||
|
|
||||||
|
**合并后解锁全部限制 + 触发合同签署和挖矿开启。**
|
||||||
|
|
||||||
|
### 决策 5:推荐奖励取决于"被推荐人买了什么",与推荐人自身无关
|
||||||
|
|
||||||
|
推荐奖励规则(与现有逻辑完全一致,只是新增预种产品类型):
|
||||||
|
|
||||||
|
| 场景 | 推荐人 A | 被推荐人 B | A 获得奖励 |
|
||||||
|
|------|----------|------------|------------|
|
||||||
|
| B 认种 1 棵树 | 买了 1 份预种 | 认种 1 棵树 | **3600** 绿积分 |
|
||||||
|
| B 买 1 份预种 | 买了 1 份预种 | 买 1 份预种 | **720** 绿积分 |
|
||||||
|
| B 买 1 份预种 | 认种了 1 棵树 | 买 1 份预种 | **720** 绿积分 |
|
||||||
|
| B 认种 1 棵树 | 认种了 1 棵树 | 认种 1 棵树 | **3600** 绿积分(原有逻辑不变) |
|
||||||
|
|
||||||
|
规则本质:奖励金额 = 被推荐人购买产品对应的 SHARE_RIGHT(树=3600,预种份=720)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 涉及服务清单(纯新增方式)
|
||||||
|
|
||||||
|
| 服务 | 现有代码改动 | 新增内容 |
|
||||||
|
|------|-------------|----------|
|
||||||
|
| **planting-service** | `app.module.ts` 加 1 行 import | **新增 PrePlantingModule**(独立聚合根、Controller、Service、Repository、Events、合并逻辑、开关) |
|
||||||
|
| **referral-service** | `app.module.ts` 加 1 行 import | **新增 PrePlantingStatsModule**(新 handler 消费预种事件更新团队统计) |
|
||||||
|
| **reward-service** | 无 | **不涉及**。预种的 1/5 分配由 planting-service 的预种模块直接调用 wallet-service 完成 |
|
||||||
|
| **authorization-service** | `app.module.ts` 加 1 行 import | **新增 PrePlantingGuardModule**(路由级 Middleware,仅对授权申请路由生效) |
|
||||||
|
| **trading-service** | `app.module.ts` 加 1 行 import | **新增 PrePlantingGuardModule**(路由级 Middleware,仅对卖单路由生效) |
|
||||||
|
| **wallet-service** | `app.module.ts` 加 1 行 import | **新增 PrePlantingGuardModule**(路由级 Middleware,仅对提现路由生效) |
|
||||||
|
| **admin-service** | `app.module.ts` 加 1 行 import | **新增 PrePlantingAdminModule**(开关管理 + 预种订单查询视图) |
|
||||||
|
| **contribution-service (2.0)** | `app.module.ts` 加 1 行 import | **新增 PrePlantingCdcModule**(CDC 消费预种表、1/5 算力、冻结逻辑) |
|
||||||
|
| **mobile-app (Flutter)** | 无 | **新增预种功能模块**(购买页、持仓页、合并流程、签约弹窗) |
|
||||||
|
|
||||||
|
**关键**:除 `app.module.ts` 的 import 注册外,**每个服务的现有 .ts 文件零修改**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 数据模型变更(全部是新增表,不修改任何现有表)
|
||||||
|
|
||||||
|
### planting-service(新增 4 张表)
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
// ===== 以下全部是新增表,写在 schema.prisma 末尾 =====
|
||||||
|
|
||||||
|
// 预种订单
|
||||||
|
model PrePlantingOrder {
|
||||||
|
id BigInt @id @default(autoincrement())
|
||||||
|
orderNo String @unique // PPL{timestamp}{random}
|
||||||
|
userId BigInt
|
||||||
|
accountSequence String
|
||||||
|
portionCount Int @default(1)
|
||||||
|
pricePerPortion Decimal @default(3171)
|
||||||
|
totalAmount Decimal // portionCount × 3171
|
||||||
|
provinceCode String // 省代码(购买时选择)
|
||||||
|
cityCode String // 市代码(购买时选择)
|
||||||
|
status String @default("CREATED") // CREATED → PAID → MERGED
|
||||||
|
mergedToMergeId BigInt? // 合并后指向 PrePlantingMerge.id
|
||||||
|
mergedAt DateTime?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
paidAt DateTime?
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
@@map("pre_planting_orders")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预种持仓(每用户一条)
|
||||||
|
model PrePlantingPosition {
|
||||||
|
id BigInt @id @default(autoincrement())
|
||||||
|
userId BigInt @unique
|
||||||
|
accountSequence String @unique
|
||||||
|
totalPortions Int @default(0) // 累计购买份数(含已合并)
|
||||||
|
availablePortions Int @default(0) // 待合并份数(0-4)
|
||||||
|
mergedPortions Int @default(0) // 已合并份数
|
||||||
|
totalTreesMerged Int @default(0) // 已合成的树数
|
||||||
|
provinceCode String? // 首次购买时选择的省代码(后续复用)
|
||||||
|
cityCode String? // 首次购买时选择的市代码(后续复用)
|
||||||
|
firstPurchaseAt DateTime? // 首次购买时间(1年冻结起点)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
@@map("pre_planting_positions")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并记录(预种的"树",不进入现有 planting_orders 表)
|
||||||
|
model PrePlantingMerge {
|
||||||
|
id BigInt @id @default(autoincrement())
|
||||||
|
mergeNo String @unique // PMG{timestamp}{random}
|
||||||
|
userId BigInt
|
||||||
|
accountSequence String
|
||||||
|
sourceOrderNos Json // 5 笔预种订单号数组
|
||||||
|
treeCount Int @default(1) // 合并产生的树数(固定 1)
|
||||||
|
|
||||||
|
// 省市选择(合并后由用户选择)
|
||||||
|
selectedProvince String?
|
||||||
|
selectedCity String?
|
||||||
|
provinceCityConfirmedAt DateTime?
|
||||||
|
|
||||||
|
// 合同签署
|
||||||
|
contractStatus String @default("PENDING") // PENDING → SIGNED → EXPIRED
|
||||||
|
contractSignedAt DateTime?
|
||||||
|
|
||||||
|
// 挖矿
|
||||||
|
miningEnabledAt DateTime?
|
||||||
|
|
||||||
|
mergedAt DateTime @default(now())
|
||||||
|
@@map("pre_planting_merges")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预种分配记录(预种模块自己管理分配,不经过 reward-service)
|
||||||
|
model PrePlantingRewardEntry {
|
||||||
|
id BigInt @id @default(autoincrement())
|
||||||
|
sourceOrderNo String // 来源预种订单号
|
||||||
|
sourceAccountSequence String // 购买者 accountSequence
|
||||||
|
recipientAccountSequence String // 接收者 accountSequence(推荐人/社区/省市公司/系统账户)
|
||||||
|
rightType String // 权益类型(同 RightType 枚举)
|
||||||
|
usdtAmount Decimal
|
||||||
|
rewardStatus String @default("SETTLED") // SETTLED / PENDING / EXPIRED
|
||||||
|
memo String? // 分配原因说明
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
@@map("pre_planting_reward_entries")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意**:现有 `planting_orders`、`planting_positions` 等表**零修改**。
|
||||||
|
**注意**:现有 `PlantingOrder` 聚合根代码**零修改**。
|
||||||
|
|
||||||
|
### admin-service(新增配置表)
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
// 追加到 schema.prisma 末尾
|
||||||
|
model PrePlantingConfig {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
isActive Boolean @default(false)
|
||||||
|
activatedAt DateTime?
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
updatedBy String?
|
||||||
|
@@map("pre_planting_configs")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### contribution-service 2.0(新增同步表)
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
// 追加到 schema.prisma 末尾
|
||||||
|
model SyncedPrePlantingAdoption {
|
||||||
|
id BigInt @id @default(autoincrement())
|
||||||
|
originalOrderId BigInt @unique
|
||||||
|
accountSequence String
|
||||||
|
portionCount Int
|
||||||
|
purchaseDate DateTime @db.Date
|
||||||
|
contributionPerPortion Decimal
|
||||||
|
contributionFrozen Boolean @default(false)
|
||||||
|
freezeExpiresAt DateTime?
|
||||||
|
contributionDistributed Boolean @default(false)
|
||||||
|
syncedAt DateTime @default(now())
|
||||||
|
@@map("synced_pre_planting_adoptions")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 预种分配金额配置(在预种模块新文件中定义)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// planting-service/src/pre-planting/domain/value-objects/pre-planting-right-amounts.ts(新文件)
|
||||||
|
// 基准:reward-service 的 RIGHT_AMOUNTS(实际生效的分配金额)
|
||||||
|
// 预种每份 = 整棵树金额 / 5,差额 4.8 归入总部社区
|
||||||
|
export const PRE_PLANTING_RIGHT_AMOUNTS = {
|
||||||
|
COST_FEE: 576, // 2880/5
|
||||||
|
OPERATION_FEE: 420, // 2100/5
|
||||||
|
HEADQUARTERS_BASE_FEE: 29.4, // 123/5 + 4.8 差额(3171 - 3166.2 = 4.8)
|
||||||
|
RWAD_POOL_INJECTION: 1152, // 5760/5
|
||||||
|
SHARE_RIGHT: 720, // 3600/5 = 720(推荐奖励金额)
|
||||||
|
PROVINCE_AREA_RIGHT: 21.6, // 108/5
|
||||||
|
PROVINCE_TEAM_RIGHT: 28.8, // 144/5
|
||||||
|
CITY_AREA_RIGHT: 50.4, // 252/5
|
||||||
|
CITY_TEAM_RIGHT: 57.6, // 288/5
|
||||||
|
COMMUNITY_RIGHT: 115.2, // 576/5
|
||||||
|
} as const;
|
||||||
|
// 合计 = 576 + 420 + 29.4 + 1152 + 720 + 21.6 + 28.8 + 50.4 + 57.6 + 115.2 = 3171.0 ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 核心事件流
|
||||||
|
|
||||||
|
### 流程 A:预种购买(每份) — 全部在预种模块内完成
|
||||||
|
|
||||||
|
**重要**:购买时即选择省市(与现有认种流程一致),后续购买复用同一省市。
|
||||||
|
这样 10 类权益全部可在购买时立即分配。
|
||||||
|
|
||||||
|
```
|
||||||
|
用户购买 1 份预种(3171 USDT)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[planting-service / PrePlantingModule](全新代码,不触碰现有代码)
|
||||||
|
│
|
||||||
|
├─ Step 1:前置校验
|
||||||
|
│ ├─ 开关 ON(或续购规则通过)
|
||||||
|
│ ├─ 余额 ≥ 3171
|
||||||
|
│ └─ 省市信息(首次购买:用户选择;续购:自动复用 PrePlantingPosition 中的省市)
|
||||||
|
│
|
||||||
|
├─ Step 2:冻结余额
|
||||||
|
│ └─ wallet.freezeForPlanting(3171)(调用已有内部 API)
|
||||||
|
│
|
||||||
|
├─ Step 3:确定 10 类权益的分配对象(pre-planting-reward.service.ts)
|
||||||
|
│ │
|
||||||
|
│ ├─ 4 类系统费用(硬编码,无需查询):
|
||||||
|
│ │ ├─ COST_FEE: 576 → S0000000002(成本账户)
|
||||||
|
│ │ ├─ OPERATION_FEE: 420 → S0000000003(运营账户)
|
||||||
|
│ │ ├─ HQ_BASE_FEE: 29.4 → S0000000001(总部社区)
|
||||||
|
│ │ └─ RWAD_POOL: 1152 → S0000000004(RWAD底池)
|
||||||
|
│ │
|
||||||
|
│ ├─ 推荐奖励(调用 referral-service 已有 API):
|
||||||
|
│ │ └─ SHARE_RIGHT: 720 → GET /api/v1/referral/chain/{accountSeq}
|
||||||
|
│ │ ├─ 有推荐人且已认种 → 推荐人账户(立即到账)
|
||||||
|
│ │ ├─ 有推荐人未认种 → 推荐人账户(PENDING,24h 内认种可领取)
|
||||||
|
│ │ └─ 无推荐人 → S0000000005(分享权益池)
|
||||||
|
│ │
|
||||||
|
│ ├─ 社区权益(调用 authorization-service 已有 API):
|
||||||
|
│ │ └─ COMMUNITY: 115.2 → GET /authorization/community-reward-distribution
|
||||||
|
│ │ ├─ 有前有效社区 → 社区领导账户
|
||||||
|
│ │ └─ 无社区 → S0000000001(总部)
|
||||||
|
│ │
|
||||||
|
│ └─ 省市 4 类权益(调用 authorization-service 已有 API,需要 provinceCode/cityCode):
|
||||||
|
│ ├─ PROVINCE_AREA: 21.6 → GET /authorization/province-area-reward-distribution?provinceCode=XX
|
||||||
|
│ │ └─ 有正式省公司 → 省公司账户 | 无 → 9{provinceCode}(系统省账户)
|
||||||
|
│ ├─ PROVINCE_TEAM: 28.8 → GET /authorization/province-team-reward-distribution
|
||||||
|
│ │ └─ 有授权省团队 → 团队领导账户 | 无 → S0000000001(总部)
|
||||||
|
│ ├─ CITY_AREA: 50.4 → GET /authorization/city-area-reward-distribution?cityCode=XX
|
||||||
|
│ │ └─ 有正式市公司 → 市公司账户 | 无 → 8{cityCode}(系统市账户)
|
||||||
|
│ └─ CITY_TEAM: 57.6 → GET /authorization/city-team-reward-distribution
|
||||||
|
│ └─ 有授权市团队 → 团队领导账户 | 无 → S0000000001(总部)
|
||||||
|
│
|
||||||
|
├─ Step 4:事务内持久化
|
||||||
|
│ ├─ 创建 PrePlantingOrder(status=PAID, provinceCode, cityCode)
|
||||||
|
│ ├─ 更新 PrePlantingPosition(totalPortions++, availablePortions++)
|
||||||
|
│ ├─ 设置 firstPurchaseAt + provinceCode/cityCode(仅首次)
|
||||||
|
│ ├─ 创建 PrePlantingRewardEntry(10 条记录,含每条的接收人 accountSequence)
|
||||||
|
│ └─ Outbox: "pre-planting.portion.purchased"
|
||||||
|
│
|
||||||
|
├─ Step 5:执行资金转账
|
||||||
|
│ ├─ wallet.confirmDeduction(3171)(调用已有 API)
|
||||||
|
│ └─ wallet.allocateFunds(10 条分配)(调用已有 API,与 reward-service 调用格式完全一致)
|
||||||
|
│
|
||||||
|
└─ Step 6:检查是否触发合并
|
||||||
|
└─ availablePortions == 5 ? → 触发合并(流程 B)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[referral-service / PrePlantingStatsModule](新增 handler,不改现有文件)
|
||||||
|
├─ 消费 "pre-planting.portion.purchased"
|
||||||
|
└─ 更新 TeamStatistics(团队认种统计,预种份额按 1/5 棵树计入)
|
||||||
|
```
|
||||||
|
|
||||||
|
**与现有系统的隔离**:
|
||||||
|
- 预种模块**直接调用** referral-service 和 authorization-service 的**已有内部 API** 确定分配对象
|
||||||
|
- 确定对象后,调用 wallet-service 的 `allocateFunds` 执行转账(与 reward-service 调同一个 API)
|
||||||
|
- **reward-service 完全不感知预种的存在**——预种模块自己做了 reward-service 做的事情
|
||||||
|
- 推荐奖励 720 由预种模块计算后直接写入推荐人钱包
|
||||||
|
|
||||||
|
### 流程 B:自动合并(5 份 → 1 棵树) — 不创建 PlantingOrder
|
||||||
|
|
||||||
|
```
|
||||||
|
availablePortions == 5
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[planting-service / PrePlantingModule] 同一事务内:
|
||||||
|
├─ 创建 PrePlantingMerge 记录(mergeNo, 5个sourceOrderNos, contractStatus=PENDING)
|
||||||
|
│ └─ 注意:不创建 PlantingOrder!合并的树记录在自己的表中
|
||||||
|
├─ 标记 5 笔 PrePlantingOrder → MERGED
|
||||||
|
├─ 更新 PrePlantingPosition(available-=5, merged+=5, treesMerged++)
|
||||||
|
└─ Outbox: "pre-planting.merged"
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
前端收到合并通知 → 弹出合同签署流程(省市已在首次购买时确定,无需再选)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[planting-service / PrePlantingModule] 处理合同签署:
|
||||||
|
├─ 省市从 PrePlantingPosition 直接带入 PrePlantingMerge(无需用户重新选择)
|
||||||
|
├─ 生成合同 PDF(复用 MinIO 上传逻辑)
|
||||||
|
├─ 用户签约 → contractStatus = SIGNED
|
||||||
|
├─ wallet.setHasPlanted(accountSequence, true)(调用已有 API)
|
||||||
|
├─ Outbox: "pre-planting.contract.signed"
|
||||||
|
└─ 开启挖矿:miningEnabledAt = now()
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[contribution-service / PrePlantingCdcModule](新增 handler)
|
||||||
|
├─ 消费 CDC 或 "pre-planting.contract.signed"
|
||||||
|
└─ 同步合并记录,标记为 MINING_ENABLED
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键隔离点**:
|
||||||
|
- 不创建 PlantingOrder → referral-service 的现有 handler 不会被触发
|
||||||
|
- 不发布 `planting.planting.created` → reward-service 的现有 handler 不会被触发
|
||||||
|
- 不发布 `planting-events` → contract-signing 的现有 handler 不会被触发
|
||||||
|
- **所有预种事件走 `pre-planting.*` 独立 Topic**
|
||||||
|
|
||||||
|
### 流程 C:CDC 同步到 2.0(算力 — 从第 1 份即生效)
|
||||||
|
|
||||||
|
```
|
||||||
|
每份预种购买支付成功后,Debezium 立即捕获 pre_planting_orders 变更
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[contribution-service] CDC Consumer
|
||||||
|
├─ 同步到 SyncedPrePlantingAdoption
|
||||||
|
├─ 立即计算算力 = contributionPerTree / 5 × portionCount
|
||||||
|
├─ 算力立即参与挖矿分配(从第 1 份起就有收益)
|
||||||
|
├─ 解锁条件同正常认种(15 级 + 3 阶梯,按预种份额判断)
|
||||||
|
│
|
||||||
|
├─ 1 年冻结逻辑(定时任务检查):
|
||||||
|
│ ├─ 正常状态:firstPurchaseAt + 1 年内 → 算力正常分配
|
||||||
|
│ ├─ 触发冻结:firstPurchaseAt + 1 年后仍未满 5 份 → 所有算力暂停分配
|
||||||
|
│ └─ 解冻恢复:此 ID 后续累计满 5 份 → 算力恢复分配
|
||||||
|
│ └─ 恢复后的失效期 = 恢复日起算 + 2 年
|
||||||
|
│
|
||||||
|
└─ 正常到期:首次产生挖矿收益日 + 2 年后失效(未被冻结过的情况)
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键时间线示例:**
|
||||||
|
```
|
||||||
|
Day 0: 买第 1 份 → 算力 = tree算力/5,立即开始挖矿分配
|
||||||
|
Day 30: 买第 2 份 → 算力 += tree算力/5
|
||||||
|
Day 200: 买第 3 份 → 算力 += tree算力/5
|
||||||
|
Day 365: 仍只有 3 份 → 所有 3 份算力冻结(暂停分配)
|
||||||
|
Day 400: 买第 4 份 → 仍冻结(未满 5 份)
|
||||||
|
Day 420: 买第 5 份 → 自动合并成 1 棵树
|
||||||
|
→ 所有 5 份算力解冻,恢复分配
|
||||||
|
→ 解冻起算 + 2 年后失效
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 跨服务限制实现(全部通过新增 NestJS Middleware,不改现有代码)
|
||||||
|
|
||||||
|
### 实现模式:NestJS Middleware + forRoutes 精确路由匹配 + 内部 API
|
||||||
|
|
||||||
|
每个需要限制的服务新增一个 `PrePlantingGuardModule`(新文件),通过 `NestModule.configure()` + `forRoutes()` 注册路由级别 Middleware。
|
||||||
|
**只有特定路由才会执行检查逻辑**,其他路由完全无感知、零执行开销。Middleware 调用 planting-service 暴露的预种资格 API。
|
||||||
|
|
||||||
|
**planting-service 新增内部 API**(在 PrePlantingModule 内):
|
||||||
|
```
|
||||||
|
GET /internal/pre-planting/eligibility/{accountSequence}
|
||||||
|
返回:{
|
||||||
|
hasPrePlanting: boolean, // 是否有预种记录
|
||||||
|
totalPortions: number, // 累计份数
|
||||||
|
totalTreesMerged: number, // 已合成树数
|
||||||
|
canApplyAuthorization: boolean, // 可申请授权
|
||||||
|
canTrade: boolean, // 可卖出 eUSDT
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
逻辑:
|
||||||
|
- `canApplyAuthorization = totalTreesMerged >= 1`(已有认种记录的老用户不受影响,因为 hasPrePlanting=false 时 Guard 直接放行)
|
||||||
|
- `canTrade = totalTreesMerged >= 1`(同上)
|
||||||
|
|
||||||
|
### 授权锁(authorization-service — 新增文件)
|
||||||
|
|
||||||
|
```
|
||||||
|
新增文件:authorization-service/src/pre-planting/pre-planting-guard.module.ts
|
||||||
|
新增文件:authorization-service/src/pre-planting/pre-planting-authorization.middleware.ts
|
||||||
|
新增文件:authorization-service/src/pre-planting/pre-planting.client.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// pre-planting-guard.module.ts(新文件,不触碰现有代码)
|
||||||
|
@Module({ providers: [PrePlantingClient] })
|
||||||
|
export class PrePlantingGuardModule implements NestModule {
|
||||||
|
configure(consumer: MiddlewareConsumer) {
|
||||||
|
consumer
|
||||||
|
.apply(PrePlantingAuthorizationMiddleware)
|
||||||
|
.forRoutes(
|
||||||
|
{ path: 'authorization/apply*', method: RequestMethod.POST },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// pre-planting-authorization.middleware.ts(新文件)
|
||||||
|
@Injectable()
|
||||||
|
export class PrePlantingAuthorizationMiddleware implements NestMiddleware {
|
||||||
|
constructor(private readonly prePlantingClient: PrePlantingClient) {}
|
||||||
|
|
||||||
|
async use(req: Request, res: Response, next: NextFunction) {
|
||||||
|
try {
|
||||||
|
const accountSequence = req['user']?.accountSequence;
|
||||||
|
if (!accountSequence) return next(); // 无用户信息,放行
|
||||||
|
|
||||||
|
const eligibility = await this.prePlantingClient.getEligibility(accountSequence);
|
||||||
|
|
||||||
|
// 没有预种记录(纯认种用户)→ 直接放行,现有逻辑零影响
|
||||||
|
if (!eligibility.hasPrePlanting) return next();
|
||||||
|
|
||||||
|
// 有预种记录但未满 5 份合并 → 拦截
|
||||||
|
if (!eligibility.canApplyAuthorization) {
|
||||||
|
return res.status(403).json({
|
||||||
|
message: '须累积购买5份预种计划合并成树后方可申请授权',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
} catch (error) {
|
||||||
|
// planting-service 不可达时,默认放行(不影响现有功能)
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 交易锁(trading-service — 新增文件)
|
||||||
|
|
||||||
|
```
|
||||||
|
新增文件:trading-service/src/pre-planting/pre-planting-guard.module.ts
|
||||||
|
新增文件:trading-service/src/pre-planting/pre-planting-trading.middleware.ts
|
||||||
|
新增文件:trading-service/src/pre-planting/pre-planting.client.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
同理:Middleware 通过 `forRoutes({ path: 'trading/orders', method: POST })` 精确匹配卖单路由。其他路由**完全不经过此 Middleware**。对无预种记录的用户直接放行。
|
||||||
|
|
||||||
|
### 提现锁(wallet-service — 新增文件)
|
||||||
|
|
||||||
|
```
|
||||||
|
新增文件:wallet-service/src/pre-planting/pre-planting-guard.module.ts
|
||||||
|
新增文件:wallet-service/src/pre-planting/pre-planting-withdrawal.middleware.ts
|
||||||
|
新增文件:wallet-service/src/pre-planting/pre-planting.client.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Middleware 通过 `forRoutes` 精确匹配提现路由,检查 `hasPlanted`(wallet-service 自己的字段,合并签约后由 PrePlantingModule 设置为 true)。
|
||||||
|
|
||||||
|
**Middleware 的关键设计**:
|
||||||
|
- **精确路由匹配**:通过 `forRoutes()` 只对特定路由生效,其他路由零执行开销
|
||||||
|
- **异常容错**:planting-service 不可达时默认放行(`catch → next()`),不影响现有功能
|
||||||
|
- `hasPrePlanting=false`(纯认种用户)→ **直接放行**,现有功能零影响
|
||||||
|
- `hasPrePlanting=true` 且 `canXxx=true` → 放行
|
||||||
|
- `hasPrePlanting=true` 且 `canXxx=false` → 拦截
|
||||||
|
|
||||||
|
### 1 年算力冻结(contribution-service — 新增文件)
|
||||||
|
|
||||||
|
```
|
||||||
|
新增文件:contribution-service/src/pre-planting/pre-planting-cdc.module.ts
|
||||||
|
新增文件:contribution-service/src/pre-planting/pre-planting-contribution.service.ts
|
||||||
|
新增文件:contribution-service/src/pre-planting/pre-planting-freeze-scheduler.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
冻结逻辑在全新的 service 文件中实现,不触碰现有 `contribution-calculation.service.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// pre-planting-freeze-scheduler.ts(新文件)
|
||||||
|
@Cron('0 0 * * *') // 每日检查
|
||||||
|
async checkContributionFreeze() {
|
||||||
|
// 查找所有 firstPurchaseAt + 1年 < NOW() 且 totalPortions < 5 的用户
|
||||||
|
// 冻结其预种算力记录
|
||||||
|
// 查找所有 totalPortions >= 5 且仍被冻结的用户
|
||||||
|
// 解冻,设 expireDate = 解冻日 + 2年
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 后台开关逻辑
|
||||||
|
|
||||||
|
修改文件:`admin-service` 新增 `PrePlantingConfigController` + `PrePlantingConfigEntity`
|
||||||
|
|
||||||
|
### 核心原则
|
||||||
|
|
||||||
|
- **随时可开**:打开后所有用户均可购买预种
|
||||||
|
- **随时可关**:关闭后限制新购买,但**已成交的一切保持不变**
|
||||||
|
- 已支付的预种订单:状态不变、分配不变、算力不变
|
||||||
|
- 已获得的推荐奖励:不回收
|
||||||
|
- 已产生的算力:继续参与挖矿分配(除非触发 1 年冻结规则)
|
||||||
|
- 待合并的份额:允许继续购买至下一个 5 的整数倍(凑满合并)
|
||||||
|
- **开关仅控制"能否发起新购买",不影响任何已完成的业务流程**
|
||||||
|
|
||||||
|
### 开关规则(planting-service 购买前校验):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
async validatePrePlantingPurchase(userId, portionCount) {
|
||||||
|
const config = await adminClient.getPrePlantingConfig();
|
||||||
|
const position = await prePositionRepo.findByUserId(userId);
|
||||||
|
|
||||||
|
if (config.isActive) {
|
||||||
|
// 开关打开:任何人都可以购买
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开关关闭:已成交的保持不变,仅限制新购买
|
||||||
|
if (!position || position.totalPortions === 0) {
|
||||||
|
// 从未购买过的用户:显示"待开启"
|
||||||
|
throw new BusinessError('预种功能待开启');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已有未凑满的份额:允许继续购买至下一个 5 的倍数
|
||||||
|
const remainder = position.availablePortions % 5;
|
||||||
|
if (remainder === 0) {
|
||||||
|
// 已凑满当前轮次(如 5/10/15...),不可开启新一轮
|
||||||
|
throw new BusinessError('预种功能已关闭,您当前份额已满,无法继续购买');
|
||||||
|
}
|
||||||
|
const maxAdditional = 5 - remainder;
|
||||||
|
if (portionCount > maxAdditional) {
|
||||||
|
throw new BusinessError(`当前只可再购买 ${maxAdditional} 份以凑满5份`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端展示逻辑
|
||||||
|
|
||||||
|
| 开关状态 | 用户状态 | 前端表现 |
|
||||||
|
|----------|----------|----------|
|
||||||
|
| ON | 任何用户 | 正常显示购买入口 |
|
||||||
|
| OFF | 从未购买 | 显示"待开启",购买按钮置灰 |
|
||||||
|
| OFF | 有 1-4 份未合并 | 显示"可继续购买 N 份凑满合并",购买按钮可用 |
|
||||||
|
| OFF | 份额恰好为 5 的倍数 | 显示"预种功能已暂停",购买按钮置灰 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 新增 Kafka Topics
|
||||||
|
|
||||||
|
| Topic | 生产者 | 消费者 | 触发时机 |
|
||||||
|
|-------|--------|--------|----------|
|
||||||
|
| `pre-planting.portion.purchased` | planting-service | referral-service | 每份购买支付成功 |
|
||||||
|
| `pre-planting.order.paid` | referral-service | reward-service | referral 处理完团队统计后 |
|
||||||
|
| `pre-planting.merged` | planting-service | contribution-service, referral-service | 5 份合并完成 |
|
||||||
|
|
||||||
|
**注意:不复用任何现有 Topic**。预种的所有事件(购买、合并、签约)全部走 `pre-planting.*` 独立 Topic,现有消费者完全不受影响。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 新增 Debezium CDC Connector(独立连接器,不修改现有连接器)
|
||||||
|
|
||||||
|
**不修改现有 Debezium 连接器**。为预种表创建一个**全新的独立连接器**,确保现有 CDC 流零影响:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "pre-planting-connector",
|
||||||
|
"config": {
|
||||||
|
"connector.class": "io.debezium.connector.postgresql.PostgresConnector",
|
||||||
|
"database.hostname": "postgres-planting",
|
||||||
|
"database.port": "5432",
|
||||||
|
"database.dbname": "rwa_planting",
|
||||||
|
"database.server.name": "cdc.pre-planting",
|
||||||
|
"table.include.list": "public.pre_planting_orders,public.pre_planting_positions,public.pre_planting_merges",
|
||||||
|
"slot.name": "pre_planting_slot",
|
||||||
|
"publication.name": "pre_planting_publication",
|
||||||
|
"topic.prefix": "cdc.pre-planting"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Topic 命名(与现有 CDC Topic 完全隔离):
|
||||||
|
- `cdc.pre-planting.public.pre_planting_orders`
|
||||||
|
- `cdc.pre-planting.public.pre_planting_positions`
|
||||||
|
- `cdc.pre-planting.public.pre_planting_merges`
|
||||||
|
|
||||||
|
contribution-service 新增对应 CDC Consumer(在 PrePlantingCdcModule 内)。
|
||||||
|
|
||||||
|
**隔离保证**:
|
||||||
|
- 独立 replication slot → 不影响现有 slot 的 WAL 消费
|
||||||
|
- 独立 publication → 不影响现有 publication
|
||||||
|
- 独立 topic prefix → 现有消费者不会收到预种 CDC 事件
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 关键文件索引
|
||||||
|
|
||||||
|
### 需要触碰的现有文件(仅 import 注册,不改业务逻辑)
|
||||||
|
|
||||||
|
| 文件 | 改动 |
|
||||||
|
|------|------|
|
||||||
|
| `planting-service/src/app.module.ts` | `imports: [..., PrePlantingModule]` |
|
||||||
|
| `planting-service/prisma/schema.prisma` | 文件末尾追加 4 张新表定义 |
|
||||||
|
| `referral-service/src/app.module.ts` | `imports: [..., PrePlantingStatsModule]` |
|
||||||
|
| `authorization-service/src/app.module.ts` | `imports: [..., PrePlantingGuardModule]` |
|
||||||
|
| `trading-service/src/app.module.ts` | `imports: [..., PrePlantingGuardModule]` |
|
||||||
|
| `wallet-service/src/app.module.ts` | `imports: [..., PrePlantingGuardModule]` |
|
||||||
|
| `admin-service/src/app.module.ts` | `imports: [..., PrePlantingAdminModule]` |
|
||||||
|
| `admin-service/prisma/schema.prisma` | 文件末尾追加 1 张新表定义 |
|
||||||
|
| `contribution-service/src/app.module.ts` | `imports: [..., PrePlantingCdcModule]` |
|
||||||
|
| `contribution-service/prisma/schema.prisma` | 文件末尾追加 1 张新表定义 |
|
||||||
|
|
||||||
|
**以上改动总量**:每个文件仅增加 1 行 import。现有业务逻辑文件**零修改**。
|
||||||
|
|
||||||
|
### 全部新增的文件
|
||||||
|
|
||||||
|
**planting-service/src/pre-planting/**(核心模块,约 15-20 个新文件)
|
||||||
|
| 文件 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| `pre-planting.module.ts` | 模块注册 |
|
||||||
|
| `domain/aggregates/pre-planting-order.aggregate.ts` | PrePlantingOrder 聚合根 |
|
||||||
|
| `domain/aggregates/pre-planting-position.aggregate.ts` | PrePlantingPosition 聚合根 |
|
||||||
|
| `domain/aggregates/pre-planting-merge.aggregate.ts` | PrePlantingMerge 聚合根(合并的树) |
|
||||||
|
| `domain/events/pre-planting-*.event.ts` | 领域事件(purchased/merged/contract-signed) |
|
||||||
|
| `domain/value-objects/pre-planting-order-status.enum.ts` | 预种状态枚举 |
|
||||||
|
| `domain/value-objects/pre-planting-right-amounts.ts` | 1/5 分配金额常量 |
|
||||||
|
| `application/services/pre-planting-application.service.ts` | 购买 + 合并应用服务 |
|
||||||
|
| `application/services/pre-planting-reward.service.ts` | 预种分配服务(调用 wallet-service) |
|
||||||
|
| `application/services/pre-planting-contract.service.ts` | 合并后合同签署服务 |
|
||||||
|
| `api/controllers/pre-planting.controller.ts` | 用户端 API |
|
||||||
|
| `api/controllers/internal-pre-planting.controller.ts` | 内部资格查询 API |
|
||||||
|
| `infrastructure/repositories/pre-planting-order.repository.ts` | 订单仓储 |
|
||||||
|
| `infrastructure/repositories/pre-planting-position.repository.ts` | 持仓仓储 |
|
||||||
|
| `infrastructure/repositories/pre-planting-merge.repository.ts` | 合并记录仓储 |
|
||||||
|
| `infrastructure/kafka/pre-planting-outbox-publisher.service.ts` | Outbox 事件发布 |
|
||||||
|
|
||||||
|
**referral-service/src/pre-planting/**(新 handler)
|
||||||
|
| 文件 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| `pre-planting-stats.module.ts` | 模块注册 |
|
||||||
|
| `pre-planting-purchased.handler.ts` | 消费预种购买事件,更新团队统计 |
|
||||||
|
|
||||||
|
**authorization-service/src/pre-planting/**(路由级 Middleware)
|
||||||
|
| 文件 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| `pre-planting-guard.module.ts` | Middleware 模块注册(forRoutes 精确匹配) |
|
||||||
|
| `pre-planting-authorization.middleware.ts` | 授权申请拦截 Middleware |
|
||||||
|
| `pre-planting.client.ts` | 调用 planting-service 资格 API 的 HTTP Client |
|
||||||
|
|
||||||
|
**trading-service/src/pre-planting/**(路由级 Middleware)
|
||||||
|
| 文件 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| `pre-planting-guard.module.ts` | Middleware 模块注册(forRoutes 精确匹配) |
|
||||||
|
| `pre-planting-trading.middleware.ts` | 卖单拦截 Middleware |
|
||||||
|
| `pre-planting.client.ts` | HTTP Client |
|
||||||
|
|
||||||
|
**wallet-service/src/pre-planting/**(路由级 Middleware)
|
||||||
|
| 文件 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| `pre-planting-guard.module.ts` | Middleware 模块注册(forRoutes 精确匹配) |
|
||||||
|
| `pre-planting-withdrawal.middleware.ts` | 提现拦截 Middleware |
|
||||||
|
| `pre-planting.client.ts` | HTTP Client |
|
||||||
|
|
||||||
|
**admin-service/src/pre-planting/**(开关管理)
|
||||||
|
| 文件 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| `pre-planting-admin.module.ts` | 模块注册 |
|
||||||
|
| `pre-planting-config.entity.ts` | 开关实体 |
|
||||||
|
| `pre-planting-config.controller.ts` | 开关 API |
|
||||||
|
| `pre-planting-config.repository.ts` | 开关仓储 |
|
||||||
|
|
||||||
|
**contribution-service/src/pre-planting/**(CDC + 算力)
|
||||||
|
| 文件 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| `pre-planting-cdc.module.ts` | 模块注册 |
|
||||||
|
| `pre-planting-cdc.consumer.ts` | 预种表 CDC 消费 |
|
||||||
|
| `pre-planting-contribution.service.ts` | 1/5 算力计算 |
|
||||||
|
| `pre-planting-freeze-scheduler.ts` | 1 年冻结定时任务 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 实施阶段
|
||||||
|
|
||||||
|
### Phase 1:预种购买基础(planting-service + admin-service)
|
||||||
|
- Schema 迁移(3 新表 + 1 字段)
|
||||||
|
- PrePlantingOrder 聚合根 + PrePlantingPosition
|
||||||
|
- 购买 API + 开关配置
|
||||||
|
- Outbox 事件发布
|
||||||
|
|
||||||
|
### Phase 2:分配与推荐(reward-service + referral-service)
|
||||||
|
- 1/5 分配逻辑 + 720 推荐奖励
|
||||||
|
- 预种事件消费 + 团队统计
|
||||||
|
- 合并订单跳过分配逻辑
|
||||||
|
|
||||||
|
### Phase 3:自动合并(planting-service 核心)
|
||||||
|
- 5 份合并 → PrePlantingMerge 创建(不创建 PlantingOrder)
|
||||||
|
- 合并后省市选择 + 合同签署流程
|
||||||
|
- 前端合并通知 + 签约弹窗
|
||||||
|
|
||||||
|
### Phase 4:跨服务限制(authorization + trading + wallet)
|
||||||
|
- 授权申请资格校验
|
||||||
|
- eUSDT 卖出限制
|
||||||
|
- 提现 hasPlanted 校验
|
||||||
|
- 内部 API 端点
|
||||||
|
|
||||||
|
### Phase 5:2.0 算力集成(contribution-service)
|
||||||
|
- CDC 新表消费
|
||||||
|
- 1/5 算力计算
|
||||||
|
- 1 年冻结 / 解冻逻辑
|
||||||
|
- Debezium 连接器配置
|
||||||
|
|
||||||
|
### Phase 6:前端 + 测试
|
||||||
|
- Flutter 预种购买/持仓页面
|
||||||
|
- 合并提示与合同签署
|
||||||
|
- admin-web 开关管理
|
||||||
|
- 集成测试(购买 → 分配 → 合并 → 签约 → 挖矿)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 验证方案
|
||||||
|
|
||||||
|
1. **单元测试**:PrePlantingOrder 聚合根状态机、PRE_PLANTING_RIGHT_AMOUNTS 总额校验(= 3171)
|
||||||
|
2. **集成测试**:购买 5 份 → 验证 5 次分配(各 3171)→ 验证自动合并 → 验证 PrePlantingMerge 创建
|
||||||
|
3. **E2E 测试**:合并后签约 → hasPlanted=true → 可申请授权 → 可卖出 eUSDT → 可提现
|
||||||
|
4. **CDC 测试**:预种订单 → contribution-service 同步 → 算力 = tree算力/5 → 1 年冻结验证
|
||||||
|
5. **开关测试**:关闭开关 → 新用户不可购买 → 已有 3 份的用户可继续购买 2 份 → 凑满合并
|
||||||
Loading…
Reference in New Issue