From 27bd9d9d0ac5f31ab49808139d9f96a4bd528cd0 Mon Sep 17 00:00:00 2001 From: hailin Date: Tue, 9 Dec 2025 02:36:51 -0800 Subject: [PATCH] docs: add planting architecture optimization documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/planting-architecture-optimization.md | 550 +++++++++++++++++++++ 1 file changed, 550 insertions(+) create mode 100644 docs/planting-architecture-optimization.md diff --git a/docs/planting-architecture-optimization.md b/docs/planting-architecture-optimization.md new file mode 100644 index 00000000..c8b7518d --- /dev/null +++ b/docs/planting-architecture-optimization.md @@ -0,0 +1,550 @@ +# 认种功能架构优化方案 + +## 概述 + +本文档描述认种(Planting)功能的架构优化方案,基于现有微服务架构进行扩展,实现 2199 USDT 的完整分配流程。 + +**核心原则:** +- 所有账户地址通过 MPC 按需生成 +- 所有资金操作都是区块链转账(从认种人钱包转出) +- 不创建新服务,只扩展现有服务 + +--- + +## 一、2199 USDT 分配明细 + +每棵树认种费用 2199 USDT,分配如下: + +| 序号 | 账户类型 | 金额(USDT) | 说明 | +|------|----------|------------|------| +| 1 | 成本账户 | 400 | 固定成本 | +| 2 | 运营账户 | 300 | 运营费用 | +| 3 | 总部社区账户 | 9 | 总部社区收益 | +| 4 | RWAD矿池 | 800 | 注入矿池(30天后开始挖矿) | +| 5 | 直接推荐人 | 500 | 仅直推,无多级 | +| 6 | 省公司区域权益 | 15 | 正式省公司(含1%算力) | +| 7 | 省公司团队权益 | 20 | 授权省公司 | +| 8 | 市公司区域权益 | 35 | 正式市公司(含2%算力) | +| 9 | 市公司团队权益 | 40 | 授权市公司 | +| 10 | 社区权益 | 80 | 社区授权 | +| **合计** | | **2199** | | + +--- + +## 二、系统账户设计 + +### 2.1 系统账户类型 + +```typescript +enum SystemAccountType { + COST_ACCOUNT = 'COST_ACCOUNT', // 成本账户 + OPERATION_ACCOUNT = 'OPERATION_ACCOUNT', // 运营账户 + HQ_COMMUNITY = 'HQ_COMMUNITY', // 总部社区账户 + RWAD_POOL_PENDING = 'RWAD_POOL_PENDING', // RWAD矿池待注入 + SYSTEM_PROVINCE = 'SYSTEM_PROVINCE', // 系统省账户(无授权时) + SYSTEM_CITY = 'SYSTEM_CITY', // 系统市账户(无授权时) +} +``` + +### 2.2 数据库表设计(扩展 authorization-service) + +```prisma +// ============================================ +// 系统账户表 +// 管理成本、运营、总部社区、矿池等系统级账户 +// ============================================ +model SystemAccount { + id BigInt @id @default(autoincrement()) @map("account_id") + + // 账户类型 + accountType String @map("account_type") @db.VarChar(30) + + // 区域信息(仅 SYSTEM_PROVINCE/SYSTEM_CITY 需要) + regionCode String? @map("region_code") @db.VarChar(10) + regionName String? @map("region_name") @db.VarChar(50) + + // MPC 生成的钱包地址(按需生成) + walletAddress String? @map("wallet_address") @db.VarChar(42) + mpcPublicKey String? @map("mpc_public_key") @db.VarChar(130) + + // 余额 + usdtBalance Decimal @default(0) @map("usdt_balance") @db.Decimal(20, 8) + hashpower Decimal @default(0) @map("hashpower") @db.Decimal(20, 8) + + // 累计统计 + totalReceived Decimal @default(0) @map("total_received") @db.Decimal(20, 8) + totalTransferred Decimal @default(0) @map("total_transferred") @db.Decimal(20, 8) + + // 状态 + status String @default("ACTIVE") @map("status") @db.VarChar(20) + + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + ledgerEntries SystemAccountLedger[] + + @@unique([accountType, regionCode], name: "uk_account_region") + @@index([accountType], name: "idx_account_type") + @@index([walletAddress], name: "idx_wallet_address") + @@map("system_accounts") +} + +// ============================================ +// 系统账户流水表 +// 记录系统账户的所有资金变动 +// ============================================ +model SystemAccountLedger { + id BigInt @id @default(autoincrement()) @map("ledger_id") + accountId BigInt @map("account_id") + + // 流水类型 + entryType String @map("entry_type") @db.VarChar(50) + + // 金额 + amount Decimal @map("amount") @db.Decimal(20, 8) + balanceAfter Decimal @map("balance_after") @db.Decimal(20, 8) + + // 关联信息 + sourceOrderId BigInt? @map("source_order_id") // 来源认种订单 + txHash String? @map("tx_hash") @db.VarChar(66) // 链上交易哈希 + + memo String? @map("memo") @db.VarChar(500) + + createdAt DateTime @default(now()) @map("created_at") + + account SystemAccount @relation(fields: [accountId], references: [id]) + + @@index([accountId, createdAt(sort: Desc)], name: "idx_account_created") + @@index([sourceOrderId], name: "idx_source_order") + @@index([txHash], name: "idx_tx_hash") + @@map("system_account_ledgers") +} +``` + +--- + +## 三、MPC 按需生成地址流程 + +### 3.1 触发条件 + +当系统账户需要接收资金但尚未生成钱包地址时: + +```typescript +async function ensureWalletAddress(systemAccount: SystemAccount): Promise { + if (systemAccount.walletAddress) { + return systemAccount.walletAddress; + } + + // 调用 MPC 服务生成地址 + const { publicKey, address } = await mpcService.generateAddress({ + accountType: 'SYSTEM', + accountId: systemAccount.id.toString(), + }); + + // 更新系统账户 + await prisma.systemAccount.update({ + where: { id: systemAccount.id }, + data: { + walletAddress: address, + mpcPublicKey: publicKey, + }, + }); + + // 注册到 blockchain-service 进行监听 + await blockchainService.registerMonitoredAddress({ + address, + accountType: 'SYSTEM', + accountId: systemAccount.id, + }); + + return address; +} +``` + +### 3.2 用户账户按需生成 + +用户钱包地址在以下场景按需生成: +- 首次认种时(需要从钱包扣款) +- 首次充值时(需要收款地址) +- 查询收款地址时 + +--- + +## 四、认种完整流程 + +### 4.1 流程图 + +``` +用户发起认种请求 + ↓ +验证用户钱包余额 ≥ 2199 USDT × 数量 + ↓ +创建认种订单(PENDING) + ↓ +计算分配方案(查询省市授权状态) + ↓ +执行链上转账(多笔转账) + ├── 400 → 成本账户 + ├── 300 → 运营账户 + ├── 9 → 总部社区账户 + ├── 800 → RWAD矿池账户 + ├── 500 → 直接推荐人(作为待领取奖励) + ├── 15+1%算力 → 省区域权益接收方 + ├── 20 → 省团队权益接收方 + ├── 35+2%算力 → 市区域权益接收方 + ├── 40 → 市团队权益接收方 + └── 80 → 社区权益接收方 + ↓ +更新订单状态(COMPLETED) + ↓ +更新团队统计(referral-service) + ↓ +更新授权考核进度(authorization-service) + ↓ +30天后启动挖矿(矿池注入) +``` + +### 4.2 分配目标确定逻辑 + +```typescript +interface AllocationTarget { + targetType: string; + targetUserId?: bigint; // 用户账户 + targetSystemAccountId?: bigint; // 系统账户 + amount: Decimal; + hashpowerPercent?: Decimal; +} + +async function calculateAllocation( + planterId: bigint, + treeCount: number, + provinceCode: string, + cityCode: string, +): Promise { + const unitPrice = new Decimal(2199); + const totalAmount = unitPrice.mul(treeCount); + + const allocations: AllocationTarget[] = []; + + // 1. 固定系统账户分配 + allocations.push( + { targetType: 'COST_ACCOUNT', targetSystemAccountId: costAccountId, amount: new Decimal(400).mul(treeCount) }, + { targetType: 'OPERATION_ACCOUNT', targetSystemAccountId: operationAccountId, amount: new Decimal(300).mul(treeCount) }, + { targetType: 'HQ_COMMUNITY', targetSystemAccountId: hqCommunityAccountId, amount: new Decimal(9).mul(treeCount) }, + { targetType: 'RWAD_POOL', targetSystemAccountId: rwadPoolAccountId, amount: new Decimal(800).mul(treeCount) }, + ); + + // 2. 直接推荐人(500 USDT) + const referrer = await referralService.getDirectReferrer(planterId); + if (referrer) { + allocations.push({ + targetType: 'DIRECT_REFERRER', + targetUserId: referrer.userId, + amount: new Decimal(500).mul(treeCount), + }); + } else { + // 无推荐人,归入运营账户 + allocations.push({ + targetType: 'OPERATION_ACCOUNT', + targetSystemAccountId: operationAccountId, + amount: new Decimal(500).mul(treeCount), + }); + } + + // 3. 省公司权益(15 区域 + 20 团队) + const provinceAuth = await authorizationService.getActiveProvinceAuth(provinceCode); + if (provinceAuth?.roleType === 'PROVINCE_COMPANY' && provinceAuth.benefitActive) { + // 正式省公司 - 区域权益 15U + 1% 算力 + allocations.push({ + targetType: 'PROVINCE_REGION', + targetUserId: provinceAuth.userId, + amount: new Decimal(15).mul(treeCount), + hashpowerPercent: new Decimal(1), + }); + } else { + // 无正式省公司,归入系统省账户 + const systemProvince = await getOrCreateSystemAccount('SYSTEM_PROVINCE', provinceCode); + allocations.push({ + targetType: 'SYSTEM_PROVINCE', + targetSystemAccountId: systemProvince.id, + amount: new Decimal(15).mul(treeCount), + }); + } + + // 授权省公司 - 团队权益 20U + if (provinceAuth?.roleType === 'AUTH_PROVINCE_COMPANY' && provinceAuth.benefitActive) { + allocations.push({ + targetType: 'PROVINCE_TEAM', + targetUserId: provinceAuth.userId, + amount: new Decimal(20).mul(treeCount), + }); + } else { + const systemProvince = await getOrCreateSystemAccount('SYSTEM_PROVINCE', provinceCode); + allocations.push({ + targetType: 'SYSTEM_PROVINCE', + targetSystemAccountId: systemProvince.id, + amount: new Decimal(20).mul(treeCount), + }); + } + + // 4. 市公司权益(35 区域 + 40 团队)- 类似省公司逻辑 + // ... + + // 5. 社区权益(80 USDT) + const communityAuth = await authorizationService.getCommunityAuth(planterId); + if (communityAuth && communityAuth.benefitActive) { + allocations.push({ + targetType: 'COMMUNITY', + targetUserId: communityAuth.userId, + amount: new Decimal(80).mul(treeCount), + }); + } else { + allocations.push({ + targetType: 'OPERATION_ACCOUNT', + targetSystemAccountId: operationAccountId, + amount: new Decimal(80).mul(treeCount), + }); + } + + return allocations; +} +``` + +--- + +## 五、24小时待领取奖励机制 + +### 5.1 奖励状态流转 + +``` +PENDING(待领取) + ↓ 用户认种 +CLAIMABLE(可结算) + ↓ 用户结算 +SETTLED(已结算) + +PENDING(待领取) + ↓ 24小时未认种 +EXPIRED(已过期) +``` + +### 5.2 reward-service 现有表结构 + +```prisma +model RewardLedgerEntry { + // 奖励状态: PENDING → CLAIMABLE → SETTLED 或 PENDING → EXPIRED + rewardStatus String @default("PENDING") + + expireAt DateTime? // 24小时后过期时间 + claimedAt DateTime? // 用户认种时间(领取) + settledAt DateTime? // 结算时间 + expiredAt DateTime? // 实际过期时间 +} +``` + +### 5.3 定时任务 + +```typescript +// 每分钟检查过期奖励 +@Cron('* * * * *') +async checkExpiredRewards() { + const expiredRewards = await prisma.rewardLedgerEntry.findMany({ + where: { + rewardStatus: 'PENDING', + expireAt: { lt: new Date() }, + }, + }); + + for (const reward of expiredRewards) { + await prisma.$transaction([ + // 更新奖励状态 + prisma.rewardLedgerEntry.update({ + where: { id: reward.id }, + data: { + rewardStatus: 'EXPIRED', + expiredAt: new Date(), + }, + }), + // 更新用户汇总 + prisma.rewardSummary.update({ + where: { userId: reward.userId }, + data: { + pendingUsdt: { decrement: reward.usdtAmount }, + expiredTotalUsdt: { increment: reward.usdtAmount }, + }, + }), + ]); + + // 将过期金额转入运营账户 + await transferToOperationAccount(reward.usdtAmount, reward.id); + } +} +``` + +--- + +## 六、授权考核规则 + +### 6.1 省市公司授权考核 + +| 角色 | 初始目标 | 月度考核 | 权益 | +|------|----------|----------|------| +| 授权省公司 | 500棵 | 阶梯递增 | 团队权益 20U | +| 正式省公司 | 已达标 | 无 | 区域权益 15U + 1%算力 | +| 授权市公司 | 200棵 | 阶梯递增 | 团队权益 40U | +| 正式市公司 | 已达标 | 无 | 区域权益 35U + 2%算力 | + +### 6.2 阶梯考核目标(authorization-service 已有) + +```prisma +model LadderTargetConfig { + roleType RoleType + monthIndex Int // 第几个月 + monthlyTarget Int // 当月目标 + cumulativeTarget Int // 累计目标 +} +``` + +### 6.3 社区考核 + +- 认种 1 棵后获得社区授权 +- 每月保持认种 10 棵维持权益 +- 连续 2 个月不达标,降级为普通用户 + +--- + +## 七、龙虎榜规则 + +### 7.1 排名计算(referral-service 已有) + +```prisma +model TeamStatistics { + // 龙虎榜分值 = 团队总认种量 - 最大单个直推团队认种量 + maxSingleTeamPlantingCount Int @default(0) + effectivePlantingCountForRanking Int @default(0) +} +``` + +### 7.2 计算公式 + +```typescript +function calculateLeaderboardScore(userId: bigint): number { + const stats = await getTeamStatistics(userId); + + // 有效分值 = 团队总认种 - 最大单线团队认种 + return stats.totalTeamPlantingCount - stats.maxSingleTeamPlantingCount; +} +``` + +--- + +## 八、服务职责划分 + +| 服务 | 职责 | +|------|------| +| **planting-service** | 认种订单管理、分配计算、矿池注入批次 | +| **wallet-service** | 用户钱包余额、链上转账执行 | +| **blockchain-service** | 地址监听、交易广播、MPC 交互 | +| **reward-service** | 奖励流水、24h过期处理、结算 | +| **referral-service** | 推荐关系、团队统计、龙虎榜 | +| **authorization-service** | 省市社区授权、考核进度、**系统账户管理** | +| **identity-service** | 用户身份、MPC 钱包创建 | + +--- + +## 九、待实现功能清单 + +### 9.1 authorization-service 扩展 + +- [ ] 添加 `SystemAccount` 表 +- [ ] 添加 `SystemAccountLedger` 表 +- [ ] 实现系统账户 CRUD API +- [ ] 实现按需生成 MPC 地址逻辑 + +### 9.2 planting-service 扩展 + +- [ ] 实现完整分配计算逻辑 +- [ ] 集成 wallet-service 执行链上转账 +- [ ] 集成 authorization-service 查询授权状态 +- [ ] 集成 referral-service 查询推荐人 + +### 9.3 reward-service 扩展 + +- [ ] 实现 24 小时过期定时任务 +- [ ] 实现用户认种触发奖励领取 +- [ ] 实现过期奖励转入运营账户 + +### 9.4 wallet-service 扩展 + +- [ ] 实现批量链上转账 API +- [ ] 支持系统账户转账 + +### 9.5 blockchain-service 扩展 + +- [ ] 支持系统账户地址监听 +- [ ] 实现 MPC 签名批量交易 + +--- + +## 十、数据流示意 + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ 认种数据流 │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 用户钱包 (wallet-service) │ +│ │ │ +│ │ 2199 USDT × N │ +│ ▼ │ +│ planting-service │ +│ │ │ +│ ├─── 400 ──→ 成本账户 (authorization-service.SystemAccount) │ +│ ├─── 300 ──→ 运营账户 (authorization-service.SystemAccount) │ +│ ├─── 9 ──→ 总部社区 (authorization-service.SystemAccount) │ +│ ├─── 800 ──→ RWAD矿池 (authorization-service.SystemAccount) │ +│ ├─── 500 ──→ 直推人钱包 (wallet-service) → reward-service (待领取) │ +│ ├─── 15 ──→ 省区域 (用户钱包 或 系统省账户) │ +│ ├─── 20 ──→ 省团队 (用户钱包 或 系统省账户) │ +│ ├─── 35 ──→ 市区域 (用户钱包 或 系统市账户) │ +│ ├─── 40 ──→ 市团队 (用户钱包 或 系统市账户) │ +│ └─── 80 ──→ 社区 (用户钱包 或 运营账户) │ +│ │ +│ 所有转账通过 blockchain-service 执行链上交易 │ +│ 所有地址通过 MPC 按需生成 │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 附录:关键配置 + +### A. 系统账户初始化 + +```sql +-- 初始化固定系统账户(地址按需生成) +INSERT INTO system_accounts (account_type, region_code, status) VALUES + ('COST_ACCOUNT', NULL, 'ACTIVE'), + ('OPERATION_ACCOUNT', NULL, 'ACTIVE'), + ('HQ_COMMUNITY', NULL, 'ACTIVE'), + ('RWAD_POOL_PENDING', NULL, 'ACTIVE'); +``` + +### B. 环境变量 + +```env +# MPC 服务配置 +MPC_SERVICE_URL=http://mpc-service:3010 + +# 认种相关 +PLANTING_UNIT_PRICE=2199 +REWARD_EXPIRE_HOURS=24 +MINING_START_DELAY_DAYS=30 +``` + +--- + +*文档版本: v1.0* +*创建日期: 2025-12-08* +*最后更新: 2025-12-08*