hailin
e99dc122ad
fix(nginx): API 请求改为代理到 Next.js 而非直连 mining-admin-service
...
nginx /api/ 直连 mining-admin-service:3023 会绕过 Next.js rewrite,
导致 /api/trading 和 /api/mining 无法路由到对应服务 (404)。
改为代理到 Next.js (3100), 由 rewrite 规则分发到各后端服务。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 01:36:55 -08:00
hailin
0b8c76f8b5
fix(mining-admin-web): Dockerfile 添加 build ARG 传入后端服务地址
...
next.config.js 的 rewrite 在 next build 时计算, Docker build 阶段
环境变量不可用导致 rewrite 使用 localhost 默认值 (容器内不可达)。
添加 ARG 将服务地址传入 build 阶段:
- NEXT_PUBLIC_API_URL -> mining-admin-service:3023
- TRADING_SERVICE_URL -> trading-service:3022
- MINING_SERVICE_URL -> mining-service:3021
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 01:32:29 -08:00
hailin
59efdb1f78
fix(mining-admin-web): 修复 API 请求超时和路由问题
...
问题:
- mining-admin-web 容器与后端服务在不同 Docker 网络, 无法通过公网 IP 回连 (hairpin NAT 失败)
- next.config.js 生产模式强制走 mapi.szaiai.com Kong 网关, 容器内无法访问
- client.ts 使用 NEXT_PUBLIC_API_URL 导致外部 URL 被 build 时内联到客户端包
- mining-service controller 有 mining/ 前缀, 直连模式 rewrite 丢失该前缀
修复:
- next.config.js: 改用 API_GATEWAY_URL 判断路由模式, 未设置则直连后端服务
- next.config.js: mining rewrite 保留 mining/ 前缀匹配 controller 路由
- client.ts: baseURL 固定为 /api, 所有请求统一走 Next.js rewrite 代理
- docker-compose.2.0.yml: 添加 TRADING_SERVICE_URL 和 MINING_SERVICE_URL 环境变量
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 01:14:19 -08:00
hailin
d9d8f69562
feat(nginx): 添加 madmin.szaiai.com nginx 配置
...
mining-admin-web 前端代理,Next.js :3100。
API 由 Next.js SSR rewrite 转发到 mapi.szaiai.com (Kong)。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 00:01:37 -08:00
hailin
6443acf34a
fix(deploy-mining): cdc-resnapshot 支持 standalone 模式远程操作 1.0 Debezium
...
standalone 模式下 source CDC connectors 在 1.0 服务器 (192.168.1.111:8084),
cdc-resnapshot 需要指向 1.0 Debezium 才能删除并重建 connector 触发全量快照。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 23:42:53 -08:00
hailin
0204f748e6
fix(debezium): outbox connector 配置支持 standalone 模式 (postgres-2)
...
- database.hostname 从硬编码 "postgres" 改为 ${DEBEZIUM_DB_HOST:-postgres}
- database.user/password 改为环境变量替换 ${POSTGRES_USER}/${POSTGRES_PASSWORD}
- standalone 模式设置 DEBEZIUM_DB_HOST=postgres-2
- shared 模式不设置,默认值 postgres 保持不变
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 23:01:45 -08:00
hailin
2a5b51aa8d
fix(deploy-mining): ensure_kafka_image 输出到 stderr 避免被 $() 捕获
...
docker pull 在 group_info=$(run_kafka_cmd ...) 内执行时,stdout 被命令替换
捕获到变量中,屏幕无任何输出导致脚本看起来卡住。
- ensure_kafka_image 输出重定向到 stderr
- full_reset 开头显式预拉取镜像
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:42:42 -08:00
hailin
0156be8d25
fix(deploy-mining): 预拉取 Kafka CLI 镜像避免 timeout 期间拉取失败
...
standalone 模式下 run_kafka_cmd 使用 docker run confluentinc/cp-kafka:7.5.0,
首次运行时镜像未缓存导致 docker pull 被 timeout 30 截断,循环重试卡住。
添加 ensure_kafka_image() 在执行命令前先确保镜像已拉取。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:36:38 -08:00
hailin
d53c2212a6
fix(deploy-mining): 修复 standalone 模式跨服务器 full-reset 卡住问题
...
- run_kafka_cmd 添加 timeout 30 防止跨服务器 Kafka 命令无限挂起
- CDC consumer offset 重置前先检查 group 是否存在,不存在则跳过
- 等待时间从 15s/20s 增加到 30s(匹配 KafkaJS 默认 sessionTimeout)
- max_retries 从 3 增加到 5,并输出实际 Kafka 错误信息
- 重试失败后 fallback 删除 consumer group(服务重启时自动重建)
- 同步修复 sync_reset() 和 full_reset() Step 3/Step 8 三处逻辑
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:33:28 -08:00
hailin
394f2529cd
fix(mining-admin-web): ensure public dir exists in Docker build
...
mkdir -p public before build so COPY --from=builder /app/public works
even without static assets.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:03:44 -08:00
hailin
ad51aa521f
fix(mining-admin-web): add public/.gitkeep to fix Docker build
...
Dockerfile COPY --from=builder /app/public fails when public dir is missing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:03:01 -08:00
hailin
88ad3ab53d
feat: 2.0 API 域名从 rwaapi.szaiai.com 迁移到 mapi.szaiai.com
...
- mining-admin-web: .env.production, next.config.js fallback URL
- mining-app: environment.dart baseUrl, update_config.dart checkUpdateUrl
- docker-compose.2.0.yml: mining-admin-service UPLOAD_BASE_URL
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 21:58:03 -08:00
hailin
981b11f746
feat(api-gateway): 添加 standalone 模式 (up2) 支持 2.0 服务与 Kong 同机部署
...
- 新增 kong-standalone.yml: 2.0 服务通过 host.docker.internal 访问本机端口
1.0 服务仍走 192.168.1.111, CORS 已添加 mapi.szaiai.com
- 新增 docker-compose.standalone.yml: compose override 添加 extra_hosts
- deploy.sh 新增 up2/sync2 命令
用法:
./deploy.sh up2 # 启动 Kong (standalone)
./deploy.sh sync2 # 重新同步 standalone 配置
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 21:44:20 -08:00
hailin
42cf189749
feat(api-gateway): 添加 mapi.szaiai.com nginx+SSL 配置和 deploy.sh nginx 子命令
...
- 新增 nginx/mapi.szaiai.com.conf: 与 rwaapi.szaiai.com 同构的 SSL 反代配置
- deploy.sh 新增 nginx install/ssl 子命令,支持一键安装 nginx+证书
- 用法: sudo ./deploy.sh nginx install mapi.szaiai.com
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 21:35:00 -08:00
hailin
ec73541fe1
refactor(mining-blockchain): 移除 mpc-service 依赖,改为 HTTP 直调 mpc-system
...
将 mining-blockchain-service 的 MPC 签名通信从 Kafka 事件驱动(经由 mpc-service 中转)
改为 HTTP 直接调用 mpc-system 的 account-service (port 4000)。
## 核心变更
### mpc-signing.client.ts (重写)
- 移除 EventPublisherService、MpcEventConsumerService 依赖和 pendingRequests Map
- 移除 OnModuleInit 中的 Kafka 事件注册
- 新增 HttpService (@nestjs/axios) + JwtService (@nestjs/jwt) 依赖注入
- 签名流程改为:
1. POST /api/v1/mpc/sign → 创建签名会话 (snake_case: username, message_hash)
2. GET /api/v1/mpc/sessions/{session_id} → 轮询结果 (每 2s, 最多 5 分钟)
- JWT 认证: 使用 MPC_JWT_SECRET (HS256) 生成 Bearer token,匹配 mpc-system 格式
- 所有公共接口不变 (signMessage, signMessageAsXxxMarketMaker, isConfigured, getXxxAddress 等)
### 删除的文件
- mpc-event-consumer.service.ts: Kafka MPC 事件消费者 (SigningCompleted/SessionFailed/KeygenCompleted)
- mpc-keygen-completed.handler.ts: Keygen 地址派生处理器 (不再由此服务处理)
### 模块更新
- infrastructure.module.ts: 移除 MpcEventConsumerService,新增 JwtModule.register({})
- kafka/index.ts: 移除 mpc-event-consumer.service 导出
- event-handlers/index.ts: 移除 mpc-keygen-completed.handler 导出
### 部署配置
- docker-compose.2.0.yml: 新增 MPC_ACCOUNT_SERVICE_URL 和 MPC_JWT_SECRET 环境变量
- deploy-mining.sh: standalone 模式新增 export MPC_ACCOUNT_SERVICE_URL (默认 http://192.168.1.111:4000 )
## 不受影响的部分
- Erc20TransferService / MpcTransferInitializerService 调用方式不变
- EventPublisherService (用于其他事件) 不变
- WithdrawalEventConsumerService 不变
- mpc-system 本身零修改
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 20:53:35 -08:00
hailin
c657bf6e2b
revert: 撤回 mpc-service HTTP 调用方案,改为直接调用 mpc-system
...
Revert "fix(deploy): export MPC_SERVICE_URL in standalone mode"
Revert "refactor(mining-blockchain): replace Kafka MPC signing with HTTP direct calls"
将改为直接调用 mpc-system (Go TSS 后端) 的 API,跳过 mpc-service 中间层。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 20:33:39 -08:00
hailin
3102f3e7fb
fix(deploy): export MPC_SERVICE_URL in standalone mode
...
In standalone mode, mpc-service runs on the 1.0 server (192.168.1.111),
not in the local Docker network. The default docker-compose value
http://mpc-service:3006 won't resolve. Export MPC_SERVICE_URL pointing
to the 1.0 server's IP so mining-blockchain-service can reach it.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 20:30:44 -08:00
hailin
1106a40ff1
refactor(mining-blockchain): replace Kafka MPC signing with HTTP direct calls
...
Remove Kafka event-driven MPC signing (publish/consume pattern) and replace
with HTTP POST + polling to mpc-service, matching identity-service approach.
- Rewrite mpc-signing.client.ts: POST /api/v1/mpc/sign + poll status
- Delete mpc-event-consumer.service.ts (no longer needed)
- Delete mpc-keygen-completed.handler.ts (keygen handled elsewhere)
- Add MPC_SERVICE_URL env var to docker-compose.2.0.yml
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 20:28:26 -08:00
hailin
0d47fadf59
feat(kafka): add EXTERNAL listener on port 9093 for LAN access
...
Add a third Kafka listener (EXTERNAL://0.0.0.0:9093) so that
2.0 standalone services on other servers (e.g. 192.168.1.10) can
connect to 1.0's Kafka at 192.168.1.111:9093.
Listeners now:
- PLAINTEXT (kafka:29092) - internal Docker network
- PLAINTEXT_HOST (localhost:9092) - host-local access
- EXTERNAL (192.168.1.111:9093) - LAN access for remote services
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 19:49:34 -08:00
hailin
ee07b52af9
feat(mining-2.0): 支持 standalone 独立部署模式,2.0 服务可脱离 1.0 单独运行
...
## 背景
2.0 挖矿生态需要从 1.0 服务器(192.168.1.111)迁移到独立服务器(192.168.1.10),
实现物理隔离部署。2.0 拥有独立的 PostgreSQL/Redis,通过远程 Kafka 接收 1.0 CDC 数据。
## docker-compose.2.0.yml 变更
### 网络参数化
- 网络改为 external: true + name 参数化:
`name: ${RWA_NETWORK_NAME:-services_rwa-network}`
- shared 模式复用 1.0 网络, standalone 模式使用独立 rwa-2-network
### 基础设施地址参数化 (所有 7 个 backend service)
- DATABASE_URL: @${POSTGRES_HOST:-postgres}:${POSTGRES_PORT:-5432}
- REDIS_HOST: ${REDIS_HOST:-redis}
- KAFKA_BROKERS: ${KAFKA_BROKERS:-kafka:29092}
### 新增 3 个 standalone profile 基础设施服务
- postgres-2: PostgreSQL 16, WAL logical, init-multiple-dbs.sh 自动建库
- redis-2: Redis 7, appendonly 持久化
- debezium-2: Debezium Connect 2.4, 连接远程 Kafka(192.168.1.111:9093)
用于 2.0 内部 outbox 模式 (服务事件 → Kafka → mining-admin-service)
### 可选依赖
- 应用 service 添加 depends_on postgres-2/redis-2 with required: false
(Docker Compose v2.20+, shared 模式下自动跳过)
## deploy-mining.sh 变更
### 部署模式切换
- DEPLOY_MODE 环境变量: shared(默认) / standalone
- load_env() 按模式设置基础设施地址和 COMPOSE_ARGS
- shared 模式不 export 变量,避免覆盖容器侧 Docker Compose 默认值
### Kafka 远程操作支持
- run_kafka_cmd() / run_kafka_cmd_stdin(): standalone 模式用临时容器执行 Kafka CLI
- 所有 Kafka 操作函数 (sync_reset, sync_status, cdc_resnapshot, full_reset) 已适配
### 基础设施生命周期管理
- infra_up / infra_down: 独立管理 standalone 基础设施
- services_up(): standalone 模式自动先启动基础设施
- services_down(): standalone 模式同时停止基础设施
- services_clean(): fallback 列表包含 standalone 容器名
### full_reset() standalone 适配
- standalone 模式跳过 1.0 source CDC 操作 (远程 Debezium 管理)
- standalone 使用 debezium_2_offsets offset topic
- 自动启动 debezium-2 后注册 outbox connectors
### 其他
- health_check(): standalone 模式检查本地 PG/Redis 容器 + 远程 Kafka
- show_help(): 新增 DEPLOY_MODE 说明和 infra-up/infra-down 命令
- print_header(): 显示当前 DEPLOY_MODE
- 所有 ~15 处 docker compose 调用统一使用 $COMPOSE_ARGS
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 19:32:03 -08:00
hailin
f39fd52001
feat(c2c-bot): rename HOT_WALLET to C2C_BOT_WALLET and change dUSDT to 绿积分
...
- Rename env vars HOT_WALLET_ADDRESS/USERNAME to C2C_BOT_WALLET_ADDRESS/USERNAME
in mining-blockchain-service to avoid conflict with existing hot wallet
- Update docker-compose.2.0.yml with new env var names
- Change all "dUSDT" labels to "绿积分" on C2C Bot admin page
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 08:40:45 -08:00
hailin
be52ac979b
fix(trading-service): add MINING_BLOCKCHAIN_SERVICE_URL to docker-compose
...
trading-service BlockchainClient defaults to http://localhost:3020 but
mining-blockchain-service runs on port 3026. Add the correct Docker
internal URL so the C2C Bot can reach the blockchain service.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 08:21:17 -08:00
hailin
8d7e5b17a1
fix(mining-admin-service): cast response.data to any for envelope unwrapping
...
TypeScript build fails because MiningServiceResponse type doesn't have
a 'data' property. The runtime response from mining-service wraps data
in a { success, data } envelope, so we need `as any` to access it.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:49:31 -08:00
hailin
7549b2b9a9
fix(mining-admin): 解包mining-service响应信封,取response.data.data
...
mining-service返回 { success, data: { ... } } 格式,
mining-admin-service需要取 .data.data 而非 .data,
否则前端读到的是信封对象而非实际数据,导致 TypeError。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:44:17 -08:00
hailin
48720d1846
feat(blockchain): 1.0 blockchain-service 同步添加 RPC 端点自动故障转移
...
与 mining-blockchain-service (2.0) 保持一致的故障转移方案:
当 RPC 端点连续失败超过 3 分钟后自动轮转到下一个备选端点。
新增文件:
- rpc-provider-manager.service.ts: RPC 故障转移管理器(与 2.0 相同逻辑)
修改文件:
- blockchain.config.ts: 新增 rpcUrls 配置字段
- chain-config.service.ts: 新增 rpcUrls 属性和 parseRpcUrls 解析方法
- domain.module.ts: 注册并导出 RpcProviderManager
- index.ts: 导出 RpcProviderManager
- evm-provider.adapter.ts: 委托 RpcProviderManager 获取 provider,
所有方法通过 executeWithFailover 包裹
- erc20-transfer.service.ts: 移除本地 providers Map,改用 RpcProviderManager,
新增 isRpcConnectionError 区分 RPC 网络错误与合约执行错误
- docker-compose.yml: blockchain-service 添加 KAVA_RPC_URLS 默认 4 个端点
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:36:02 -08:00
hailin
b9e9bb6e4e
fix(mining-admin): 修正调用mining-service的URL路径,补全/api/v2/mining前缀
...
mining-service有全局前缀api/v2和控制器前缀mining/admin,
但mining-admin-service的HTTP调用缺少这两个前缀导致404,
错误被catch静默吞掉,前端显示空数据。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:34:21 -08:00
hailin
3635369a8a
feat(mining-blockchain): RPC端点自动故障转移,连续失败3分钟后切换备选节点
...
问题:Kava主网RPC (evm.kava.io) 偶发503,导致mining-blockchain-service
所有链上操作失败(转账、余额查询、区块扫描等)。
方案:新增RpcProviderManager单例服务,统一管理各链的JsonRpcProvider实例,
当某个RPC端点连续失败超过3分钟后自动轮转到下一个备选端点。
新增文件:
- rpc-provider-manager.service.ts: 核心故障转移管理器
· 每条链维护 provider/urls/currentIndex/failureState
· reportSuccess() 重置失败状态
· reportFailure() 记录失败,>=3分钟触发 switchToNextUrl()
· 轮转创建新 JsonRpcProvider,替换旧实例
· 每30秒记录一次失败日志,避免日志刷屏
修改文件:
- blockchain.config.ts: 新增 rpcUrls 配置字段(KAVA_RPC_URLS/BSC_RPC_URLS)
- chain-config.service.ts: 解析逗号分隔的URL列表,回退到单个rpcUrl
- domain.module.ts: 注册并导出 RpcProviderManager
- index.ts: 导出 RpcProviderManager
- evm-provider.adapter.ts: 委托RpcProviderManager获取provider,
所有公开方法通过executeWithFailover包裹,自动上报成功/失败
- erc20-transfer.service.ts: 移除本地providers Map,改用RpcProviderManager,
新增isRpcConnectionError()区分RPC网络错误与合约执行错误
- docker-compose.2.0.yml: 添加KAVA_RPC_URLS默认4个端点
- .env.example: 添加KAVA_RPC_URLS配置说明
默认端点仍为 evm.kava.io,备选: evm.kava-rpc.com,
kava-evm-rpc.publicnode.com, rpc.ankr.com/kava_evm
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:06:31 -08:00
hailin
ef663c0c08
fix(deploy): replace envsubst with eval heredoc for ${VAR:-default} support
...
GNU envsubst does not handle ${VAR:-default} bash syntax - it leaves
the entire expression unsubstituted. This caused CDC connector
registration to fail with "password authentication failed for user
${POSTGRES_USER:-rwa_user}".
Replace all envsubst calls with a substitute_env_vars() helper that
uses eval+heredoc, which natively supports bash default value syntax.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 06:22:01 -08:00
hailin
ea3d256647
fix(deploy): 恢复connector JSON原样,仅在load_env中export变量修复envsubst
...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 06:09:53 -08:00
hailin
5728953b41
fix(deploy): connector JSON改为硬编码凭据,与outbox connector保持一致
...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 06:06:47 -08:00
hailin
a4f3a8d3ab
fix(deploy): 修复envsubst无法解析${VAR:-default}语法导致CDC connector注册失败
...
问题:
commit 5b1f4c82 在 full-reset Step 9 中用 envsubst 替换 connector JSON 中的
数据库凭据,但 envsubst(GNU gettext)不支持 bash 的 ${VAR:-default} 语法,
导致 "${POSTGRES_USER:-rwa_user}" 被原样发送给 Debezium,认证失败。
修复:
1. deploy-mining.sh load_env(): 默认值赋值改为 export,确保 envsubst 能访问
2. connector JSON 文件: ${VAR:-default} 改为 ${VAR},默认值由脚本 export 提供
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 06:03:38 -08:00
hailin
b9f803c5c8
fix(blockchain): 修复health check路径不匹配并配置C2C Bot热钱包
...
- app.config.ts: 添加apiPrefix读取API_PREFIX环境变量
- docker-compose: health check从api/v2改为api/v1(与trading-service一致)
- docker-compose: 配置HOT_WALLET默认值,解决"区块链服务不可用"和钱包地址不显示
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 05:46:58 -08:00
hailin
c802519ec2
fix(c2c-bot): 调整purchaseOrder操作顺序,先扣余额再链上转账
...
问题:原流程先执行不可逆的链上dUSDT转账,再扣减卖家DB余额。
若转账成功但扣减失败(余额不足、DB异常),会导致:
- dUSDT已转出(链上不可回退)
- 订单仍为PENDING(可能被重复处理)
- 卖家余额未扣减
修复:
1. 将deductSellerBalance移至transferDusdt之前(可逆操作先行)
2. 链上转账失败时调用restoreSellerBalance回补余额
3. 新增restoreSellerBalance方法,失败时记录CRITICAL级别日志
修改后流程:扣余额(可逆) → 链上转账(不可逆) → 更新订单状态(DB)
任何步骤失败都不会导致资金损失。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 05:02:19 -08:00
hailin
251e37f772
feat(c2c-bot): 添加C2C Bot管理页面,支持运行时开关和热钱包查看
...
- 新增C2C Bot管理页面(mining-admin-web):Bot开关、热钱包余额/地址/QR码、统计、订单历史
- 新增admin API端点(trading-service):status/enable/disable/orders
- 重构Bot调度器enabled为Redis驱动,支持运行时开关(多实例安全)
- C2cOrderRepository新增findBotPurchasedOrders和getBotStats查询方法
- 侧边栏添加C2C Bot导航入口
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 04:47:28 -08:00
hailin
bf772967f5
feat(mining): 批量补发30%分配到运营和总部账户,并添加交易筛选器
...
- 批量补发时将剩余30%分配到运营(12%)和总部(18%)系统账户
- SystemMiningAccountRepository.mine()支持referenceId/referenceType参数
- BatchMiningExecution新增operationAmount/headquartersAmount字段(含DB迁移)
- 三层架构(mining-service→admin-service→admin-web)全链路支持referenceType筛选
- 系统账户交易记录页面增加"全部/批量补发"筛选按钮
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 04:25:20 -08:00
hailin
338321b3a2
fix(c2c): 用updateMany+status条件防止合并时的竞态条件
...
findFirst找到PENDING订单后,如果被takeOrder接走(状态变MATCHED),
updateMany因status!=PENDING返回count=0,自动回退到创建新订单。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 03:29:27 -08:00
hailin
60d99add2c
fix(c2c): 过期恢复时合并到已有PENDING订单,避免同maker产生重复挂单
...
原来每个过期的MATCHED子订单都创建独立PENDING,导致一个卖单被多人
部分接单后过期会产生多个重复挂单。现在恢复时先查找同maker/type/price
的PENDING订单,有则合并数量,无则创建新订单。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 03:25:57 -08:00
hailin
49ba2fcb19
feat(c2c): 添加expireOrder事务流程的详细调试日志
...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 03:09:50 -08:00
hailin
627c3c943c
refactor(c2c): expireOrder使用Prisma事务确保原子性
...
将 expireOrder 中的 解冻/状态更新/恢复创建 包在 prisma.$transaction 中:
- 事务失败全部回滚,不会出现半完成的不一致状态
- SELL MATCHED/PAID 过期恢复:保持冻结 + 标记EXPIRED + 创建PENDING 原子执行
- BUY MATCHED/PAID 过期恢复:解冻taker + 标记EXPIRED + 创建PENDING 原子执行
- PENDING 过期:解冻 + 标记EXPIRED 原子执行
- 删除 restoreExpiredOrder 方法,逻辑合并到事务内
- 遵循现有模式(executeTransfer 等),在事务回调中直接使用 tx 操作
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 02:43:48 -08:00
hailin
bcfa5143e3
fix(mining-app): C2C订单详情页自动刷新,列表刷新间隔缩短
...
- 订单详情 Provider 活跃状态(PENDING/MATCHED/PAID)每10秒自动刷新
过期/完成/取消后停止刷新,节省资源
- 市场订单和我的订单列表刷新间隔从1分钟缩短到30秒
- 离开订单详情页时立即刷新市场和我的订单列表
确保过期恢复的新PENDING订单及时在列表中显示
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 02:23:21 -08:00
hailin
33dda98e81
fix(c2c): 修复过期恢复的竞态条件,SELL订单保持冻结避免资金窗口
...
- SELL MATCHED/PAID 订单过期恢复时,不再先解冻再重新冻结
- 保持 maker 的冻结不变,直接转给新 PENDING 订单
- 消除了解冻→重新冻结之间的竞态窗口(余额可能被其他操作消耗)
- 恢复失败时补充解冻,防止 maker 资金被永久冻结
- BUY 订单恢复时不复制上一个 taker 的 sellerKavaAddress
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 02:11:47 -08:00
hailin
7f2479d995
fix(mining-app): 更新弹窗不可点击外部关闭,订单详情按买卖角色显示不同倒计时文案
...
- 更新提示弹窗 barrierDismissible 始终为 false,防止用户误触关闭
- 订单详情页根据买家/卖家角色显示不同的倒计时提示文案
- 买方:你需要在xx:xx内完成付款 / 等待卖方确认收款
- 卖方:对方将在xx:xx内完成付款 / 请在xx:xx内确认收款
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 01:58:53 -08:00
hailin
4e4a876341
fix(c2c): MATCHED/PAID订单过期后自动恢复为新PENDING订单
...
当部分成交的订单过期时,将过期数量恢复到市场:
- BUY单过期:直接为maker创建新PENDING BUY单
- SELL单过期:检查maker余额,重新冻结后创建新PENDING SELL单
- 恢复失败不影响过期流程(仅记录日志)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 01:37:00 -08:00
hailin
73a617b88c
fix(c2c): 单价和总金额单位改为绿积分,待付款提示改为对方
...
- C2C市场列表/接单弹窗中单价和总金额单位从"积分值"改为"绿积分"
- 订单详情待付款倒计时提示改为"对方将在xx:xx内完成付款"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 00:57:30 -08:00
hailin
64d998c7b3
fix(trading): 卖出金额超过可用积分股时提示并禁用确认按钮
...
- 新增 _getSellValidationError 校验方法
- 输入金额反算的积分股数量 > 可用余额时显示红色提示
- 校验失败时禁用"确认交易"按钮(灰色)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 22:29:33 -08:00
hailin
b8f8831516
feat: PENDING订单自动过期、接单显示余额、积分股金额输入
...
1. C2C PENDING订单24小时自动过期并解冻冻结资产
- 新增 DEFAULT_PENDING_TIMEOUT_HOURS 常量
- findExpiredOrders 支持 PENDING 状态查询
- expireOrder 处理 PENDING 卖单解冻
2. C2C接单对话框显示卖方可用余额
- 确认出售时显示用户账户可用积分值(非订单数量)
- 新增订单数量行,方便对比
3. 积分股兑换页面新增金额输入
- 卖出时显示金额输入框(积分值),与数量双向联动
- 输入数量自动计算金额,输入金额自动反算数量
- 全部按钮同步更新两个字段
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 22:15:47 -08:00
hailin
83c29f8540
fix(c2c): 订单详情单价和总金额标签改为绿积分
...
- 单价: "积分值" → "绿积分/积分值"
- 总金额: "积分值" → "绿积分"(买方实际支付的绿积分数量)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:46:26 -08:00
hailin
6ec829a804
fix(c2c): 隐藏订单详情页的买入/卖出标签
...
订单信息卡片中移除"买入"/"卖出"类型标签,
仅保留"我发布的"标记(当用户是maker时显示)。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:43:50 -08:00
hailin
6ccc192bc6
fix(c2c): 用户无交易账户时自动创建零余额账户
...
createOrder 和 takeOrder 中,如果用户没有交易账户,
自动创建零余额账户而非报错"交易账户不存在"。
买单不需要余额,不应因缺少账户而无法下单。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:29:42 -08:00
hailin
a1c3657390
fix(c2c): 修复付款水单图片无法显示的问题
...
1. 后端: proofs 图片端点添加 @Public() 装饰器,
Image.network 无法携带 JWT token
2. 前端: paymentProofUrl 是相对路径,拼接 baseUrl
构建完整 URL 供 Image.network 加载
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:16:53 -08:00