Commit Graph

1288 Commits

Author SHA1 Message Date
hailin 5b1f4c82e6 fix(deploy): full-reset 时重建 1.0 source CDC connectors 以确保完整数据同步
问题:
  执行 deploy-mining.sh full-reset 后,identity-postgres-connector 等 1.0 source
  CDC connectors 保留了旧的 Debezium offset 和 replication slot,导致 Debezium
  认为 initial snapshot 已完成而跳过重新快照。如果 connector 的 JSON 配置文件中
  新增了表(如 identity-connector.json 中的 wallet_addresses),这些表的存量数据
  永远不会被捕获到 Kafka topic,2.0 服务无法通过 CDC 同步到这些数据。

  具体表现:Kafka topic cdc.identity.public.wallet_addresses 始终为空(0条消息),
  2.0 auth-service 的 synced_wallet_addresses 表为空,用户 KAVA 地址未同步。

修复:
  在 full_reset() 的 Step 4 中,除了处理 outbox connectors,还新增了对 1.0 source
  CDC connectors (identity/referral/planting) 的处理:
  1. 删除 connector(释放 replication slot)
  2. 发送 tombstone 清除 debezium_offsets topic 中的偏移量
  3. 调用 pg_drop_replication_slot() 删除 PostgreSQL replication slot

  新增 Step 9:从 scripts/debezium/*.json 配置文件重新注册 source connectors,
  因为 offset 和 slot 都已清除,snapshot.mode=initial 会触发全新的 initial snapshot,
  确保所有配置表(包括新增的 wallet_addresses)的存量数据都被灌入 Kafka topic。

  总步骤数从 18 调整为 19。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 20:26:06 -08:00
hailin f60e3751b8 fix(c2c): 修复水单上传权限、手机号、卖方ID、资产显示
- Dockerfile: 用 su-exec 模式解决 Docker volume 权限问题
- JWT guard: 从 token 提取 phone 字段
- 订单详情: 新增卖方ID显示
- C2C市场页: 修复资产概览两列重复显示 availableCash,
  改为左列显示可用积分股、右列显示可用积分值

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 09:19:38 -08:00
hailin e783661002 fix(c2c): 修复水单上传权限、手机号显示、卖方ID显示
- Dockerfile 预创建 /app/uploads/c2c-proofs 并设置正确权限
- JWT guard 从 token payload 提取 phone 字段(之前仅提取 accountSequence)
- 订单详情页订单信息组新增卖方ID显示

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 09:13:46 -08:00
hailin 25ea0bf64e fix(trading-service): 修复 Multer 类型缺失导致构建失败
使用内联类型替代 Express.Multer.File,避免 @types/multer 依赖

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 08:58:55 -08:00
hailin ce173451f5 feat(c2c): 订单详情增强、付款水单上传、买单逻辑修复及schema对齐
- 订单详情页显示完整手机号和收款账号信息
- 新增付款水单上传功能(前后端全链路)
- 修复时间显示为本地时区格式
- 移除买单发布时的积分值余额验证(买方通过外部绿积分支付)
- 前端买单发布页隐藏余额卡片和"全部"按钮
- 补齐 Prisma migration 与 schema 差异(payment_proof_url、
  bot_purchased索引、market_maker_deposits/withdraws表)
- docker-compose 新增 trading-uploads 卷用于水单持久化

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 08:54:05 -08:00
hailin 4df23b02b8 fix(trading-service): 添加做市商钱包环境变量,修复地址未配置问题
FUSDT/EUSDT_MARKET_MAKER_ADDRESS 和 USERNAME 只传给了
mining-blockchain-service,但 trading-service 初始化时也需要
读取这些变量写入数据库,导致前端显示"做市商钱包地址未配置"。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 07:56:16 -08:00
hailin 8e63547a3e fix(transfer): 修复积分股划转到分配账户失败问题
后端:
- transfer.service.ts: Error → BadRequestException,业务错误返回HTTP 400而非500
- transfer.controller.ts: Error → UnauthorizedException,正确返回HTTP 401
- 错误信息改为中文:余额不足、账户不存在等提示更明确

前端:
- asset_display.dart: 新增 tradingAvailableShares 计算属性(总可用 - 挖矿可用)
- trading_page.dart: 划转弹窗显示可用余额(扣除冻结)而非总余额
- trading_page.dart: 划转失败时显示后端具体错误信息而非通用提示

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 06:24:35 -08:00
hailin 3cbb874503 fix(auth-service): 返回完整手机号,修复QR码扫码失败
- login/profile 接口返回 user.phone.value 替代 user.phone.masked
- 根因:QR码编码脱敏号 199****9327,正则要求纯数字匹配失败

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 06:00:47 -08:00
hailin 8c31dee000 fix(c2c): 修复买方待付款页面灰色无法操作问题
根因: c2c_order_model.dart 的 _parsePaymentMethod 不识别 GREEN_POINTS,
导致 paymentMethod=null → hasPaymentInfo=false → 收款信息卡片隐藏 → 页面不可操作

前端修复:
- C2cPaymentMethod 枚举增加 greenPoints,解析器支持 GREEN_POINTS
- 支持逗号分隔的多支付方式字符串(取第一个作为主要方式)
- 订单详情页增加绿积分图标和卖方 Kava 地址显示(买方可复制)

后端修复:
- takeOrder() 接买单时自动获取卖方 Kava 地址写入 sellerKavaAddress
- 买方在订单详情页可看到卖方 Kava 地址用于转绿积分

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 05:41:14 -08:00
hailin f167f1227c Revert "fix(trading-service): C2C卖单不再强制要求Kava钱包地址"
This reverts commit 9b8f720915.
2026-01-30 21:04:27 -08:00
hailin 9b8f720915 fix(trading-service): C2C卖单不再强制要求Kava钱包地址
executeTransfer不使用sellerKavaAddress,C2C交易是积分值划转+外部绿积分支付,
不涉及Kava链上操作。改为可选获取,失败不阻断订单创建。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:03:59 -08:00
hailin 7180e2ac27 fix(contribution): 算力记录按层级升序排列 L1→L2→...→L15
用户期望 L1 在前 L15 在后,将 levelDepth/bonusTier 排序从 DESC 改为 ASC

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 20:14:31 -08:00
hailin 17f8a61bcf feat(contribution-service): 贡献值明细按 L/T 降序排序
- 同伴下贡献值 (TEAM_LEVEL): 按 levelDepth DESC 排序 (L3, L2, L1)
- 同伴上贡献值 (TEAM_BONUS): 按 bonusTier DESC 排序 (T3, T2, T1)
- 全部/本人: 按 levelDepth DESC, bonusTier DESC, createdAt DESC

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:20:03 -08:00
hailin a31fcaa9b8 fix(mining-admin): configValue → value,修复配置读取后 fallback 到默认值
Prisma 返回的字段是 value,controller 写成了 configValue,
导致 getP2pTransferFee / getTransferEnabled 永远返回默认值

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:18:13 -08:00
hailin 3507805005 fix(mining-admin): Docker uploads 目录权限修复,预创建 /app/uploads 并设置 nestjs 用户所有权
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:19:14 -08:00
hailin 6900905475 fix(mining-admin): APK下载URL指向localhost导致手机无法下载
问题:FileStorageService 默认 UPLOAD_BASE_URL 为 http://localhost:3020/downloads,
手机端无法访问服务器的 localhost。

修复:
- docker-compose.2.0.yml: 添加 UPLOAD_BASE_URL=https://rwaapi.szaiai.com/mining-admin/downloads
- 添加 mining-admin-uploads volume 持久化上传的 APK 文件
- 修正默认端口 3020→3023(mining-admin-service 实际端口)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:56:40 -08:00
hailin 94d4524ee3 fix(c2c): 积分股→积分值,C2C交易对象修正为积分值(cash)
C2C交易的产品是积分值,支付方式是绿积分(外部1.0系统),与积分股无关。

前端:
- c2c_publish_page: 余额卡、数量输入、提示文案、确认弹窗全部改为积分值
- c2c_market_page: 余额概览(availableShares→availableCash)、订单数量标签、接单弹窗
- c2c_order_detail_page: 订单详情、划转提示、确认收款弹窗

后端 c2c.service.ts:
- createOrder SELL: freezeShares→freezeCash
- takeOrder BUY(taker=卖方): freezeShares→freezeCash
- takeOrder SELL(taker=买方): 移除冻结(买方通过外部支付绿积分)
- cancelOrder SELL: unfreezeShares→unfreezeCash
- expireOrder: unfreezeShares→unfreezeCash,SELL不再解冻taker
- executeTransfer: 统一BUY/SELL为单向积分值划转,assetType改为CASH

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:41:23 -08:00
hailin 49bcb96c4c fix(trading): 补充 p2p_transfers 表遗漏的 fee 列
schema 中定义了 fee 字段但 0002 migration 遗漏,导致
prisma.p2pTransfer.create() 报错 "column fee does not exist"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:24:50 -08:00
hailin f0c7cee94e fix(auth): lookupByPhone 支持查询未迁移的 1.0 用户
P2P 转账验证手机号时,lookupByPhone 只查 users 表(V2 注册用户),
导致未登录过 2.0 的 1.0 老用户(CDC 同步在 synced_legacy_users 表)
被报"不存在"。修改为先查 users 表,未找到再查 synced_legacy_users。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:41:58 -08:00
hailin 187b82e9ac feat(c2c): 修复6项C2C交易问题 (#11-#16)
- #11: 价格固定1:1,最小交易数量为1
- #12: BUY买单不再冻结买方积分值(绿积分通过外部1.0系统支付)
- #13: 支持部分成交,taker可指定数量,剩余自动拆分为新PENDING订单
- #14: 发布页双向输入,积分股数量与积分值金额1:1联动
- #15: 接BUY单时弹出收款信息输入(收款方式、账号、姓名)
- #16: BUY单创建时验证积分值余额但不冻结

后端: cancelOrder/expireOrder/executeTransfer 均按BUY/SELL分别处理
前端: 发布页价格只读、市场页接单对话框增加数量和收款输入

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:36:57 -08:00
hailin 9adef67bb8 feat(admin-web): P2P划转记录管理页面 + 手续费汇总
## 后端 — mining-admin-service
- users.controller: 新增 GET /users/p2p-transfers 端点(搜索+分页)
  - 放在 :accountSequence 路由之前避免被 catch-all 拦截
- users.service: 新增 getP2pTransfers() 代理方法
  - 调用 trading-service 的 /api/v2/p2p/internal/all-transfers
  - 返回划转记录列表 + 汇总统计 + 分页信息

## 前端 — mining-admin-web
- 新增 /p2p-transfers 页面:
  - 三个汇总卡片:累计手续费收入、累计划转金额、成功划转笔数
  - 搜索框支持账号、手机号、转账单号搜索
  - 记录表格:转账单号、发送方、接收方、转账金额、手续费、备注、时间
  - 分页控件
- sidebar: 新增"P2P划转"导航项(位于"交易管理"下方)
- users.api: 新增 getP2pTransfers API + P2pTransferRecord 类型
- use-users: 新增 useP2pTransfers hook

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 10:41:55 -08:00
hailin 9f94344e8b feat: 算力记录排序 + P2P转账管理后台查询端点
## 算力记录排序(全栈)
- mining-admin-service controller: 新增 sortBy/sortOrder 查询参数
- users.service: 动态构建 orderBy(支持 sourceType, levelDepth, amount, createdAt)
  - levelDepth 排序特殊处理:先按 sourceType 分组,再按 levelDepth/bonusTier 排序,null 值排末尾
- admin-web contribution-records-list: 可点击排序表头(来源、获得算力、层级/等级、生效日期)
  - 三态切换:升序 → 降序 → 取消排序
  - 排序图标指示当前状态

## P2P转账管理后台查询端点(后端准备)
- trading-service P2pTransferService: 新增 getAllTransfers() 方法
  - 列出全部已完成 P2P 转账记录(分页 + 搜索)
  - 返回汇总统计:总手续费、总转账金额、总笔数
- trading-service controller: 新增 GET /p2p/internal/all-transfers(@Public 内部端点)
- P2pTransferHistoryItem 接口扩展 fromPhone/fromNickname/toNickname 字段

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 10:37:22 -08:00
hailin b1607666a0 fix(contribution): LEVEL_OVERFLOW 回收任务,修复已解锁层级的溢出记录无法被回收的 bug
当下级认种时上级 unlocked_level_depth 不足,层级奖励进入 LEVEL_OVERFLOW(PENDING)。
上级后续解锁到足够层级后,现有 backfill 因条件 expectedLevel > currentLevel 为 false
而跳过,导致 PENDING 记录永远无法被回收。新增独立调度任务每10分钟扫描并回收。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 10:12:48 -08:00
hailin ca4e5393be feat(p2p-transfer): 实现P2P划转手续费功能(全栈)
## 功能概述
- P2P转账(积分值)支持手续费收取,手续费存入系统成本费账户 S0000000002
- 发送方实际扣除 = 转账金额 + 手续费,接收方全额收到转账金额
- 手续费金额和最小划转金额可在管理后台动态配置(默认: 手续费5, 最小划转6)

## 后端 — mining-admin-service
- GET /configs/p2p-transfer-fee: 管理端获取手续费配置(需鉴权)
- POST /configs/p2p-transfer-fee: 管理端设置手续费配置,校验最小划转 > 手续费
- GET /configs/internal/p2p-transfer-fee: 内部调用端点(@Public 无鉴权)

## 后端 — trading-service
- Prisma schema: P2pTransfer model 新增 fee Decimal(30,8) 字段
- docker-compose: 新增 MINING_ADMIN_SERVICE_URL 环境变量
- p2p-transfer.service: 动态获取手续费配置,余额校验含手续费,
  事务内分别记录转账流水和手续费流水(P2P_TRANSFER_FEE),
  手续费存入系统成本费账户 S0000000002
- p2p-transfer.controller: 新增 GET /p2p/transfer-fee-config 代理端点
- 转账结果和历史记录新增 fee 字段返回

## 前端 — mining-admin-web
- configs.api.ts: 新增 getP2pTransferFee / setP2pTransferFee API
- use-configs.ts: 新增 useP2pTransferFee / useSetP2pTransferFee hooks
- configs/page.tsx: 新增"P2P划转手续费设置"卡片(手续费 + 最小划转金额)

## 前端 — mining-app (Flutter)
- api_endpoints.dart: 新增 p2pTransferFeeConfig 端点常量
- p2p_transfer_fee_config_model.dart: 新增手续费配置 Model
- trading_remote_datasource.dart: 新增 getP2pTransferFeeConfig 方法
- transfer_providers.dart: 新增 p2pTransferFeeConfigProvider
- send_shares_page.dart: 发送页面显示手续费信息、最小划转金额提示、
  实际扣除金额计算、"全部"按钮扣除手续费、确认弹窗展示手续费明细

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 06:44:19 -08:00
hailin 817b7d3a9f fix(contribution): 算力分配时序保证 + bonus补发stale-read修复
4处改动确保部署清库重新同步后100%可靠:

1. contribution.scheduler.ts - CDC就绪门控
   注入CDCConsumerService,processUnprocessedAdoptions/publishRecentlyUpdatedAccounts/
   processContributionBackfill三个调度方法开头加isCdcReady()检查,
   确保用户+推荐+认种三阶段CDC同步全部完成后才开始处理。

2. contribution-calculation.service.ts - 推荐数据防护
   calculateForAdoption()中,userReferral为null时warn并return,
   不标记distributed,调度器下次重试。覆盖continuous mode下
   认种事件先于推荐事件到达的竞态场景。

3. bonus-claim.service.ts - bonus补发stale-read修复
   processBackfillForAccount()中,level事务的updateAccountUnlockStatus
   通过incrementDirectReferralAdoptedCount()同时修改unlockedLevelDepth
   和unlockedBonusTiers,导致bonus分支条件永远为false。
   修复:保存originalDirectReferralAdoptedCount和originalUnlockedBonusTiers,
   bonus分支使用原始值判断和传参。

4. config.controller.ts - mining-admin同步检查增强
   isSynced新增allAdoptionsProcessed条件(unprocessedAdoptions===0),
   确保所有认种分配+补发完成后才允许激活挖矿。
   修复data变量作用域问题(原在if块内声明,外部引用会报错)。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 05:54:02 -08:00
hailin 83384acdac fix(mining-service): Redis DB 11 冲突修复,迁移至 DB 16
问题:
  mining-service (2.0) 与 blockchain-service (1.0) 共用 Redis DB 11,
  存在数据污染和资源抢占风险。虽然当前 Key 前缀不同
  (mining:* vs blockchain:*),但缺乏结构性隔离保障。

方案:
  - 将 mining-service Redis DB 从 11 迁移到 16 (超出默认 0-15 范围)
  - Redis 基础设施配置增加 --databases 20,支持 DB 16+
  - 同步修正 .env.example 与代码默认值不一致的问题 (原 .env=1, 代码=11)

修改清单:
  - mining-service/infrastructure.module.ts: 代码默认值 11 → 16
  - mining-service/redis.service.ts: fallback 默认值 1 → 16
  - mining-service/.env.example: REDIS_DB=1 → REDIS_DB=16
  - docker-compose.2.0.yml: mining-service REDIS_DB 11 → 16 + 注释
  - docker-compose.yml: Redis 添加 --databases 20
  - docker-compose.infra.yml: Redis 添加 --databases 20
  - docker-compose.windows.yml: Redis 添加 --databases 20

部署注意:
  1. 需重启 Redis 容器使 --databases 20 生效
  2. 需重启 mining-service 使新 DB 16 生效
  3. 旧 DB 11 中 mining-service 的残留数据可手动清理:
     redis-cli -n 11 KEYS "mining:*" | xargs redis-cli -n 11 DEL

Redis DB 分配表 (修改后):
  1.0: DB 0-11 (identity=0, wallet=1, ..., blockchain=11)
  2.0: DB 8,10,12-16 (blockchain=8, contribution=10, trading=12,
       admin=13, auth=14, wallet=15, mining=16)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:22:20 -08:00
hailin 454b379f6c feat(mining-blockchain-service): mining_ 前缀隔离,与 blockchain-service 100% 资源分离
mining-blockchain-service 的所有共享资源全部加上 mining_ 前缀,
确保与 1.0 blockchain-service 完全隔离,互不干扰。

## Kafka Topic 隔离 — 生产者 (event-publisher.service.ts)

- source header: 'blockchain-service' → 'mining-blockchain-service'
- topic 映射全部加 mining_ 前缀:
  - blockchain.deposits → mining_blockchain.deposits
  - blockchain.wallets → mining_blockchain.wallets
  - blockchain.transactions → mining_blockchain.transactions
  - mpc.SigningRequested → mining_mpc.SigningRequested
  - blockchain.market_maker.deposits → mining_blockchain.market_maker.deposits
  - 默认 fallback: blockchain.events → mining_blockchain.events

## Domain Event eventType 隔离 (5 个事件类)

- deposit-detected.event.ts: mining_blockchain.deposit.detected
- deposit-confirmed.event.ts: mining_blockchain.deposit.confirmed
- wallet-address-created.event.ts: mining_blockchain.wallet.address.created
- transaction-broadcasted.event.ts: mining_blockchain.transaction.broadcasted
- market-maker-deposit-confirmed.event.ts: mining_blockchain.market_maker.deposit.confirmed

## Kafka Topic 隔离 — 消费者 (3 个 consumer)

- mpc-event-consumer: mining_mpc.KeygenCompleted / SigningCompleted / SessionFailed
- withdrawal-event-consumer: mining_wallet.withdrawals / mining_wallet.system-withdrawals
  - 事件类型检查: mining_wallet.withdrawal.requested / mining_wallet.system-withdrawal.requested
- deposit-ack-consumer: mining_wallet.acks
  - 事件类型检查: mining_wallet.deposit.credited
  - outbox ACK 匹配: mining_blockchain.deposit.confirmed

## Kafka 事件类型 — Event Handlers

- mpc-signing.client.ts:
  - MPC_SIGNING_TOPIC → mining_mpc.SigningRequested
  - eventType → mining_blockchain.mpc.signing.requested
- withdrawal-requested.handler.ts:
  - mining_blockchain.withdrawal.confirmed / failed / status
- system-withdrawal-requested.handler.ts:
  - mining_blockchain.system-withdrawal.confirmed / failed

## Redis Key 前缀隔离

- address-cache: blockchain:monitored_addresses: → mining_blockchain:monitored_addresses:
- hot-wallet-balance: hot_wallet:dusdt_balance: → mining_hot_wallet:dusdt_balance:
- hot-wallet-balance: hot_wallet:native_balance: → mining_hot_wallet:native_balance:

## 数据库名称隔离

- docker-compose.yml: rwa_blockchain → rwa_mining_blockchain
- docker-compose.2.0.yml: rwa_blockchain → rwa_mining_blockchain
- deploy-mining.sh: MINING_DATABASES + SERVICE_DB 映射 → rwa_mining_blockchain

## 下游服务需配套更新 (不在本次修改范围)

- mpc-service: 消费 mining_mpc.SigningRequested, 发布 mining_mpc.* 结果
- mining-wallet-service: 发布 mining_wallet.*, 消费 mining_blockchain.*
- trading-service: 消费 mining_blockchain.market_maker.deposits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 01:58:45 -08:00
hailin 08cf4681f2 fix: migration 使用 IF NOT EXISTS 防止重复创建 + clean 去掉 --remove-orphans
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 00:37:29 -08:00
hailin 4a803ea008 feat(deploy): 添加 clean 命令清除 2.0 所有 Docker 资源
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 23:36:35 -08:00
hailin 6b92ab0dd8 Revert "fix(2.0): 所有 Kafka consumer 改为 fromBeginning: true 确保 full-reset 全量同步"
This reverts commit 534d4ce70c.
2026-01-29 22:41:40 -08:00
hailin a41feb841f fix(mining-service): 添加 ManualMiningRecord 缺失的 migration 0004
schema 中定义的 manual_mining_records 表缺少对应的 migration 文件,
导致 schema 与 migration 不一致。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 22:30:04 -08:00
hailin 534d4ce70c fix(2.0): 所有 Kafka consumer 改为 fromBeginning: true 确保 full-reset 全量同步
- mining-blockchain-service: withdrawal/mpc/deposit-ack consumer 改为 fromBeginning: true
- trading-service: cdc-consumer/market-maker-deposit consumer 改为 fromBeginning: true
- mining-service: contribution-event handler 改为 fromBeginning: true
- deploy-mining.sh: CDC_CONSUMER_GROUPS 补充所有 2.0 服务的 consumer group ID

确保 ./deploy-mining.sh full-reset 可以 100% 从 0 开始同步所有 1.0 数据。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 22:20:23 -08:00
hailin 5dc37e24d2 fix(deploy): cdc_resnapshot 清空 rwa_auth 的 processed_cdc_events
cdc_resnapshot 之前只清空 rwa_contribution 的幂等表,遗漏了 rwa_auth,
导致 wallet address CDC 重新快照后消息被幂等检查跳过,KAVA 地址无法重新同步。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:24:59 -08:00
hailin f2b83650b5 fix(deploy): full-reset 添加 wallet CDC consumer group 和修复 cdc-resnapshot
- CDC_CONSUMER_GROUPS 添加 auth-service-cdc-group-wallet
- cdc_resnapshot 同时停止 auth-service(之前只停了 contribution-service)
- cdc_resnapshot 完成后同时启动 auth-service

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:12:45 -08:00
hailin 6f01892945 fix(debezium): identity connector 添加 wallet_addresses 表
Debezium identity-connector 之前只捕获 user_accounts 表,
导致 auth-service 的 WalletAddressCdcConsumer 收不到任何事件。
添加 public.wallet_addresses 到 table.include.list。

需要重新注册 connector 才能生效。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:06:42 -08:00
hailin dc51c19dfd fix(mining-admin): 修复 APK 解析 adbkit-apkreader 导入方式
adbkit-apkreader 是 CJS 模块,直接导出 class(module.exports = ApkReader),
不存在 .default 属性。将 dynamic import 改为 require 直接调用 ApkReader.open()。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 13:45:25 -08:00
hailin 3ff38ca9c2 fix(mining-admin): 添加 buildNumber 到版本检查返回结果
mining-app VersionInfo.fromJson 要求 buildNumber 字段,
CheckUpdateResult 接口和 checkUpdate 方法之前未包含该字段。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 13:29:53 -08:00
hailin 96e1fa4534 fix(mining-admin): 适配 mining-app 版本检查 API 格式
- CheckUpdateDto: current_version_code 改为 versionCode 匹配 mining-app 请求参数
- MobileVersionController: 响应格式改为 { hasUpdate, latestVersion: {...} } 匹配 mining-app 解析
- TransformInterceptor: 添加 @SkipTransform() 装饰器,移动端版本检查接口跳过响应包装

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 13:26:13 -08:00
hailin f595c6f26d fix(mining-admin): 将 upload DTO 的 changelog 改为可选
前端 upload-modal 在用户未填写更新日志时不发送 changelog 字段,
导致 DTO 校验失败返回 400。将 changelog 改为 @IsOptional(),
与前端行为一致。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 13:13:57 -08:00
hailin 4112b45b9e feat(mining-admin): 新建公开版本管理接口供 mobile-upgrade 前端使用
mining-admin-service 有全局 AdminAuthGuard,导致 mobile-upgrade 前端
调用版本接口返回 401。新建 UpgradeVersionController (@Public) 作为
独立的公开接口,路径为 /api/v2/upgrade-versions,不影响现有需认证的
/api/v2/versions 接口。前端 apiPrefix 同步更新。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 12:53:29 -08:00
hailin 7e289430ae feat(auth-service): CDC 同步 wallet_addresses 并提供内部 API
- auth-service: 新增 SyncedWalletAddress Prisma model 和 migration
- auth-service: 新增 WalletAddressCdcConsumer 消费 1.0 钱包地址变更
- auth-service: 新增 InternalController 提供 kava 地址查询 API
- trading-service: IdentityClient 改调 auth-service 内部 API
- docker-compose.2.0.yml: 添加 CDC_TOPIC_WALLET_ADDRESSES 和 AUTH_SERVICE_URL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 12:20:23 -08:00
hailin 83fa6bec74 feat(c2c): 支持绿积分(GREEN_POINTS)作为默认支付方式
- 后端 paymentMethod 字段从 PostgreSQL 枚举改为 String,支持逗号分隔多种支付方式
- 添加数据库迁移将 C2cPaymentMethod 枚举列转为 TEXT 类型
- DTO 验证改为 @IsString() 接受 GREEN_POINTS 及其组合
- 前端保持发送完整的支付方式列表(含 GREEN_POINTS)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:39:00 -08:00
hailin 263f1ecf8e feat(c2c): 卖单自动获取账户ID和Kava地址,移除手动输入
后端创建卖单时自动从 identity-service 获取卖家 Kava 地址并存入订单,
前端发布页面自动展示 accountSequence(只读),不再需要手动输入1.0系统ID。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:08:56 -08:00
hailin 776d181ef3 fix(trading-service): 修复P2P转账API响应双重包装问题
- 移除controller中的手动包装,由TransformInterceptor统一处理
- 前端增加类型检查防止解析错误

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 09:11:59 -08:00
hailin 28c73136a8 fix(trading-service): 修复P2P转账历史查询参数解析
确保 page 和 pageSize 是有效数字,避免 skip: NaN 错误

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 09:00:28 -08:00
hailin dcc83b9f79 fix(trading-service): 使用Docker容器名调用auth-service
改为使用 auth-service:3024 替代 IP 地址

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 08:56:24 -08:00
hailin 8b459dd33f fix(trading-service): 修复P2P转账AUTH_SERVICE_URL默认值
默认值从localhost改为内网IP,解决Docker环境中调用auth-service失败的问题

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 08:49:54 -08:00
hailin 40389fcfc7 feat(trading-service, mining-admin-web): 支持在管理后台配置做市商钱包地址
- 后端: 在 UpdateConfigDto 和 updateConfig 方法中添加 kavaWalletAddress 字段
- 前端: 在充值对话框中添加钱包地址配置输入框

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 07:53:04 -08:00
hailin 7a8a3a8fd1 feat(trading-service): 初始化做市商时自动读取环境变量配置钱包地址
- 从 FUSDT_MARKET_MAKER_ADDRESS 环境变量读取做市商钱包地址
- 初始化时自动设置 kavaWalletAddress
- 如果做市商已存在但钱包地址为空,也会从环境变量更新

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 07:31:16 -08:00
hailin 812b127ace fix(trading-service): 添加缺失的数据库字段迁移
Schema 中有但 migration 中缺失的字段:
- market_maker_configs: kava_wallet_address, mpc_username
- c2c_orders: seller_kava_address, bot_purchased, payment_tx_hash

这些字段缺失导致 500 错误:
"The column `market_maker_configs.kava_wallet_address` does not exist"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 07:20:21 -08:00
hailin b4afc4615c fix(mining-admin-service): 修复 APK 解析和添加 AppVersion migration
1. 修复 package-parser.service.ts:
   - ApkReader.open 需要文件路径,改为先写入临时文件再解析
   - 添加 fs/path/os 模块导入
   - 完成后自动清理临时文件

2. 添加 AppVersion 表 migration:
   - 创建 Platform 枚举类型 (ANDROID, IOS)
   - 创建 app_versions 表
   - 添加必要索引

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 22:24:45 -08:00
hailin fd64903841 fix(mining-admin-service): 添加 adbkit-apkreader 类型声明
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 22:21:18 -08:00
hailin 8314dda670 fix(mining-admin-service): 更新 package-lock.json
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 22:17:01 -08:00
hailin 4ce43c20cc fix(mining-admin-service): 添加 APK/IPA 解析依赖包
添加版本管理所需的包解析依赖:
- adbkit-apkreader: 解析 Android APK 文件
- jszip: 解压 iOS IPA 文件
- plist: 解析 iOS Info.plist 文件
- @types/plist: TypeScript 类型声明

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 22:15:43 -08:00
hailin edc0ea46c9 fix: 修复 mining-blockchain-service Kafka consumer group 冲突
- mining-blockchain-service 使用独立的 consumer group ID,避免与 blockchain-service 冲突
- withdrawal-event-consumer: blockchain-service-withdrawal-events -> mining-blockchain-service-withdrawal-events
- mpc-event-consumer: blockchain-service-mpc-events -> mining-blockchain-service-mpc-events
- deposit-ack-consumer: blockchain-service-deposit-acks -> mining-blockchain-service-deposit-acks
- 更新 docker-compose.yml 和 kafka.config.ts 的默认配置

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 22:05:55 -08:00
hailin 76d566d145 feat: 集成 mining-app 升级和遥测功能,扩展 mobile-upgrade 支持多应用
## mining-app (Flutter)
- 新增 updater 模块: 版本检查、APK下载(断点续传+SHA256校验)、安装
- 新增 telemetry 模块: 事件上报、会话追踪、心跳检测(DAU统计)
- 集成原生 MethodChannel 实现 APK 安装
- 在关于页面添加"检查更新"功能入口

## mining-admin-service (NestJS)
- 新增版本管理 API (/api/v2/versions)
- 实现 DDD 架构: Entity, Value Objects, Repository
- 支持 APK/IPA 解析 (需安装 adbkit-apkreader, jszip, plist)
- 支持文件上传和静态文件服务

## mobile-upgrade (Next.js)
- 扩展支持多后端: 榴莲 App (admin-service) + 股行 App (mining-admin-service)
- 添加应用选择器 UI
- 配置独立的 API 端点

## 修复
- 移除未使用的 _apiBaseUrl 字段 (Flutter)
- 替换废弃的 WillPopScope 为 PopScope (Flutter)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 20:03:26 -08:00
hailin 219fb7bb69 fix(mining-blockchain): 移除旧的 MARKET_MAKER_* 变量名引用
- main.ts: 使用 EUSDT/FUSDT_MARKET_MAKER_* 验证配置
- blockchain.config.ts: 使用 eusdtMarketMaker/fusdtMarketMaker 配置
- market-maker-deposit-detection.service.ts: 每种代币使用独立的做市商钱包地址

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 19:20:48 -08:00
hailin 3b95a8a332 feat(mining-blockchain): 支持 eUSDT 和 fUSDT 独立做市商钱包
- 新增 EUSDT_MARKET_MAKER_USERNAME/ADDRESS 配置
- 新增 FUSDT_MARKET_MAKER_USERNAME/ADDRESS 配置
- mpc-signing.client.ts: 分离 eUSDT 和 fUSDT 做市商签名方法
- erc20-transfer.service.ts: 根据代币类型选择对应钱包转账
- transfer.controller.ts: 更新余额查询和状态接口

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 19:05:15 -08:00
hailin aa33803d08 fix(mining-blockchain): 修正做市商钱包配置项顺序
统一 USERNAME 在前,ADDRESS 在后的格式,与 HOT_WALLET 保持一致

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 18:33:16 -08:00
hailin cfdcd9352a feat(mining-blockchain-service): 支持做市商独立MPC钱包签名
- MpcSigningClient 支持两个钱包: C2C Bot 和做市商
  - HOT_WALLET_USERNAME/ADDRESS: C2C Bot 热钱包
  - MARKET_MAKER_MPC_USERNAME/WALLET_ADDRESS: 做市商钱包
- Erc20TransferService 新增 transferTokenAsMarketMaker() 方法
- eUSDT/fUSDT 转账使用做市商钱包签名和转账
- 新增 /transfer/market-maker/status 状态检查接口

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 18:27:09 -08:00
hailin 4283a369ae fix(mining-blockchain-service): 修复Redis DB配置超出范围问题
- 将 REDIS_DB 从 16 改为 8(Redis 仅支持 0-15)
- 更新 .env.example 添加做市商钱包配置说明
- 添加 eUSDT/fUSDT 合约地址配置
- 添加区块扫描配置项

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 18:16:38 -08:00
hailin 58feec255d feat(market-maker): 实现做市商区块链充提功能
- 扩展 mining-blockchain-service 支持 eUSDT/fUSDT 转账
- 添加 trading-service 区块链提现 API(自动回滚失败交易)
- 前端支持中心化和区块链充提两种模式(Tab切换)
- 区块链充值显示钱包地址和二维码
- 区块链提现支持输入目标地址直接转账

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 17:56:15 -08:00
hailin 94f9e7d5b5 fix(trading-service): 使用事务确保成交时账户余额更新的原子性
## 问题描述

用户 D25122700015 的卖单成交后,订单状态变为 FILLED,成交记录存在,
但 frozenShares 未释放,cashBalance 未增加,交易流水缺少 SELL 记录。

## 根本原因

`tryMatch` 方法中的数据库操作没有使用事务:
1. trade.create - 单独提交
2. orderRepository.save - 单独提交
3. accountRepository.save(buyerAccount) - 单独提交
4. accountRepository.save(sellerAccount) - 可能因前面异常而跳过

如果步骤 1-3 成功但步骤 4 失败,会导致:
- 成交记录存在 ✓
- 订单状态 FILLED ✓
- 买方账户正常 ✓
- 卖方账户未更新 ✗

## 修复方案

使用 Prisma 事务包装所有关键操作,确保原子性:
1. 创建成交记录
2. 更新买单状态
3. 更新卖单状态(含销毁信息)
4. 更新买方账户(扣除冻结现金,增加积分股)
5. 更新卖方账户(扣除冻结积分股,增加现金)
6. 记录交易流水

任何一步失败,整个事务回滚。

## 受影响用户

- D25122700015: 订单 OMKXYTXS6KKC3A6
- 成交记录: TMKXYTXXH8CYQZ7
- 需要手动修复现有数据

## 回滚方法

git revert <此commit>

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 17:20:31 -08:00
hailin 1974c43eba feat(market-maker): 实现做市商区块链充值监控功能
- mining-blockchain-service:
  - 添加 MarketMakerDeposit 和 MarketMakerBlockCheckpoint 表
  - 添加 eUSDT/fUSDT 代币合约配置
  - 实现做市商钱包充值检测服务
  - 添加启动时配置验证和错误日志
  - 发布充值确认事件到 Kafka

- trading-service:
  - 添加做市商充提记录表 (MarketMakerDeposit, MarketMakerWithdraw)
  - 添加 Kafka 消费者监听充值确认事件
  - 实现充值自动入账和流水记录

- 部署配置:
  - 更新 docker-compose 添加新环境变量
  - 更新 deploy-mining.sh 添加 blockchain 服务

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 17:13:41 -08:00
hailin 042a52550b feat(c2c): 实现C2C Bot自动交易系统
- 创建独立的 mining-blockchain-service 服务 (基于 blockchain-service)
- 添加 dUSDT 转账接口供 C2C Bot 调用
- 实现 C2cBotService 自动购买卖单
- 实现 C2cBotScheduler 每10秒扫描待处理卖单
- 添加 BlockchainClient 和 IdentityClient 客户端
- 更新 C2cOrder 模型添加 Bot 购买相关字段
- 使用 MPC 热钱包签名交易

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 07:10:25 -08:00
hailin cec98e9d3e feat(contribution): 添加定时任务补发未完全解锁的贡献值
每10分钟扫描已认种但解锁状态不完整的账户,检查其直推用户认种情况,
若满足新的解锁条件则自动补发层级贡献值和奖励档位。

- 添加 findAccountsWithIncompleteUnlock 查询方法
- 添加 findPendingLevelByAccountSequence 和 claimLevelRecords 方法
- 实现 processBackfillForAccount 和 claimLevelContributions 补发逻辑
- 添加 processContributionBackfill 定时任务(每10分钟执行)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 06:25:57 -08:00
hailin 2597d0ef46 feat: 实现P2P转账功能及前端资产页面优化
- trading-service: 添加P2pTransfer模型和P2P转账API
- auth-service: 添加用户手机号查询接口用于转账验证
- frontend: 修复资产页面冻结份额显示和转账页面余额字段
- frontend: 添加P2P转账记录页面

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 06:25:42 -08:00
hailin 37d3300b17 fix(contribution-service): CDC planting_orders 阶段按 order_id 排序处理
## 问题背景

用户 D25122700018 的层级已解锁(unlocked_level_depth=5),但缺少 TEAM_LEVEL 算力记录。
其下级用户 D25122700019 的团队算力被错误地分配给了 D25122700015(level 2)而非 D25122700018(level 1)。

## 根本原因分析

1. 源系统数据顺序正确:
   - D25122700018: order_id=55, created_at=2026-01-09 11:57:01 (先认种)
   - D25122700019: order_id=57, created_at=2026-01-09 12:00:38 (后认种)

2. Kafka 消息顺序错误:
   - D25122700019: offset=732, synced_at=10:15:32 (先处理)
   - D25122700018: offset=798, synced_at=10:15:41 (后处理)

3. 原因:Debezium snapshot 按 PostgreSQL 物理存储顺序(heap order)读取数据,
   而非按主键顺序。即使 topic 只有 1 个分区,消息顺序仍然错误。

4. 后果:当处理 D25122700019 的认种时,D25122700018 的 unlocked_level_depth 还是 0,
   导致 D25122700019 的 TEAM_LEVEL 算力跳过 level 1 直接分配给 level 2。

## 解决方案

对 planting_orders 阶段实现"收集-排序-处理"模式:
1. 先收集所有消息到内存数组(不立即处理)
2. 按 order_id(源系统主键)升序排序
3. 再按排序后的顺序逐条处理

这确保上游用户的认种记录先于下游用户处理,避免算力分配错误。

## 受影响用户案例

- 上游用户: D25122700018 (order_id=55)
- 下游用户: D25122700019 (order_id=57, 58, 59)
- 错误分配: D25122700019 的 TEAM_LEVEL 给了 D25122700015 而非 D25122700018

## 回滚方法

如需回滚此修改,将 consumePhaseToEnd 方法中的判断条件改为 false:
```typescript
const needsSorting = false; // 原: phase.tableName === 'planting_orders'
```
或直接 revert 此 commit。

## 风险评估

- 业务逻辑完全不变,只改变处理顺序
- user_accounts 和 referral_relationships 阶段保持原有逻辑
- 内存开销可控(10000 条记录约 5MB)
- 排序开销可忽略(O(n log n))

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 03:41:14 -08:00
hailin e9dea69ee9 feat(batch-mining): 动态获取批量补发计算起始日期
重构批量补发功能,将硬编码的起始日期(2025-11-08)改为从 Excel 数据中
动态获取,提高计算的准确性和灵活性。

后端改动 (mining-service):
- 新增 DEFAULT_MINING_START_DATE 常量作为找不到有效数据时的默认值
- 新增 getCalculatedStartDate() 方法:从批次1用户的 miningStartDate 中
  获取最早日期
- 新增 parseDate() 方法:支持解析 2025.11.8、2025-11-08、2025/11/8 格式
- 修改 buildMiningPhases() 方法:新增 startDateStr 参数,不再硬编码日期
- 修改 preview/execute 方法:在返回结果中包含 calculatedStartDate 字段

前端改动 (mining-admin-web):
- 更新 BatchPreviewResult 接口,新增 calculatedStartDate 字段
- 预览结果描述中显示计算起始日期(蓝色高亮)
- 确认对话框中新增"计算起始日期"行

降级策略:
- 若批次1用户不存在或日期均无效,自动使用默认日期 2025-11-08

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 02:01:40 -08:00
hailin 0009a9358d fix(mining-admin-service): 修正调用 mining-service admin API 路径
mining-service 的 AdminController 路由前缀改为 mining/admin 后,
mining-admin-service 中调用的路径也需要相应修改

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 02:15:12 -08:00
hailin ab320083f7 fix(mining-service): 修复批量补发记录分页参数类型问题
Query 参数是字符串类型,需要显式转换为数字

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 02:05:16 -08:00
hailin c7f7c10d59 fix(mining-service): 修正 AdminController 路由前缀
将 AdminController 路由从 /admin 改为 /mining/admin,
以匹配 Kong 网关路由 /api/v2/mining

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 01:51:11 -08:00
hailin 134e45e0bf fix(mining-admin-service): 审计日志失败不影响批量补发返回结果
批量补发实际操作完成后,即使审计日志创建失败也应返回成功响应。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 00:57:00 -08:00
hailin 8a47659c47 feat(batch-mining): 按阶段创建补发记录并添加用户查询功能
- 修改BatchMiningRecord表结构,添加phase和daysInPhase字段
- 修改execute函数,按阶段为每个用户创建记录
- 添加用户批量补发记录查询API
- mining-admin-web用户详情页添加"批量补发"Tab

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 00:30:06 -08:00
hailin f44af3a2ed fix(batch-mining): 修正grandTotalAmount重复累加问题
用户可能在多个批次中出现,之前按批次累加batchTotalAmount会导致
同一用户的收益被重复计算。改为直接累加所有用户的amount(去重)。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 00:04:35 -08:00
hailin 18e9749ad8 fix(batch-mining): 修正总天数计算逻辑
- 总挖矿天数 = 从2025-11-08到今天的自然天数
- 最后阶段天数 = 总天数 - 前面各阶段天数之和
- 不再累加preMineDays作为总天数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:46:27 -08:00
hailin d47276a460 fix(batch-mining): 添加详细日志追踪阶段划分和总天数计算
- 添加更清晰的阶段划分注释说明
- 添加日志打印最后批次preMineDays=0时改为1天的情况
- 添加预期总金额日志用于验证计算正确性

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:44:10 -08:00
hailin 0adc4c8c26 fix(batch-mining): 最后批次preMineDays=0时改为1天
最后一个批次即使 preMineDays=0,也要算1天(所有人一起挖1天生成收益)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:37:35 -08:00
hailin d98e22f151 fix(batch-mining): 移除多余的最后阶段
根据需求:总天数 = 所有批次的 preMineDays 之和
- 阶段1: 只有第一批,分配第一批的 preMineDays 天
- 阶段2: 第一批+第二批,分配第二批的 preMineDays 天
- 依次类推...

没有额外的"最后阶段",不再使用 maxTotalMiningDays

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:35:50 -08:00
hailin c90d88a047 Revert "fix(batch-mining): 修正阶段划分逻辑"
This reverts commit 9e9c791283.
2026-01-21 23:34:12 -08:00
hailin 9e9c791283 fix(batch-mining): 修正阶段划分逻辑
preMineDays 表示该批次比最后批次提前多少天开始挖矿
阶段天数 = 当前批次的preMineDays - 下一批次的preMineDays(差值)

例如:批次1(3天)、批次2(2天)、批次3(1天)、批次4(0天)
- 阶段1:只有批次1,持续 3-2=1 天
- 阶段2:批次1+2,持续 2-1=1 天
- 阶段3:批次1+2+3,持续 1-0=1 天
- 最后阶段:所有批次一起挖剩余天数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:33:58 -08:00
hailin 2358b3ea17 fix(batch-mining): 修复重复用户计算问题
- 添加 userBatchContributions 按用户-批次跟踪算力
- 修复阶段计算时同一用户被重复计算的问题
- 修复输出结果时同一用户金额被重复累加的问题
- 使用 processedInPhase Set 避免同一阶段重复处理同一用户

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:24:03 -08:00
hailin f14ad0b7ad fix(batch-mining): 修正补发计算逻辑
- 去掉虚构的'全网算力'概念
- 每天固定分配70%产出给参与用户
- 用户收益 = 每日产出 × 70% × 天数 × (用户算力/当前参与总算力)
- 总补发金额固定为: 日产出 × 70% × 总天数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:08:55 -08:00
hailin 702fa937e8 fix(batch-mining): 修正阶段划分逻辑
- preMineDays 是该批次加入后挖矿的天数,不是差值
- 批次1的preMineDays=3 → 批次1先独挖3天
- 批次2的preMineDays=2 → 批次1+2一起挖2天
- 批次3的preMineDays=1 → 批次1+2+3一起挖1天
- 最后所有批次一起挖剩余天数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:29:34 -08:00
hailin 8b8d1f7d16 Revert "fix(batch-mining): 简化计算逻辑"
This reverts commit 4dcbe38309.
2026-01-21 21:17:00 -08:00
hailin 4dcbe38309 fix(batch-mining): 简化计算逻辑
- 移除分阶段计算,改用简单公式
- 用户收益 = (用户算力/全网算力) × 每日产出 × 天数
- 全网算力 = 用户算力 / 0.7

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:16:14 -08:00
hailin 97b3a20a7c fix(batch-mining): 修正70%比例计算逻辑
- 移除 PERSONAL_RATE,避免70%被乘两次
- 用户算力 = 棵数 × 22617(不再乘70%)
- 全网算力 = 用户算力 / 0.7(70%体现在这里)
- 预期结果:(1000000/365/2)*70%*74 = 70958.90411

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:07:35 -08:00
hailin e79d42db61 fix(batch-mining): 修复计算逻辑,批量补发用户只占全网70%
- 添加 BATCH_USERS_NETWORK_RATIO 常量(0.70)
- 计算全网算力时:实际全网算力 = 用户算力 / 0.7
- 修正预期结果约为 70,958 而非 104,656

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 20:58:42 -08:00
hailin 16daa7403c fix(mining-admin): 修正Excel列索引
Excel实际格式是:
- 索引0: 序号
- 索引1: 注册ID
- 索引2: 认种量(棵)
- 索引3: 挖矿开始时间
- 索引4: 批次
- 索引5: 授权提前挖的天数
- 索引6: 备注

之前代码从索引0读取用户ID是错误的,现在修正为从索引1开始读取。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:58:17 -08:00
hailin ca5de3add1 debug: 添加原始Excel数据日志 2026-01-21 19:46:31 -08:00
hailin 390cc3131d fix(contribution): 修复T2/T3补发记录缺少treeCount和baseContribution
补发奖励时从SyncedAdoption查询原始认种数据,
确保补发记录包含正确的棵数和基础贡献值。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:38:18 -08:00
hailin e4c320970f fix(batch-mining): 重构分阶段挖矿计算逻辑
核心修改:
1. 正确理解 preMineDays 的含义:该批次比下一批次提前的天数
2. 新增 totalMiningDays:从挖矿开始日期到今天的总天数
3. 分阶段计算收益:
   - 阶段1: 批次1独挖 (preMineDays1 - preMineDays2) 天
   - 阶段2: 批次1+2共挖 (preMineDays2 - preMineDays3) 天
   - 阶段3: 批次1+2+3共挖 (preMineDays3 - 0) 天
   - 最终阶段: 所有批次共挖 (totalMiningDays - 已用天数) 天
4. 每个阶段按当时的全网算力比例分配收益

示例:
- 批次1 preMineDays=3,批次2 preMineDays=2,批次3 preMineDays=1
- totalMiningDays=74(从11.8到1.21)
- 阶段1: 批次1独挖1天 (3-2=1)
- 阶段2: 批次1+2共挖1天 (2-1=1)
- 阶段3: 批次1+2+3共挖1天 (1-0=1)
- 阶段4: 所有批次共挖71天 (74-3=71)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 18:56:45 -08:00
hailin af95f8da0c fix(mining-admin): 根据挖矿开始时间自动计算挖矿天数
之前错误地从Excel第6列读取preMineDays,但该列为空。
现在根据"挖矿开始时间"到今天自动计算实际挖矿天数。

修改内容:
- 修正Excel列索引(用户ID在第1列,不是第2列)
- 解析日期支持多种格式(2025.11.8, 2025-11-08, 2025/11/8)
- 自动计算从挖矿开始日期到今天的天数作为preMineDays

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 18:50:46 -08:00
hailin 30a82f09f3 fix(mining-admin): 解包 mining-service 响应的 TransformInterceptor 包装
mining-service 使用 TransformInterceptor 将所有响应包装为 { success, data, timestamp } 结构,
mining-admin-service 需要从 result.data 中提取实际数据。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:26:56 -08:00
hailin a02813a8ea fix(batch-mining): 修复 mining-admin-service 调用 mining-service API 路径
mining-service 的路由是 /api/v2/admin/batch-mining/...
但 mining-admin-service 调用时缺少 /api/v2 前缀导致 404

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:12:32 -08:00
hailin 7a4f5591b7 feat(batch-mining): 添加详细的调试日志
- mining-service batch-mining.service.ts: 添加所有方法的详细日志
- mining-admin-service batch-mining.service.ts: 添加 HTTP 请求和响应日志
- mining-admin-service batch-mining.controller.ts: 添加控制器层日志
- frontend batch-mining page.tsx: 添加前端 console.log 日志

便于调试部署后的 404 等问题

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 05:49:04 -08:00
hailin 71151eaabf feat(mining): 添加批量补发挖矿功能
- 新增批量补发服务和API (mining-service)
  - 支持按批次累积计算全网算力
  - 用户算力 = 认种棵数 × 22617 × 70%
  - 补发金额 = (用户算力/全网算力) × 每秒分配量 × 天数 × 86400
  - 防重复执行机制(只能执行一次)

- 新增文件上传和批量补发API (mining-admin-service)
  - 支持上传 Excel 文件解析
  - 预览和执行两步操作
  - 审计日志记录

- 新增批量补发页面 (mining-admin-web)
  - Excel 文件上传
  - 按批次预览计算结果
  - 执行确认对话框

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 04:59:13 -08:00
hailin f7dbe2f62b refactor(contribution): 合并所有迁移到 0001_init
- 将 0002_add_soft_delete 的 deleted_at 字段合并到 0001_init
- 删除 0002_add_soft_delete_to_system_contribution_records 目录
- 现在只保留一个初始化迁移文件

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 04:31:52 -08:00
hailin 21c6c25f7c refactor(contribution): 合并 source_type 迁移到 0001_init
将 0003_add_source_type 迁移合并到 0001_init/migration.sql

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 04:28:14 -08:00
hailin e7260be219 feat(contribution): 添加系统账户算力来源类型字段
- 添加 sourceType 字段区分算力来源类型:
  - FIXED_RATE: 固定比例分配(OPERATION 12%、PROVINCE 1%、CITY 2%)
  - LEVEL_OVERFLOW: 层级溢出归总部(上线未解锁该级别)
  - LEVEL_NO_ANCESTOR: 无上线归总部(该级无上线)
  - BONUS_TIER_1/2/3: 团队奖励未解锁归总部
- 添加 levelDepth 字段记录层级深度(1-15级)
- 更新前端表格显示来源类型列

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 04:23:50 -08:00