rwadurian/docs/planting-architecture-optim...

17 KiB
Raw Permalink Blame History

认种功能架构优化方案

概述

本文档描述认种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 系统账户类型

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

// ============================================
// 系统账户表
// 管理成本、运营、总部社区、矿池等系统级账户
// ============================================
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 触发条件

当系统账户需要接收资金但尚未生成钱包地址时:

async function ensureWalletAddress(systemAccount: SystemAccount): Promise<string> {
  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 分配目标确定逻辑

interface AllocationTarget {
  targetType: string;
  targetUserId?: bigint;      // 用户账户
  targetSystemAccountId?: bigint;  // 系统账户
  amount: Decimal;
  hashpowerPercent?: Decimal;
}

async function calculateAllocation(
  planterId: bigint,
  treeCount: number,
  provinceCode: string,
  cityCode: string,
): Promise<AllocationTarget[]> {
  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 现有表结构

model RewardLedgerEntry {
  // 奖励状态: PENDING → CLAIMABLE → SETTLED 或 PENDING → EXPIRED
  rewardStatus    String   @default("PENDING")

  expireAt        DateTime?  // 24小时后过期时间
  claimedAt       DateTime?  // 用户认种时间(领取)
  settledAt       DateTime?  // 结算时间
  expiredAt       DateTime?  // 实际过期时间
}

5.3 定时任务

// 每分钟检查过期奖励
@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 已有)

model LadderTargetConfig {
  roleType         RoleType
  monthIndex       Int      // 第几个月
  monthlyTarget    Int      // 当月目标
  cumulativeTarget Int      // 累计目标
}

6.3 社区考核

  • 认种 1 棵后获得社区授权
  • 每月保持认种 10 棵维持权益
  • 连续 2 个月不达标,降级为普通用户

七、龙虎榜规则

7.1 排名计算referral-service 已有)

model TeamStatistics {
  // 龙虎榜分值 = 团队总认种量 - 最大单个直推团队认种量
  maxSingleTeamPlantingCount        Int @default(0)
  effectivePlantingCountForRanking  Int @default(0)
}

7.2 计算公式

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. 系统账户初始化

-- 初始化固定系统账户(地址按需生成)
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. 环境变量

# 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