hailin
80e3fdb7e0
fix(admin-service): 修复合同服务调用 planting-service 端口和路径错误
...
- 端口从 3002 改为 3003(与 planting-service 实际端口一致)
- API 路径添加 /api/v1 前缀(planting-service 有全局前缀)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 23:20:26 -08:00
hailin
6845ad4a0f
fix(contracts): 移除控制器路径中的重复 v1 前缀
...
全局前缀已是 api/v1,控制器路径应为 admin/contracts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 23:12:34 -08:00
hailin
0e058caa28
fix(contracts): Prisma JSON 字段使用 undefined 替代 null
...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 23:02:02 -08:00
hailin
05e2c29f37
chore(admin-service): 更新 package-lock.json 添加 archiver/axios 依赖
...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 22:58:18 -08:00
hailin
1bb12783db
fix(contracts): 修复合同状态枚举 EXPIRED -> UNSIGNED_TIMEOUT
...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 22:55:06 -08:00
hailin
86461a052d
feat(contracts): 合同管理功能 - 查询/下载/批量打包
...
新增功能:
- 合同列表查询(支持省市、状态、时间筛选)
- 单个合同 PDF 下载(支持断点续传)
- 批量下载 ZIP 打包(异步任务处理)
- 增量下载(基于上次下载时间)
- 用户详情页合同 Tab
后端:
- planting-service: 内部合同查询 API
- admin-service: 合同管理控制器、服务、批量下载 Job
- 新增 contract_batch_download_tasks 表
前端:
- 新增独立合同管理页面 /contracts
- 用户详情页新增合同信息 Tab
- 侧边栏新增合同管理入口
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 22:50:17 -08:00
hailin
5bacd21840
feat(mobile-app): 为3个主导航页面添加下拉刷新功能
...
- TradingPage (兑换): 添加 RefreshIndicator,刷新时重新加载钱包和收益数据
- RankingPage (龙虎榜): 添加 RefreshIndicator,刷新时 invalidate leaderboardStatusProvider
- 列表视图和待开启状态视图均支持下拉刷新
- MiningPage (监控): 使用 LayoutBuilder + IntrinsicHeight 模式实现
- 刷新时并行加载用户数据、授权数据和钱包状态
注:ProfilePage 已有完整的下拉刷新实现,无需修改
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 21:50:43 -08:00
hailin
a1aba14ccf
feat(trade-password): 实现卖出交易的支付密码验证功能
...
## 后端改动
### auth-service
- user.aggregate.ts: 添加支付密码相关方法 (setTradePassword, verifyTradePassword, hasTradePassword)
- trade-password.service.ts: 新建支付密码业务逻辑服务
- trade-password.controller.ts: 新建支付密码 REST API (status/set/change/verify)
- user.repository.ts: 添加 tradePasswordHash 字段的持久化
- schema.prisma: 添加 trade_password_hash 字段
- migration 0003: 添加支付密码字段迁移
### trading-service
- audit-ledger.service.ts: 新建审计分类账服务 (Append-Only设计,仅INSERT)
- schema.prisma: 添加 AuditLedger 模型和 AuditActionType 枚举
- migration 0008: 添加审计分类账表迁移
## 前端改动 (mining-app)
### 新增页面/组件
- trade_password_page.dart: 支付密码设置/修改页面 (6位数字)
- trade_password_dialog.dart: 交易时的支付密码验证弹窗
### 功能集成
- trading_page.dart: 卖出时检查支付密码
- 未设置: 提示用户跳转设置页面
- 已设置: 弹出验证弹窗,验证通过后才能卖出
- profile_page.dart: 账户设置增加"支付密码"入口
- user_providers.dart: 添加支付密码相关 Provider
- auth_remote_datasource.dart: 添加支付密码 API 调用
- api_endpoints.dart: 添加支付密码 API 端点
- routes.dart/app_router.dart: 添加支付密码页面路由
## 安全设计
- 支付密码独立于登录密码 (6位纯数字)
- 审计分类账采用链式哈希保证完整性
- 所有敏感操作记录不可变审计日志
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 18:12:39 -08:00
hailin
1c621c32ec
feat(mobile-app): 暂时隐藏自助申请授权页面的"省团队"选项
...
- 在 _buildAuthorizationTypes() 方法中过滤掉 AuthorizationType.provinceTeam
- 现在"自助申请授权"页面只显示"社区"和"市团队"两个选项
- 原代码以注释形式保留,方便未来需要时快速恢复
- 相关枚举和后端逻辑保持不变,仅前端UI隐藏
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:46:02 -08:00
hailin
d29454fc74
feat(admin-web): 省团队收益汇总明细增加来源用户列并修复账户名称显示
...
问题描述:
1. 省团队收益汇总的详细明细中缺少收益来源用户信息
2. 账户类型显示为数字(如7440000)而不是省名称
修改内容:
1. 后端 reward-service (reward-application.service.ts)
- getRewardEntriesByType 方法返回值新增 sourceAccountSequence 字段
- 该字段表示触发此收益的用户账户序列号(来自认种用户)
2. 后端 reporting-service (reward-service.client.ts)
- RewardEntryDTO 接口新增 sourceAccountSequence 字段
3. 前端 admin-web
- system-account.types.ts: RewardEntryDTO 新增 sourceAccountSequence 字段
- system-account.types.ts: getAccountDisplayName 函数支持7开头的省团队账户
示例:7440000 → "广东省团队 (7440000)"
- SystemAccountsTab.tsx: 详细明细表格新增"来源用户"列
效果:
- 省团队收益明细现在显示:时间、账户(省名称)、来源用户、订单号、金额、状态
- 账户列显示格式:"{省名}省团队 ({账户序列号})"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:35:22 -08:00
hailin
04d3b2470a
feat(admin-web): 将USDT显示文本统一替换为"绿积分"
...
根据业务需求,将管理后台中所有面向用户显示的"USDT"文本改为"绿积分":
修改文件及内容:
1. system-transfer/page.tsx (7处)
- 错误提示: "最小划转金额为 1 USDT" → "最小划转金额为 1 绿积分"
- 余额显示: "余额: xxx USDT" → "余额: xxx 绿积分"
- 表单标签: "划转金额 (USDT)" → "划转金额 (绿积分)"
- 表单提示: "最小划转金额为 1 USDT" → "最小划转金额为 1 绿积分"
- 订单金额、详情弹窗金额、确认弹窗金额显示
2. userDetail.types.ts (2处)
- DEPOSIT_USDT: 'USDT充值' → '绿积分充值'
- USDT: 'USDT' → '绿积分'
3. users/[id]/page.tsx (1处)
- DEPOSIT_USDT: 'USDT充值' → '绿积分充值'
4. formatters.ts (1处)
- formatCurrency函数中 USDT: '积分 ' → '绿积分 '
注意:所有修改均为纯UI显示文本,不影响程序逻辑和功能。
映射对象的key保持不变,仅修改显示给用户的value值。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:29:27 -08:00
hailin
207b522754
feat(customer-service): 客服联系方式从硬编码改为后台可配置
...
将 mobile-app "联系客服" 弹窗的微信/QQ联系方式从硬编码改为
admin-web 后台动态配置,支持任意数量的联系方式管理。
## Backend (admin-service)
- 新增 Prisma 模型: ContactType 枚举(WECHAT/QQ) + CustomerServiceContact
- 新增迁移 SQL: 建表 + 2条索引 + 4条种子数据(保留现有硬编码联系方式)
- 新增双 Controller (参考 app-asset.controller.ts 模式):
- AdminCustomerServiceContactController (admin/customer-service-contacts)
GET 列表 / POST 新增 / PUT 更新 / DELETE 删除
- PublicCustomerServiceContactController (customer-service-contacts)
GET 仅返回 isEnabled=true,按 sortOrder 排序
- 注意: 公开 Controller 用 @Controller('customer-service-contacts')
避免与全局前缀 api/v1 双重叠加
## Kong 网关
- 新增路由 admin-customer-service-contacts-public
路径 /api/v1/customer-service-contacts → admin-service:3010
- Admin 端点由已有 admin-api 路由 (/api/v1/admin) 覆盖
## Admin-web
- endpoints.ts: 新增 CUSTOMER_SERVICE_CONTACTS 端点组
- customerServiceContactService.ts: CRUD 服务 (list/create/update/delete)
- settings/page.tsx: 新增"客服联系方式管理"区块
表格展示(排序/类型/标签/联系方式/启停/操作) + 内联新增/编辑表单
- settings.module.scss: contactTable / contactForm / contactFormFields 样式
## Flutter Mobile-app
- storage_keys.dart: 新增 cachedCustomerServiceContacts 缓存 key
- customer_service_contact_service.dart: API + 缓存服务
(内存5分钟TTL + SharedPreferences持久化 + 后台静默刷新)
- injection_container.dart: 注册 customerServiceContactServiceProvider
- profile_page.dart: _showCustomerServiceDialog() 从硬编码改为
动态 API 加载,contacts 为空时显示"暂无客服联系方式"占位符
## 文件清单 (4 新建 + 9 修改)
新建:
- backend/.../migrations/20260205100000_add_customer_service_contacts/migration.sql
- backend/.../controllers/customer-service-contact.controller.ts
- frontend/admin-web/src/services/customerServiceContactService.ts
- frontend/mobile-app/lib/core/services/customer_service_contact_service.dart
修改:
- backend/.../prisma/schema.prisma
- backend/.../src/app.module.ts
- backend/api-gateway/kong.yml
- frontend/admin-web/src/infrastructure/api/endpoints.ts
- frontend/admin-web/src/app/(dashboard)/settings/page.tsx
- frontend/admin-web/src/app/(dashboard)/settings/settings.module.scss
- frontend/mobile-app/lib/core/storage/storage_keys.dart
- frontend/mobile-app/lib/core/di/injection_container.dart
- frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 05:00:25 -08:00
hailin
34ba209e44
fix(app-assets): 修复公开API路径双重前缀 + Kong网关路由缺失
...
问题:移动端配置的开屏图/引导图无效
根因:
1. PublicAppAssetController 和 PublicSystemConfigController 的
@Controller('api/v1/xxx') 与 NestJS 全局前缀 api/v1 叠加,
导致实际端点为 api/v1/api/v1/xxx(双重前缀)
2. Kong 网关缺少 /api/v1/app-assets 和 /api/v1/system-config 路由
3. Flutter 端使用 /admin-service/api/v1/xxx 路径,不匹配任何 Kong 路由
修复:
- 后端:Controller 路径去掉 api/v1 前缀,由全局前缀统一添加
- Kong:新增 admin-app-assets-public 和 admin-system-config-public 路由
- Flutter:API 路径改为 /app-assets 和 /system-config/display/settings
受影响文件:
- backend/api-gateway/kong.yml (新增2条路由)
- backend/.../app-asset.controller.ts (Controller路径修正)
- backend/.../system-config.controller.ts (Controller路径修正)
- frontend/.../app_asset_service.dart (API路径修正)
- frontend/.../system_config_service.dart (API路径修正)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 04:36:53 -08:00
hailin
cba7ff590a
fix(mining-app): K线蜡烛图最小实体高度优化,消除横线"-"显示
...
问题:销毁时段(无交易)的小时K线中,open ≈ close(价差仅 ~2.8e-10),
蜡烛实体映射到像素后高度接近0,旧代码强制最小1px导致显示为横线"-"。
修复:将蜡烛实体最小高度从固定1px改为 max(bodyWidth * 0.4, 3.0)px,
即至少为蜡烛宽度的40%或3像素(取较大值),使 doji 蜡烛显示为
可辨识的小方块而非横线。有正常涨跌幅的蜡烛不受影响。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 21:31:52 -08:00
hailin
ef5ac2bf94
fix(mining-app): 价格刷新倒计时与后端销毁调度器同步
...
- 倒计时不再从页面打开时任意起点开始
- 自动计算距下一个整分钟第3秒的剩余秒数作为初始值
(销毁在每分钟第0秒执行,留3秒余量等数据库写完)
- 倒计时归零时通过 ref.invalidate 主动刷新价格数据
- 确保每次刷新都能拿到最新的销毁后价格
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 21:17:10 -08:00
hailin
abb0da36a9
feat(mining-app): 兑换页价格刷新改为60秒并显示倒计时
...
- 价格 Provider 刷新间隔从15秒改为60秒,与后端销毁调度器同步
(销毁每分钟执行一次,15秒内数据不会变化,避免无意义请求)
- 兑换页"当前积分股价值"右侧新增倒计时显示(60s→1s)
让用户直观知道下次数据刷新时间
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 21:14:16 -08:00
hailin
b639b5d499
fix(mining-app): 价格显示优化 + 涨跌幅精度再提升
...
- 兑换页顶部价格改用 formatPriceFull 显示完整零(不再用 0.0{n} 缩写)
- K线纵坐标有效数字从7位精简为4位,节省空间更简洁
- 涨跌幅精度再提升:后端 toFixed(8)→toFixed(12),前端 6位→10位小数
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:43:48 -08:00
hailin
2e91686a88
fix(mining-app): 优化页面文案与涨跌幅精度
...
- 兑换页顶部隐藏价格后方"积分值"文字,界面更简洁
- 兑换页"较上线首日"涨跌幅精度从2位小数提升至6位,每分钟销毁引起的涨幅尾数可见
- 兑换页"黑洞销毁量"文案改为"已销毁量",更直观易懂
- 贡献值页"积分股池实时余量"文案改为"100亿销毁剩余量"
- 后端 priceChangePercent 精度从 toFixed(2) 提升至 toFixed(8),支持前端高精度显示
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:23:59 -08:00
hailin
dcc46c37b6
fix(mining-app): 价格有效数字从6位调整为7位,最后2位每分钟可见变化
...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:12:15 -08:00
hailin
f5d25afab8
fix(mining-app): 价格显示有效数字从3位增加到6位
...
每分钟销毁引起的价格变化约 4.66e-12(第7位有效数字),
原来只显示3位有效数字 0.0{5}979 无法观察到变化。
改为6位后 0.0{5}979941,最后一位每1-2分钟变化一次,
用户可在兑换页面实时观察到销毁带来的价格上涨。
影响范围:formatPrice、K线图Y轴/十字线、交易记录、挖矿记录
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:09:32 -08:00
hailin
deffdab18b
fix(mobile-upgrade): 股行App版本管理API地址改为 mapi.szaiai.com
...
mobile-upgrade 部署在榴莲皇后服务器上,股行的 mining-admin-service
运行在另一台服务器(103.39.231.240),需通过 mapi.szaiai.com 域名访问。
原配置 rwaapi.szaiai.com/mining-admin 无法路由到股行服务器,导致 30s 超时。
修改: NEXT_PUBLIC_MINING_API_URL 从 rwaapi.szaiai.com → mapi.szaiai.com
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 19:04:56 -08:00
hailin
59acea33fe
feat(trading): K线图增加周/月/年周期
...
- 前端周期选项增加「周」「月」「年」
- 后端 parsePeriodToMinutes 增加 1w/1M/1y 映射
- getPeriodStart 对日历周期按自然边界对齐:
- 1w → 周一 00:00 UTC(ISO 周标准)
- 1M → 月初1日 00:00 UTC
- 1y → 年初1月1日 00:00 UTC
- 固定周期(1m~1d)仍使用 epoch 模运算,不受影响
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:42:38 -08:00
hailin
c24f383501
fix(trading): K线Y轴动态缩放 + 价格显示格式统一 + 首日涨幅修复
...
- K线图Y轴改为只基于可见K线计算范围,实现动态缩放(类似TradingView)
- 价格显示统一使用 0.0{n}xxx 格式替代科学计数法,覆盖全局 formatPrice、
K线图、交易记录页、挖矿记录页
- 修复"较上线首日"百分比始终显示 +0.00% 的问题:getFirstSnapshot 过滤
price=0 的早期快照
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:36:26 -08:00
hailin
f13814e577
fix(mobile-app): 排名详情页隐藏敏感统计字段
...
火柴人排名详情页 (UserProfilePage) 暂时隐藏以下显示元素(代码保留,注释隐藏):
- 统计卡片:引荐数、同伴数、本人认种数(仅保留"同伴认种")
- 基本信息卡片:用户ID (accountSequence)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:41:11 -08:00
hailin
d075853a7f
feat(app-assets): 应用图片管理 — 开屏图/引导图可从 admin-web 配置
...
新增从 admin-web 后台管理开屏图(2张)和引导图(5张+标题/副标题)的完整功能链路。
移动端优先使用后台配置的远程图片,无配置或加载失败时自动回退到本地 asset。
### Backend (admin-service)
- Prisma schema 新增 AppAssetType 枚举 + AppAsset 模型 (type/sortOrder 唯一约束)
- 新增 AdminAppAssetController: 图片上传(multipart)、列表查询、元数据更新、删除
- 新增 PublicAppAssetController: 公开查询接口供移动端消费 (仅返回 isEnabled=true)
- 新增数据库 migration: 20260204100000_add_app_assets
### Admin-web
- endpoints.ts 新增 APP_ASSETS 端点组
- 新增 appAssetService.ts: list/upload/update/delete 方法
- Settings 页新增"应用图片管理"区块: 开屏图 2 卡槽 + 引导图 5 卡槽
- 每个卡槽支持: 图片上传预览、启用/禁用开关、删除、引导图额外支持标题和副标题编辑
### Mobile-app (Flutter)
- 新增 AppAssetService: 3 级缓存策略 (内存 5min TTL → SharedPreferences → 后台静默刷新)
- splash_page.dart: 支持远程开屏图 (CachedNetworkImage),fallback 到本地 asset
- guide_page.dart: 支持远程引导图+标题/副标题覆盖,fallback 到本地 asset
- 替换 2 张开屏图为新版 (1280x1826/1834, ~245KB)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:20:26 -08:00
hailin
c7978f6fb5
fix(mining-wallet-service): pool-account GET :type 改为 @Public() 允许内网服务间调用
...
mining-admin-service 通过 fetch 查询余额时无 token,@AdminOnly() 导致 401,UI 始终显示 0.00
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 09:21:39 -08:00
hailin
17ecc9954f
fix(admin-service): 认种筛选改用 PlantingOrderQueryView 实时查询
...
UserQueryView.personalAdoptionCount 预计算字段未被事件同步更新(始终为 0),
导致前端选"已认种"后查不到数据。
修复:认种数过滤(minAdoptions/maxAdoptions)不再查 UserQueryView 的
stale 字段,改为实时 groupBy 查询 PlantingOrderQueryView
(status='MINING_ENABLED'),与 getBatchUserStats 展示数据源保持一致。
- 已认种(minAdoptions>=1):accountSequence IN 有订单的集合
- 未认种(maxAdoptions=0):accountSequence NOT IN 有订单的集合
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 08:09:12 -08:00
hailin
50dc18a224
feat(admin-web): 用户管理高级筛选增加"已认种/未认种"过滤
...
在用户管理页面的"用户状态"下拉框中新增"已认种"和"未认种"两个筛选选项。
实现方式:
- 复用后端已有的 minAdoptions/maxAdoptions 查询参数
- "已认种"映射为 minAdoptions=1(personalAdoptionCount >= 1)
- "未认种"映射为 maxAdoptions=0(personalAdoptionCount = 0)
- 与原有"正常/冻结"状态筛选互斥(同一下拉框)
- 切换筛选时自动重置分页到第 1 页
后端无改动:admin-service 的 ListUsersDto 和 UserQueryRepository
已支持 minAdoptions/maxAdoptions 参数及对应的 WHERE 条件。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 07:58:24 -08:00
hailin
126169c631
fix(injection): findUnique 改为 findFirst 避免命名唯一索引类型错误
...
Prisma @@unique 单字段命名索引 uk_adoption_id 的 TypeScript 类型
与 findUnique where 输入不兼容(TS2322)。改用 findFirst + where
字段查询,走同一个唯一索引,性能相同。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 06:14:13 -08:00
hailin
1baed76d8e
fix(injection): docker-compose 添加注入钱包环境变量 + 未配置时不启用消费者
...
问题:
.env 配置了 FUSDT_INJECTION_WALLET_USERNAME 和 FUSDT_INJECTION_WALLET_ADDRESS,
但 docker-compose.2.0.yml 没有将这两个变量传入容器,导致容器内 process.env
拿不到值,Adoption Injection Consumer 启动后报错。
修复:
1. docker-compose.2.0.yml: 添加 FUSDT_INJECTION_WALLET_USERNAME/ADDRESS
和 CDC_TOPIC_CONTRIBUTION_OUTBOX 环境变量传递
2. AdoptionInjectionConsumerService: onModuleInit 检查钱包是否配置,
未配置时跳过 Kafka 连接(不浪费消费者组资源)
3. AdoptionInjectionHandler: 检查 Consumer 是否启用,未启用时不注册
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 06:08:48 -08:00
hailin
c93eeba79a
fix(injection): findUnique 使用命名唯一索引 uk_adoption_id
...
Prisma 的 @@unique 使用自定义名 "uk_adoption_id" 后,
findUnique 的 where 必须用 { uk_adoption_id: { adoptionId } }
而非 { adoptionId },否则报 PrismaClientValidationError。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 06:05:26 -08:00
hailin
8980a169ed
fix(trading): 修复做市商吃单扣款金额错误(使用交易总额而非原始数量×价格)
...
问题:
做市商吃单时,buyerPayAmount = tradeQuantity × price(原始数量×价格),
未计入销毁倍数。例如:卖出 697.81 积分股,销毁倍数 5000.88,
交易总额 = 17,615.96 积分值,但做市商只被扣了 697.81 × 0.005 = 3.49。
10% 手续费(1,761.60)反而大于做市商支出,导致做市商不减反增。
修复:
- 做市商吃单时:actualBuyerCost = sellerGrossAmount(含销毁倍数的交易总额)
- 普通用户买入时:actualBuyerCost = buyerPayAmount(原始数量×价格,不变)
- frozenCash 仍释放下单时冻结的原始金额(buyerPayAmount)
- 做市商交易流水记录 assetType=CASH + 实际支付金额
做市商吃单扣款计算(修复后):
MM 支出 = sellerGrossAmount(交易总额)
MM 手续费收入 = tradeFee(10%)
MM 净支出 = sellerReceiveAmount = 交易总额 × 90%
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 05:56:12 -08:00
hailin
000e8f7ef1
fix(trading): 修复积分股重复记账,做市商吃单积分股只进流通池
...
问题:
之前所有卖出成交时,积分股同时记入了买方账户和流通池,
导致同一笔积分股被重复计入两处(双重记账)。
修复:
- 做市商吃单时:积分股只进入流通池,不增加做市商 shareBalance
(目前不允许做市商挂卖单,做市商不需要持有积分股)
- 普通用户买入时:积分股直接进入买方账户,不再重复计入流通池
- 将 mmConfig 查询提到循环外复用,去掉循环内冗余查询
积分股流向(修复后):
做市商吃单: 卖方 -X → 流通池 +X(做市商 shareBalance 不变)
用户间交易: 卖方 -X → 买方 +X(流通池不变)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 05:47:16 -08:00
hailin
4817d92507
feat(adoption-injection): 认种自动 fUSDT 注入做市商钱包 + CDC outbox 修复
...
## contribution-service 改动
### 1. CDC Outbox 实时发布修复
- adoption-synced.handler: handleCreate/handleUpdate 在同步数据后立即写入
AdoptionSynced outbox 事件,确保 mining-admin-service 实时接收认种同步
- referral-synced.handler: 同理,写入 ReferralSynced outbox 事件
- 之前只有手动调用 /admin/adoptions/publish-all 才会创建 outbox 事件
### 2. 认种 fUSDT 注入事件
- 新增 AdoptionFusdtInjectionRequestedEvent 事件类
- 当认种状态变为 MINING_ENABLED 时触发
- 写入 outbox,topic: contribution.adoptionfusdtinjectionrequested
- payload 含: adoptionId, accountSequence, treeCount, adoptionDate, amount
- 转账金额 = treeCount × 5760 fUSDT
## mining-blockchain-service 改动
### 3. fUSDT 注入钱包 MPC 签名支持
- mpc-signing.client: 新增 FUSDT_INJECTION_WALLET_USERNAME/ADDRESS 配置
isFusdtInjectionConfigured(), signMessageAsFusdtInjection() 等方法
- erc20-transfer.service: IMpcSigningClient 接口增加注入钱包方法
新增 transferFusdtAsInjectionWallet() 转账方法(含余额检查、MPC签名、广播)
### 4. 认种注入 Kafka 消费者
- adoption-injection-consumer.service: 订阅 cdc.contribution.outbox
过滤 AdoptionFusdtInjectionRequested 事件,解析 Debezium 扁平化消息格式
- adoption-injection.handler: 处理注入事件
- 幂等性检查(已确认的跳过)
- 写入 adoption_injection_records 分类账(PROCESSING 状态)
- 从注入钱包转 fUSDT 到做市商钱包
- 成功: markConfirmed (txHash, blockNumber, gasUsed)
- 失败: markFailed (errorMessage),支持重试
- 发布 confirmed/failed Kafka 事件
### 5. 分类账持久化
- Prisma schema: 新增 AdoptionInjectionRecord 模型 (adoption_injection_records 表)
字段: adoption_id, account_sequence, tree_count, adoption_date, from/to_address,
amount, chain_type, tx_hash, block_number, gas_used, memo, status, error_message
索引: uk_adoption_id (唯一), idx_injection_account, idx_injection_status 等
- migration: 20250203000000_add_adoption_injection_records
- Repository 接口 + 实现: save, findByAdoptionId, markConfirmed, markFailed
### 6. 启动余额检查
- main.ts: 启动时异步查询注入钱包 fUSDT 余额,余额为 0 时输出警告日志
新增注入钱包配置验证
## 部署前需添加环境变量 (.env)
FUSDT_INJECTION_WALLET_USERNAME=wallet-bff20b69
FUSDT_INJECTION_WALLET_ADDRESS=0x7BDB89dA47F16869c90446C41e70A00dDc432DBB
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 05:25:56 -08:00
hailin
4a69fdd070
fix(trading): getConfig 自动从环境变量填充空的钱包地址
...
之前只有 initializeConfig 会读取 env 填充钱包地址,
getConfig 只读数据库。导致新增 eusdtWalletAddress 字段后
即使 .env 配置了地址,前端仍显示"未配置"。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 04:09:00 -08:00
hailin
2192f5e917
fix(trading): 修复迁移表名 MarketMakerConfig → market_maker_configs
...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 03:50:52 -08:00
hailin
ebe7123583
feat(market-maker): 积分股(eUSDT)和积分值(fUSDT)使用独立 MPC 钱包
...
- Prisma: MarketMakerConfig 新增 eusdt_wallet_address 字段
- 后端: 初始化/更新配置时读取 EUSDT_MARKET_MAKER_ADDRESS 环境变量
- 后端: getConfig API 返回 eusdtWalletAddress
- 前端: 积分股充值弹窗使用 eusdtWalletAddress (不再共用 kavaWalletAddress)
- 前端: 积分值充值弹窗继续使用 kavaWalletAddress (fUSDT 钱包)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 03:39:54 -08:00
hailin
38ee808239
fix(wallet): 池余额不足时跳过 Kafka 消息,避免无限重试
...
BurnConsumer 和 MiningDistributionConsumer 在池余额为 0 时抛出
Insufficient pool balance 错误导致 offset 不提交,造成无限重试。
现改为记录 warn 日志并标记事件为已处理(带 :skipped:insufficient_balance 标记)。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 03:28:34 -08:00
hailin
8cfd107a92
refactor(pool-accounts): 移除硬编码钱包名,改为从后端 API 动态获取
...
- 后端: 新增 GET /admin/pool-accounts 接口,返回从 .env 配置的池账户列表
- 前端: 新增 usePoolAccounts hook,动态渲染池账户卡片
- 前端: 提取 PoolAccountCard 子组件,消除重复代码
- 移除前端硬编码的 BURN_POOL_WALLET_NAME / MINING_POOL_WALLET_NAME 常量
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:57:40 -08:00
hailin
7972163af6
fix(docker): 移除池账户钱包硬编码默认值,改为从 .env 读取
...
所有池账户钱包配置(USERNAME/ADDRESS)不再有硬编码默认值,
必须在 .env 中配置才会生效。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:54:00 -08:00
hailin
c89c8769d9
fix(docker): 设置池账户钱包地址默认值
...
从 .env.example 获取池账户 MPC 钱包地址作为 docker-compose 默认值:
- BURN_POOL_WALLET_ADDRESS: 0xdE2932D2A25e1698c1354A41e2e46B414C46F5a1
- MINING_POOL_WALLET_ADDRESS: 0x8BC9091375ae8ef43ae011F0f9bAf10e51bC9D59
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:48:58 -08:00
hailin
a8098d801b
fix(docker): 添加池账户 MPC 钱包环境变量到 mining-blockchain-service
...
为100亿销毁池和200万挖矿池添加 BURN_POOL_WALLET_USERNAME/ADDRESS
和 MINING_POOL_WALLET_USERNAME/ADDRESS 环境变量配置。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:42:55 -08:00
hailin
a5f6b23a95
feat(pool-account): 池账户充值弹窗新增中心化充值 tab
...
与做市商管理一致,充值弹窗包含"中心化充值"和"区块链充值"两个 tab。
中心化充值直接调整池账户余额(ADJUSTMENT 类型分类账),无需区块链交易。
变更:
- wallet-service: pool-account.service 新增 centralizedDeposit 方法
- wallet-service: pool-account.controller 新增 POST /centralized-deposit
- admin-service: pool-account.controller 新增 POST /:walletName/centralized-deposit 代理
- frontend: configs.api + use-configs hook + configs page 充值弹窗 Tabs UI
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:26:31 -08:00
hailin
c51539e494
fix(docker): 补充 mining-admin-service 池账户相关环境变量
...
添加 MINING_WALLET_SERVICE_URL、MINING_BLOCKCHAIN_SERVICE_URL、
BURN_POOL_WALLET_USERNAME、MINING_POOL_WALLET_USERNAME 到
docker-compose.2.0.yml 的 mining-admin-service 配置中。
缺少这些变量导致池账户 API 的 walletName→poolType 映射为空,
返回 400 Bad Request。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:18:35 -08:00
hailin
46f85b13b0
fix(pool-account): 修复 seed.ts 覆盖池余额 + 激活挖矿前校验池余额
...
1. seed.ts upsert 的 update 子句移除 balance/targetBurn/remainingBurn,
避免重新部署时将已有池余额清零(导致 BurnConsumer 和
MiningDistributionConsumer 因余额不足崩溃)
2. activateMining 激活前检查 SHARE_POOL_A/B 余额,任一为0则阻止激活
并返回 400 错误提示先通过区块链充值
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 02:00:59 -08:00
hailin
4f5b18be48
feat(pool-account): 实现池账户区块链充值检测和提现功能
...
为100亿销毁池和200万挖矿池实现完整的区块链充值/提现流程:
- 充值:独立扫描器检测 fUSDT 转入 → Kafka 事件 → wallet-service 入账
- 提现:前端 → admin-service 代理 → blockchain-service MPC签名转账 → wallet-service 记账
mining-blockchain-service:
- 新增 PoolAccountDeposit/PoolAccountBlockCheckpoint Prisma 模型
- 新增 PoolAccountDepositDetectionService(每5秒扫描 fUSDT 充值,每30秒更新确认数)
- 扩展 MPC 签名客户端支持 burnPool/miningPool 2-of-3 门限钱包
- 扩展 ERC20TransferService 支持池账户 fUSDT 转账
- 新增 API: POST /transfer/pool-account, GET /pool-accounts/:poolType/wallet-info
- 新增 Kafka topic 映射: pool_account.deposit.confirmed → pool_account.deposits
mining-wallet-service:
- TransactionType 枚举新增 BLOCKCHAIN_DEPOSIT/BLOCKCHAIN_WITHDRAW
- Seed: SHARE_POOL_A/B 初始余额改为0(完全靠链上充值)
- PoolAccountService 新增 blockchainDeposit()/blockchainWithdraw() 方法
- 新增 PoolAccountDepositConsumer 监听 Kafka 充值确认事件(Redis+DB 双重幂等)
- 新增 POST /pool-accounts/blockchain-withdraw 内部 API
mining-admin-service:
- 新增 PoolAccountController 代理到 wallet-service + blockchain-service
- GET /admin/pool-accounts/:walletName/balance(并行查询链下余额+链上钱包信息)
- POST /admin/pool-accounts/:walletName/blockchain-withdraw(先链上转账再记账)
- 新增配置: MINING_WALLET_SERVICE_URL, MINING_BLOCKCHAIN_SERVICE_URL, 池钱包用户名
frontend (mining-admin-web):
- 池账户 API 从 tradingClient (→trading-service) 改为 apiClient (→admin-service)
- 移除未使用的 tradingClient 和 axios 依赖
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 01:34:06 -08:00
hailin
4d2bcc7568
fix(mining-admin): 池账户钱包配置移到后端 .env,前端从 API 读取
...
做市商的 kavaWalletAddress 是后端 API 返回的,池账户应该一样。
- 后端 mining-blockchain-service/.env.example: 新增
BURN_POOL_WALLET_USERNAME/ADDRESS 和
MINING_POOL_WALLET_USERNAME/ADDRESS(同做市商钱包配置模式)
- 前端 .env.production: 移除 NEXT_PUBLIC_BURN/MINING_POOL 变量
- 前端 configs/page.tsx: 钱包地址改从 API 响应
(poolAccountBalance.walletAddress) 读取,未配置时显示提示
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 00:14:38 -08:00
hailin
6dbb620e82
feat(mining-admin): 配置管理新增100亿销毁池和200万挖矿池账户
...
在配置管理页面新增两个池账户卡片,UI 风格对齐做市商管理中的
"现金余额(积分值)",仅支持区块链方式充值与提现:
- 100亿销毁池 (wallet-22fd661f, 2-of-3 门限)
地址: 0xdE2932D2A25e1698c1354A41e2e46B414C46F5a1
- 200万挖矿池 (wallet-974e78f5, 2-of-3 门限)
地址: 0x8BC9091375ae8ef43ae011F0f9bAf10e51bC9D59
具体改动:
- .env.production: 新增 BURN_POOL / MINING_POOL 钱包名和地址环境变量
- configs.api.ts: 新增 tradingClient、PoolAccountBalance 接口、
getPoolAccountBalance 和 poolAccountBlockchainWithdraw API
- use-configs.ts: 新增 usePoolAccountBalance (30s 刷新) 和
usePoolAccountBlockchainWithdraw hooks
- configs/page.tsx: 新增两个并排池账户 Card,包含余额展示、
QR 码充值弹窗、区块链提现弹窗(含 0x 地址校验)
后端需实现:
- GET /admin/pool-accounts/:walletName/balance
- POST /admin/pool-accounts/:walletName/blockchain-withdraw
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 00:02:32 -08:00
hailin
999d0389b3
refactor(trading): 价格数据源从 SharePool 切换到做市商 cashBalance
...
积分股价格公式中的"绿积分"(分子)本质上就是做市商的积分值余额,
SharePool 是多余的抽象层。此次改动将价格计算的数据源从独立的
SharePool 表切换到做市商的 TradingAccount.cashBalance。
主要变更:
- price.service.ts: 通过 PrismaService 直接读取做市商 cashBalance
作为价格公式的分子(绿积分),移除 SharePoolRepository 依赖
- asset.service.ts: getMarketOverview() 同步切换数据源
- order.service.ts: 10%交易手续费从 sharePoolRepository.feeIn()
改为 increment 回做市商的 TradingAccount,手续费自然留存在池中
- burn.service.ts: 移除 SharePool 初始化逻辑和依赖
- infrastructure.module.ts: 移除 SharePoolRepository 注册和导出
- seed.ts: 移除 SharePool 57.6亿初始化
价格公式、10%手续费扣除、销毁机制均保持不变,仅切换数据源。
SharePool 表和 repository 文件保留在磁盘上供历史数据参考。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 23:13:59 -08:00
hailin
14e70b56bb
fix(c2c-bot): 水单完成时间转换为北京时间 (UTC+8)
...
问题:水单上的完成时间显示 UTC 时间(如 03:38:40),实际北京时间为 11:38:40。
原因:toISOString() 始终返回 UTC 时间。
修复:手动加 8 小时偏移量,将 UTC 转换为北京时间后再格式化。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 19:42:13 -08:00