hailin
e114723ab0
feat(mpc-system): add server-party-co-managed for co_managed_keygen sessions
...
- Create new server-party-co-managed service with two-phase event handling
- Phase 1 (session_created): Store join token and wait
- Phase 2 (session_started): Execute TSS protocol (same timing as service-party-app)
- Add PartyRoleCoManagedPersistent role to isolate from normal keygen/sign
- Update docker-compose.yml with 3 co-managed party instances
- Update deploy.sh service lists
- Modify selectPartiesByCompositionForCoManaged to use new role
This ensures co_managed_keygen sessions use dedicated parties that behave
100% compatible with service-party-app, without affecting existing keygen/sign flows.
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 23:54:45 -08:00
hailin
1c66b55ea1
fix(service-party-app): 动态计算 persistent_count 并修复 keygen 触发时机
...
1. 动态计算 server-party 数量: persistent = n - t
- 2-of-3 -> persistent=1, external=2
- 3-of-5 -> persistent=2, external=3
- 4-of-7 -> persistent=3, external=4
2. 修复 5 分钟超时与 24 小时会话的冲突
- 之前: joinSession 后立即启动 5 分钟轮询,导致超时失败
- 现在: 等待 all_joined 事件后才启动 5 分钟倒计时
- 用户可以在 24 小时内慢慢邀请其他参与者加入
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 21:28:23 -08:00
hailin
66c3cec9a5
Revert "fix(service-party-app): joinSession 添加重试逻辑处理乐观锁冲突"
...
This reverts commit 8c3a299714 .
2025-12-29 13:48:14 -08:00
hailin
8c3a299714
fix(service-party-app): joinSession 添加重试逻辑处理乐观锁冲突
...
问题:
- 多个参与方同时加入会话时会触发乐观锁冲突
- server-party 有重试逻辑可以成功重试
- service-party-app (Electron) 没有重试逻辑,直接失败
- 导致外部参与方无法成功加入 co_managed_keygen 会话
修复:
- joinSession 方法添加最多 3 次重试
- 支持重试的错误类型:optimistic lock、UNAVAILABLE、DEADLINE_EXCEEDED
- 使用指数退避 + 随机抖动避免重试风暴
- 抽取 doJoinSession 内部方法和 sleep 辅助方法
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:47:51 -08:00
hailin
6de545fcb9
fix(session-coordinator): generate wildcard token for co_managed_keygen external participants
2025-12-29 13:35:05 -08:00
hailin
75a2470233
debug(service-party-app): 添加 keygen 触发流程详细日志
...
添加 [KEYGEN] 前缀的 console.log 来追踪:
- checkAndTriggerKeygen 是否被调用
- activeKeygenSession 的状态
- 轮询条件是否满足
- handleSessionStart 的执行
- participateKeygen 的参数
帮助诊断 external party 为何不启动 TSS 进程
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:15:47 -08:00
hailin
576679ae30
fix(server-party): heartbeat during waitForAllParticipants
...
Problem:
- co_managed_keygen server-party waits for external party after joining
- No heartbeat sent during wait period (up to 5 minutes)
- session-coordinator has 120 second inactivity timeout
- Server-party marked as timed_out/failed while waiting
Fix:
- Send heartbeat in waitForAllParticipants polling loop
- Add Heartbeat method to MessageRouterClient interface
- Heartbeat every 2 seconds with poll interval
- Heartbeat failure only logs warning, does not block
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:04:40 -08:00
hailin
c0e292535d
fix(service-party-app): 修复 handleIncomingMessage 字段名 snake_case 问题
...
问题:
- gRPC proto-loader 使用 keepCase: true,返回 snake_case 字段名
- tss-handler.ts 的 handleIncomingMessage 期望 camelCase 字段名
- 导致 message_id, from_party, is_broadcast 等字段无法正确读取
- TSS 进程无法收到正确的消息,keygen 无法完成
修复:
- handleIncomingMessage 参数改为 snake_case (message_id, from_party, is_broadcast)
- 内部转换为 camelCase 格式后处理
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:53:26 -08:00
hailin
674bc9e5cd
fix(mpc-system): GetSessionStatus API 返回 threshold_t 和 threshold_n
...
问题:
- Account 服务的 GetSessionStatus HTTP API 没有返回 threshold 字段
- 导致 service-party-app 获取到的 threshold 始终是 0
- TSS keygen 无法使用正确的阈值参数
修复:
- Account gRPC client 添加 ThresholdT 和 ThresholdN 字段映射
- Account HTTP handler 返回 threshold_t 和 threshold_n
- service-party-app 优先使用后端返回的 threshold 值
- checkAndTriggerKeygen 使用后端 threshold 更新 activeKeygenSession
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:43:59 -08:00
hailin
fb1b27e36f
fix(service-party-app): 切换 session 时重新订阅消息流
...
问题:
- prepareForKeygen 只检查 isPrepared 标志
- 当旧 session 失败后 isPrepared 可能仍为 true
- 新 session 调用 prepareForKeygen 时直接跳过,没有重新订阅
- 导致 external party 仍订阅旧 session 的消息流
- server parties 发送的 TSS 消息无法到达 external party
修复:
- 检查 sessionId 是否变化
- 如果是新 session,先取消旧订阅再重新订阅
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:27:01 -08:00
hailin
989364969d
fix(service-party-app): 修复 gRPC 响应字段名 snake_case 问题
...
问题:
- proto-loader 使用 keepCase: true,导致 gRPC 响应字段为 snake_case
- TypeScript 接口使用 camelCase,导致字段不匹配
- joinSession 响应的 session_info.threshold_t 和 threshold_n 无法读取
- 导致 activeKeygenSession.threshold 为 {t: 0, n: 0}
- TSS 进程收到错误的 threshold 参数导致 exit code 1
修复:
- grpc-client.ts 接口改为 snake_case 以匹配 proto 定义
- main.ts 更新为使用 snake_case 字段名
- SessionEvent 处理转换为 camelCase 再传递给 handleSessionStart
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:14:30 -08:00
hailin
1b48c05aa7
fix(mpc-system): GetSessionStatus 返回实际的 threshold_n 和 threshold_t
...
问题:
- Message Router 的 GetSessionStatus 把 TotalParties 当作 ThresholdN 返回
- 导致 server-party 收到错误的 threshold_n=2 而不是 3
- TSS 协议无法正确启动(参与者数量验证失败)
修复:
- 在 session_coordinator.proto 添加 threshold_n 和 threshold_t 字段
- Session Coordinator 返回实际的 threshold 值
- Message Router 透传 threshold 值而不是参与者数量
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:59:53 -08:00
hailin
422d7007b1
fix(service-party-app): 补全 getSessionStatus 返回的 threshold 和 participants
...
问题:
- Session.tsx 期望 session 对象有 threshold 和 participants 字段
- 但 grpc:getSessionStatus 只返回了基础字段
- 导致前端显示 参与方 (0 / 0)
修复:
- 从 activeKeygenSession 获取 threshold 信息
- 从 API 返回的 participants 构建完整的参与者列表
- 添加 walletName, currentRound, totalRounds 字段
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:54:14 -08:00
hailin
c94f3e4d83
debug(service-party-app): 添加 TSS 进程详细调试日志
...
- 输出二进制文件路径和存在性检查
- 输出传递给 TSS 的参与者列表 JSON
- 输出完整的命令行参数
- 收集并输出 stderr 内容
- 帮助诊断 TSS 进程 exit code 1 问题
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:47:37 -08:00
hailin
aa9171ce2c
fix(service-party-app): 修复 threshold 为 undefined 导致的崩溃
...
问题:
- Session.tsx 直接访问 session.threshold.n 和 session.threshold.t
- 当后端返回的 session 数据中 threshold 为 undefined 时崩溃
修复:
- 添加空值检查 session.threshold?.n || 0
- 阈值信息部分添加条件渲染
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:37:09 -08:00
hailin
30ec0a1c8e
fix(service-party-app): 修复 participants 为 undefined 导致的崩溃
...
问题:
- Session.tsx 和 Home.tsx 直接访问 participants.length
- 当后端返回的 session 数据中 participants 为 undefined 时崩溃
- 导致 TypeError: Cannot read properties of undefined (reading length)
修复:
- 添加空值检查 (session.participants || []).length
- 使用 Math.max(0, ...) 防止负数长度
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:30:30 -08:00
hailin
b0a698250d
fix(service-party-app): 在 package.json 的 build 配置中添加 afterPack
...
问题:
- electron-builder 加载的是 package.json 的 build 字段
- 而不是单独的 electron-builder.json 文件
- 导致 afterPack hook 没有被执行
修复:
- 在 package.json 的 build 配置中添加 afterPack 引用
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:20:35 -08:00
hailin
072fbbad2c
fix(service-party-app): 使用 afterPack hook 确保 TSS 二进制文件被正确打包
...
问题:
- extraResources 的 ${platform}-${arch} 宏在 from 路径中可能不可靠
- 参考: https://github.com/electron-userland/electron-builder/issues/7891
解决:
- 创建 afterPack.js hook 手动复制对应平台/架构的二进制文件
- 移除 extraResources 配置,改用 hook 方式
- 确保 tss-party 二进制文件被正确复制到 resources/bin/ 目录
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:14:39 -08:00
hailin
9b9f6f143e
fix(service-party-app): 将 tss-party 二进制文件打包进应用
...
- 添加 extraResources 配置将 bin/${platform}-${arch} 目录包含到打包资源中
- 修复打包后的应用找不到 tss-party.exe 导致 TSS 协议无法执行的问题
- 二进制文件会被复制到 resources/bin/ 目录
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:10:38 -08:00
hailin
b48b59d946
fix(service-party-app): 开发模式默认使用真实 TSS Handler
...
问题:
- 开发模式自动使用 MockTSSHandler
- MockTSSHandler 不发送真正的 TSS 网络消息
- 导致 co_managed_keygen 无法完成
修复:
- 移除 NODE_ENV === 'development' 的自动 mock 逻辑
- 只有显式设置 USE_MOCK_TSS=true 时才使用 Mock Handler
- 开发模式现在默认使用真实的 TSSHandler
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:07:27 -08:00
hailin
b938722ff6
fix(service-party-app): 保留正确的 partyIndex 不覆盖
...
问题:
- handleSessionStart 中使用 forEach 的 index 作为 partyIndex
- 这会覆盖 checkAndTriggerKeygen 已经从服务器获取的正确 partyIndex
- 导致 TSS 协议使用错误的 partyIndex
修复:
- 优先使用 existing.partyIndex(从服务器获取的正确值)
- 只有找不到已有信息时才使用 fallback
- 按 partyIndex 排序确保顺序正确
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:59:33 -08:00
hailin
e72f96da10
feat(service-party-app): 验证成功后自动加入会话
...
- 移除手动输入名称和点击"确认加入"按钮的步骤
- 验证邀请码成功后自动触发 joinSession
- 生成默认参与者名称(参与者-xxxx 格式)
- 保留错误处理和重试功能
- 减少用户操作步骤,提高 co_managed_keygen 可靠性
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:48:41 -08:00
hailin
bd6537a2cb
fix(service-party-app): checkAndTriggerKeygen 改为轮询等待
...
问题:
- 原来 checkAndTriggerKeygen 只检查一次
- 如果首次检查时会话状态还不是 in_progress,就直接返回
- 导致 external party 永远不触发 keygen
修复:
- 改为与 server-party 的 waitForAllParticipants 一致的轮询逻辑
- 2 秒轮询间隔,最多等待 5 分钟
- 持续检查直到所有参与者加入且状态正确
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:44:29 -08:00
hailin
dfead071ab
fix(service-party-app): 修复 co_managed_keygen 消息丢失问题
...
问题:
- service-party-app 在 joinSession 后有 1 秒延迟才开始 keygen
- server-party 检测到所有参与者后立即发送 TSS Round 0 消息
- service-party-app 此时还没订阅消息流,导致消息丢失
- TSS 协议无法完成
修复:
- TSSHandler 新增 prepareForKeygen() 方法,在 joinSession 后立即订阅消息
- 新增 isPrepared 状态,在预订阅阶段也能缓冲消息
- handleIncomingMessage 支持 isPrepared || isRunning 时缓冲消息
- participateKeygen 保留预订阅阶段缓冲的消息,不重复订阅
- main.ts 在 joinSession 成功后立即调用 prepareForKeygen()
- 移除 1 秒延迟,改用 setImmediate 立即触发 keygen
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:35:39 -08:00
hailin
820a61793c
fix(service-party-app): 添加等待所有参与者加入的逻辑
...
- 在 checkAndTriggerKeygen 中添加参与者数量检查
- 必须等待所有 N 个参与者加入后才能开始 keygen
- 与 server-party 的 waitForAllParticipants 逻辑保持一致
- 修复 co_managed_keygen 场景下 TSS 协议无法完成的问题
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:18:38 -08:00
hailin
a22fc16313
fix(session-coordinator): 修复 FindExpired SQL 时区问题
...
- expires_at 存储为 UTC 时间
- 查询时使用 NOW() AT TIME ZONE 'UTC' 确保时区一致
- 避免因时区差异导致 session 过早被标记为过期
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:07:28 -08:00
hailin
e222279d77
fix(server-party): co_managed_keygen 等待所有参与者加入后再开始 keygen
...
- Message Router GetSessionStatus 透传 participants 列表
- Server Party 新增 GetSessionStatusFull 方法获取完整会话状态
- participate_keygen.go 对 co_managed_keygen 类型轮询等待所有 N 个参与者加入
- 不影响原有 keygen/sign 功能(仅 co_managed_keygen 触发等待逻辑)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:55:52 -08:00
hailin
48c8c071d5
fix(server-party): 支持 co_managed_keygen 会话类型
...
server-party 的 ParticipateKeygenUseCase 现在同时接受 "keygen" 和
"co_managed_keygen" 两种会话类型,使 persistent party 能够正确参与
共管钱包的密钥生成流程。
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:24:44 -08:00
hailin
9bc48d19a9
fix(mpc-system): 修复 co_managed_keygen 参与者 party_index 映射问题
...
- 在 proto 中添加 ParticipantStatus 消息和 participants 字段
- session-coordinator 返回参与者详细信息(含 party_index)
- account 服务透传 participants 到 HTTP 响应
- service-party-app 使用服务器返回的 party_index 而非数组索引
- 同时返回 join_tokens map 和 join_token 字符串以兼容两种格式
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:06:13 -08:00
hailin
0ca37ee76a
feat(mpc-system): 增强连接可靠性和消息去重机制
...
后端改进:
- SessionEventBroadcaster: 重连时自动关闭旧 channel 防止内存泄漏
- MessageBroker: 重连时关闭旧的 party/session channel
- SubscribeMessages: 订阅时自动发送数据库中的 pending 消息
客户端改进:
- GrpcClient: 添加自动重连机制(指数退避,最多10次)
- GrpcClient: 断开/重连/失败事件通知前端
- TSSHandler: 消息缓冲机制,进程启动前缓存收到的消息
- TSSHandler: 客户端本地消息去重,防止重连后重复处理
- Database: 添加 processed_messages 表和相关操作方法
- Main: Keygen 幂等性保护,防止重复触发
- Main: 会话事件缓存,解决前端订阅时序问题
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 07:37:03 -08:00
hailin
df8a14211e
debug(mpc-system): 添加 joinToken 调试日志
...
- service-party-app: validateInviteCode 记录 token 长度
- service-party-app: joinSession 记录 token 信息
- service-party-app: 修复 ValidateInviteCodeResult 类型缺少 joinToken 字段
- session-coordinator: JoinSession 记录 token 解析详情
用于调试 "invalid token" 错误
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 05:55:46 -08:00
hailin
5f4c7c135f
feat(mpc-system): 完善 co_managed_keygen 流程并添加调试控制台
...
主要改动:
- service-party-app: 发起方创建会话后自动加入并设置 activeKeygenSession
- service-party-app: 添加轮询机制确保 100% 可靠触发 keygen
- service-party-app: 添加 DebugConsole 组件 (Ctrl+Shift+D 打开)
- service-party-app: 主进程添加 debugLog 系统,日志可实时显示到前端
- session-coordinator: JoinSession 加入 messageRouterClient 发布事件
- session-coordinator: 添加 PublishSessionStarted 方法
修复:
- 发起方不设置 activeKeygenSession 导致无法触发 keygen 的问题
- 加入方可能错过 session_started 事件的时序问题
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 05:32:40 -08:00
hailin
a5ab2e8350
fix(session-coordinator): 支持 co_managed_keygen 动态参与者加入
...
问题: 通过邀请码加入共管钱包会话时报 "party not invited" 错误
原因: 外部参与者不在 party pool 中,CreateSession 时无法预先选择
修复:
- join_session.go: 对于 co_managed_keygen + wildcard token,允许动态添加参与者
- create_session.go: 新增 selectPartiesByCompositionForCoManaged,跳过 TemporaryCount 选择
- report_completion.go: 使用 IsKeygen() 方法,co_managed_keygen 完成后也创建账户记录
注意: 所有修改仅对 co_managed_keygen 类型生效,不影响现有 keygen/sign 流程
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 04:25:11 -08:00
hailin
af08f0f9c6
fix(mpc-system): 修复通过邀请码加入会话时 invalid token 错误
...
问题: 通过邀请码查询会话后加入时报 "13 INTERNAL: invalid token"
原因: GetSessionByInviteCode API 没有返回 join_token
修复:
- account-service: GetSessionByInviteCode 在查询时生成新的 wildcard join token
- account-service: CoManagedHTTPHandler 添加 jwtService 依赖注入
- service-party-app: validateInviteCode 返回 join_token
- service-party-app: Join.tsx 保存并使用 joinToken 和 partyId
- service-party-app: preload.ts joinSession 使用正确的参数格式
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 03:40:36 -08:00
hailin
21985abde5
fix(session-coordinator): 保存 WalletName 和 InviteCode 到数据库
...
- CreateSessionInput 添加 WalletName 和 InviteCode 字段
- gRPC handler 从请求中读取并传递这些字段
- CreateSession use case 在创建会话时设置这些字段
修复: 通过邀请码查询会话时找不到记录的问题
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 03:07:44 -08:00
hailin
591dc50eb9
fix(service-party-app): 创建会话时添加 initiator_party_id 参数
...
- CreateKeygenSessionRequest 添加 initiator_party_id 和 initiator_name 字段
- 创建会话前检查是否已连接到消息路由器
- 自动获取已注册的 partyId 作为发起者
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:54:43 -08:00
hailin
19e366e0d9
fix(service-party-app): 修复 Account 服务 URL 为 rwaapi.szaiai.com
...
api.szaiai.com 被 OSS/CDN 拦截,改用 rwaapi.szaiai.com 直接访问 Kong 网关
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:45:23 -08:00
hailin
551f3d27d2
feat(api-gateway): 添加 MPC Account Service 路由配置
...
添加共管钱包 API 路由,将 /api/v1/co-managed/* 请求转发到 account-service (端口 4000)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:31:56 -08:00
hailin
b1234bc434
feat(admin-web): 添加 TSS WASM 集成,实现与 Service-Party-App 功能对等
...
## 功能概述
Admin-Web 现在可以作为独立的 TSS 参与方参与共管钱包创建,
与 Service-Party-App 桌面应用功能完全对等。
## 主要变更
### 1. TSS WASM 模块 (backend/mpc-system/services/tss-wasm/)
- main.go: Go WASM 模块,封装 bnb-chain/tss-lib
- 支持 keygen 和 signing 操作
- 通过 syscall/js 与 JavaScript 通信
### 2. Admin-Web TSS 库 (frontend/admin-web/src/lib/tss/)
- tss-wasm-loader.ts: WASM 加载器
- tss-client.ts: 高级 TSS 客户端 API
- grpc-web-client.ts: gRPC-Web 客户端连接 Message Router
### 3. 本地存储模块 (frontend/admin-web/src/lib/storage/)
- share-storage.ts: IndexedDB 加密存储
- 使用 AES-256-GCM 加密,PBKDF2 密钥派生
### 4. React Hooks
- useTSSClient.ts: TSS 客户端状态管理
- useShareStorage.ts: 存储操作封装
### 5. 组件更新
- CreateWalletModal.tsx: 集成 TSS 客户端
- 添加密码保护对话框
- 实现真实 keygen 流程
- 自动保存 share 到 IndexedDB
- CoManagedWalletSection.tsx: 使用真实 API
- coManagedWalletService.ts: API 服务层
### 6. WASM 文件
- frontend/admin-web/public/wasm/tss.wasm (~19MB)
- frontend/admin-web/public/wasm/wasm_exec.js (Go 运行时)
## 技术栈
- Go 1.21+ (WASM 编译)
- bnb-chain/tss-lib v2.0.2 (TSS 协议)
- Web Crypto API (AES-256-GCM)
- IndexedDB (本地存储)
- gRPC-Web (消息路由)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 01:39:43 -08:00
hailin
be94a6ab18
fix(server-party): session 事件订阅断开后自动重连
...
Message Router 重启后,server-party 的 gRPC stream 会断开,
之前的实现会直接退出 goroutine 导致无法收到新的 session 事件。
修改内容:
- 添加自动重连逻辑,stream 断开时会尝试重新订阅
- 使用指数退避策略,从 1 秒到最大 30 秒
- 重连成功后重置退避时间
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 01:25:30 -08:00
hailin
40a257e55c
fix(mpc-system): 开发模式添加 message-router gRPC 端口映射
...
添加 50051:50051 端口映射,使开发模式与生产模式保持一致
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 00:56:04 -08:00
hailin
e78b6e6dcb
fix(service-party-app): 延迟加载 proto 定义避免启动时崩溃
...
将 proto 文件加载改为延迟加载模式,在 connect() 时才加载,
避免模块加载时 app.isPackaged 还未准备好导致的路径错误。
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:38:42 -08:00
hailin
4794cafdaa
fix(service-party-app): 改为非阻塞方式连接 Message Router
...
将 connectAndRegisterToMessageRouter() 改为非阻塞调用,
不再使用 await 阻塞应用启动。
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:34:10 -08:00
hailin
28da7f6807
feat(service-party-app): 实现启动时自动注册到 Message Router,状态验证真实化
...
## 主要变更
### 1. 启动时自动连接并注册
- main.ts: 添加 `connectAndRegisterToMessageRouter()` 函数
- 应用启动时自动连接到 Message Router 并注册为 temporary 角色
- 自动生成并持久化 partyId(使用 crypto.randomUUID)
- 自动订阅会话事件
### 2. 状态验证真实化
- appStore.ts: 重写 `checkAllServices()` 消息路由检测逻辑
- 不再只检测连接成功,而是:
1. 调用 isConnected() 检查连接状态
2. 调用 getPartyId() 检查是否已注册
3. 调用 getRegisteredParties() 从 Message Router 获取注册列表
4. 验证自己的 partyId 是否在列表中
- 状态显示更准确:
- "未连接到 xxx" - 未连接
- "已连接但未注册" - 已连接但没注册
- "已注册 (在线)" - 完全正常
- "注册验证失败" - 注册了但验证失败
### 3. 新增 IPC API
- grpc:getPartyId - 获取当前 partyId
- grpc:isConnected - 检查连接状态
- grpc:connect - 连接到 Message Router
- grpc:register - 注册为参与方
### 修改的文件
- electron/main.ts
- electron/preload.ts
- src/stores/appStore.ts
- src/types/electron.d.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:29:04 -08:00
hailin
73034c072c
feat(service-party-app): 添加获取已注册参与方列表API
...
新增 grpc.getRegisteredParties() API,用于查询 Message Router 中已注册的参与方:
- grpc-client.ts: 添加 getRegisteredParties() 方法
- main.ts: 添加 IPC 处理器
- preload.ts: 暴露 API 到渲染进程
- electron.d.ts: 添加类型定义
此功能用于测试和调试,确认 Service-Party-App 是否成功注册到 Message Router。
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 22:50:46 -08:00
hailin
de29fa4800
feat(co-managed-wallet): 添加签名会话API和Service-Party-App HTTP客户端
...
## Account Service 新增 API
- GET /api/v1/co-managed/sessions/by-invite-code/:inviteCode - 通过邀请码查询keygen会话
- POST /api/v1/co-managed/sign - 创建签名会话
- GET /api/v1/co-managed/sign/by-invite-code/:inviteCode - 通过邀请码查询签名会话
## Service-Party-App 变更
- 新增 account-client.ts HTTP客户端模块
- 集成Account服务API到Electron主进程
- 添加account相关IPC处理器
- 更新preload.ts暴露account API到渲染进程
- Settings页面添加Account服务URL配置
## 文档更新
- 更新 docs/service-party-app.md 反映实际实现
- 添加Account Service HTTP API说明
- 添加签名流程文档
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 22:34:35 -08:00
hailin
81c8db9d50
fix(service-party-app): 修复Kava API健康检查逻辑
...
问题: Kava API检测失败,原因是使用测试地址查询余额的方式不可靠
解决方案:
1. 添加 healthCheck() 方法到 KavaTxService,查询最新区块
2. 添加 kava:healthCheck IPC 处理器
3. 更新 appStore 使用 healthCheck API 而非 getBalance
修改的文件:
- kava-tx-service.ts: 添加 healthCheck() 方法
- main.ts: 添加 kava:healthCheck IPC 处理器
- preload.ts: 暴露 healthCheck API
- appStore.ts: 使用 healthCheck 检测 Kava API
- electron.d.ts: 添加 KavaHealthCheckResult 类型
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 21:01:27 -08:00
hailin
a2508ab0fd
fix(service-party-app): 修复sql.js在打包后无法加载的问题
...
问题: Electron打包后sql.js模块报"Cannot find module"错误
解决方案:
1. 使用extraResources将sql-wasm.wasm复制到resources目录
2. 修改database.ts使用wasmBinary方式加载WASM文件
3. 直接读取WASM文件作为ArrayBuffer,避免模块解析问题
修改的文件:
- package.json: 添加extraResources配置复制WASM文件
- database.ts: 使用fs.readFileSync读取WASM并传递给initSqlJs
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:50:28 -08:00
hailin
761e03ebb0
fix(service-party-app): 修复sql.js在打包后找不到模块的问题
...
## 问题
打包后的应用运行时报错 "Cannot find module 'sql.js'"
## 解决方案
### 1. electron-builder 配置
- 添加 `asarUnpack` 配置,将 sql.js 解压到 asar.unpacked 目录
- 将 `node_modules/sql.js/**/*` 添加到 files 列表
### 2. database.ts 修改
- 添加 `getSqlJsWasmPath()` 函数,根据环境返回正确的 WASM 路径
- 开发环境: node_modules/sql.js/dist/sql-wasm.wasm
- 生产环境: app.asar.unpacked/node_modules/sql.js/dist/sql-wasm.wasm
- 使用 locateFile 配置指定 WASM 文件位置
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:41:01 -08:00
hailin
f5cbc855f6
feat(service-party-app): 添加应用状态检测和启动检查功能
...
## 新增功能
### 1. 启动检测页面 (StartupCheck)
- 应用启动时显示环境检测界面
- 检测三个核心服务: 本地数据库、消息路由、Kava API
- 检测完成后自动进入主界面 (1.5秒延迟)
- 支持查看详细错误信息
- 即使部分服务异常也可进入应用
### 2. 应用状态管理 (appStore)
- 使用 Zustand 管理全局应用状态
- 跟踪各服务的连接状态: unknown/checking/connected/disconnected/error
- 支持操作进度跟踪 (keygen/sign)
- 提供状态辅助函数: getStatusColor, getStatusText, getOverallStatus
### 3. 侧边栏状态面板
- 实时显示三个服务的连接状态
- 显示当前操作进度 (keygen/sign 时)
- 支持手动刷新检测
- 显示整体就绪状态
## 新增文件
- src/stores/appStore.ts: 应用状态管理
- src/components/StartupCheck.tsx: 启动检测组件
- src/components/StartupCheck.module.css: 启动检测样式
## 修改文件
- src/App.tsx: 集成启动检测流程
- src/components/Layout.tsx: 添加状态面板
- src/components/Layout.module.css: 状态面板样式
- src/types/electron.d.ts: 添加 metadata 字段兼容
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:33:00 -08:00