Commit Graph

1400 Commits

Author SHA1 Message Date
hailin 35a812c058 feat(authorization): add admin authorization management API and real data integration
Backend (authorization-service):
- Add QueryAuthorizationsDto for query parameters (roleType, keyword, includeRevoked, page, limit)
- Add queryAuthorizations method to fetch all authorizations with user info
- Add GET /admin/authorizations endpoint for listing authorizations
- Add POST /admin/authorizations/:id/revoke endpoint for revoking authorization

Frontend (admin-web):
- Add authorization.types.ts with RoleType, Authorization, and request types
- Add authorizationService.ts for API calls (list, revoke, grant operations)
- Add useAuthorizations.ts React Query hooks
- Update authorization page to use real API data instead of mock data
- Add loading/error states, pagination, and revoke reason display
- Add new styles for loading, error, pagination, and date columns

The authorization management page now displays all authorized users
from the database with support for filtering by role type, status,
and keyword search.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 18:50:10 -08:00
hailin e08959263a fix(mobile-app): 修复待办操作完成后无法正确返回的问题
问题:
- 合同签署成功后使用 context.go('/profile') 直接跳转
- 导致从待办操作或待签合同列表 push 进来时收不到返回值
- 认种向导完成后同样使用 go 跳转,不会返回

修复:
1. contract_signing_page.dart
   - 签署成功后检查 canPop() 判断是否可以返回
   - 如果可以 pop(从待办操作/待签列表进入),返回 pop(true)
   - 否则(从认种流程/KYC流程进入),跳转 go('/profile')

2. pending_actions_page.dart
   - ADOPTION_WIZARD 添加后置检查(通过待签合同判断认种是否完成)
   - 在 _checkIfAlreadyCompleted 中添加 ADOPTION_WIZARD 检查逻辑

兼容性:
- 不影响正常的认种流程(使用 go 进入合同签署)
- 不影响 KYC 流程(使用 go 进入合同签署)
- 待签合同列表页面正常工作

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 18:21:26 -08:00
hailin d81e230639 refactor(admin-web): 简化授权管理页面,独立共管钱包功能
将授权管理页面的共管钱包功能独立成单独页面,并简化授权管理页面:

授权管理页面简化:
- 移除共管钱包部分(已独立)
- 移除后端不支持的复杂配置表单(考核规则、阶梯目标等)
- 保留核心功能:授权列表、筛选、创建授权、撤销授权
- 添加创建授权对话框(用户+类型+地区+跳过考核期)
- 添加撤销授权对话框(带原因输入)
- 支持5种授权类型:社区、省团队、正式省公司、市团队、正式市公司

共管钱包独立页面:
- 新建 /co-managed-wallet 页面
- 复用现有 CoManagedWalletSection 组件
- 侧边栏添加"共管钱包"菜单项

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 18:09:19 -08:00
hailin dcd6f2ce18 fix: 修复特殊扣减API路径和批量创建用户ID解析问题
1. mobile-app: 修复特殊扣减API路径重复问题
   - 将 /api/v1/wallets/special-deduction/execute 改为 /wallets/special-deduction/execute
   - 因为 ApiClient baseURL 已包含 /api/v1 前缀

2. admin-web: 批量创建待办操作支持中文逗号分隔
   - 正则表达式从 /[\n,]/ 改为 /[\n,,]/
   - 同时支持换行、英文逗号、中文逗号作为分隔符

3. identity-service: 添加用户查找调试日志
   - 在 findUserByIdOrSequence 方法中添加日志
   - 便于排查用户ID查找失败的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 17:54:27 -08:00
hailin d5fee8d8c6 feat(trading): enable one-click settlement button
开放兑换页面的"一键结算"功能:

- 有可结算收益时:显示"一键结算",按钮可点击(金色)
- 无可结算收益时:显示"暂无可结算收益",按钮禁用(半透明)
- 结算中:显示加载动画,防止重复点击
- 使用 rewardService.settleToBalance() API 执行结算
- 结算成功后自动刷新页面数据

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 07:38:57 -08:00
hailin dfdd8ed65a feat(pending-actions): add special deduction feature for admin-created user actions
实现特殊扣减功能,允许管理员为用户创建扣减待办操作,由用户在移动端确认执行。

## 后端 (wallet-service)

### 领域层
- 新增 `SPECIAL_DEDUCTION` 到 LedgerEntryType 枚举
  用于记录特殊扣减的账本流水类型

### 应用层
- 新增 `executeSpecialDeduction` 方法
  - 验证用户钱包存在性
  - 检查余额是否充足
  - 乐观锁控制并发
  - 扣减余额并记录账本流水
  - 返回操作结果和新余额

### API层
- 新增内部API: POST /api/v1/wallets/special-deduction/execute
  供移动端调用执行特殊扣减操作

## 前端 (admin-web)

### 类型定义
- 新增 `SPECIAL_DEDUCTION` 到 ACTION_CODES
- 新增 `SpecialDeductionParams` 接口定义扣减参数
  - amount: 扣减金额
  - reason: 扣减原因

### 页面
- 更新待办操作管理页面
  - 当选择 SPECIAL_DEDUCTION 时显示扣减金额和原因输入框
  - 验证扣减金额必须大于0
  - 验证扣减原因不能为空

### 样式
- 新增特殊扣减表单区域样式

## 前端 (mobile-app)

### 服务层
- 新增 `executeSpecialDeduction` 方法到 WalletService
- 新增 `SpecialDeductionResult` 结果类
- 新增 `specialDeduction` 到 PendingActionCode 枚举

### 页面
- 新增 `SpecialDeductionPage` 特殊扣减确认页面
  - 显示扣减金额和管理员备注
  - 显示当前余额和扣减后余额
  - 余额不足时禁用确认按钮
  - 温馨提示说明操作性质

- 更新 `PendingActionsPage`
  - 处理 SPECIAL_DEDUCTION 类型的待办操作
  - 从 actionParams 解析 amount 和 reason
  - 导航到特殊扣减确认页面

## 工作流程

1. 管理员在 admin-web 创建 SPECIAL_DEDUCTION 待办操作
   - 选择目标用户
   - 输入扣减金额
   - 输入扣减原因

2. 用户在 mobile-app 待办操作列表看到该操作

3. 用户点击后进入特殊扣减确认页面
   - 查看扣减详情
   - 确认余额充足
   - 点击确认执行扣减

4. 后端执行扣减并记录账本流水

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 07:04:46 -08:00
hailin a609600cd8 feat(fiat-withdrawal): add complete fiat withdrawal system
实现完整的法币提现功能,支持银行卡、支付宝、微信三种收款方式。
此功能与现有的区块链划转功能完全独立,互不影响。

## 后端 (wallet-service)

### 数据库
- 新增 `fiat_withdrawal_orders` 表存储法币提现订单
- 与现有 `withdrawal_orders` 表(区块链划转)完全分离
- 添加完整索引支持高效查询

### 领域层
- 新增 `FiatWithdrawalStatus` 枚举(与 WithdrawalStatus 独立)
  - 流程: PENDING -> FROZEN -> REVIEWING -> APPROVED -> PAYING -> COMPLETED
  - 或 REJECTED / FAILED / CANCELLED
- 新增 `PaymentMethod` 枚举: BANK_CARD / ALIPAY / WECHAT
- 新增 `FiatWithdrawalOrder` 聚合根
- 新增 `IFiatWithdrawalOrderRepository` 仓储接口
- 新增 `FIAT_WITHDRAWAL` 账本流水类型

### 应用层
- 新增 `FiatWithdrawalApplicationService` 处理业务逻辑
  - 发送短信验证码
  - 申请法币提现(冻结余额)
  - 提交审核
  - 审核通过/驳回
  - 开始打款
  - 完成打款

### API层
- 新增 `FiatWithdrawalController` 提供用户端API
  - POST /wallet/fiat-withdrawal/send-sms - 发送验证码
  - POST /wallet/fiat-withdrawal - 申请提现
  - GET /wallet/fiat-withdrawal - 获取提现记录
- 新增内部API供管理端调用
  - GET /api/v1/wallets/fiat-withdrawals - 查询订单
  - POST /api/v1/wallets/fiat-withdrawals/:orderNo/review - 审核
  - POST /api/v1/wallets/fiat-withdrawals/:orderNo/start-payment - 开始打款
  - POST /api/v1/wallets/fiat-withdrawals/:orderNo/complete-payment - 完成打款

## 前端 (admin-web)

- 新增法币提现审核管理页面 `/withdrawals`
- 支持按状态分 Tab 查看订单
- 支持审核通过/驳回
- 支持打款操作
- 支持查看订单详情

## 前端 (mobile-app)

- 新增 `WithdrawFiatPage` 法币提现页面
  - 支持选择银行卡/支付宝/微信
  - 输入收款账户信息
- 新增 `WithdrawFiatConfirmPage` 确认页面
  - 短信验证码验证
  - 密码验证
- 在 `WalletService` 中添加法币提现相关方法和模型

## 重要说明

此功能与现有的区块链划转功能 (withdraw_usdt_page.dart) 完全独立:
- 独立的数据库表
- 独立的聚合根
- 独立的状态枚举
- 独立的API端点
- 独立的前端页面

原有的区块链划转功能保持不变,不受任何影响。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 06:39:11 -08:00
hailin d614d18e97 Revert "feat(withdrawal): implement fiat withdrawal with bank/alipay/wechat"
This reverts commit 288d894746.
2026-01-03 05:44:43 -08:00
hailin 288d894746 feat(withdrawal): implement fiat withdrawal with bank/alipay/wechat
Add complete fiat withdrawal feature that allows users to withdraw
green credits (绿积分) to their bank card, Alipay, or WeChat account
with 1:1 CNY conversion. Key changes:

Backend (wallet-service):
- Update Prisma schema with fiat withdrawal fields (paymentMethod,
  bankName, bankCardNo, cardHolderName, alipay*, wechat*, review fields)
- Rewrite withdrawal status enum for fiat flow: PENDING → FROZEN →
  REVIEWING → APPROVED → PAYING → COMPLETED (or REJECTED/FAILED)
- Add PaymentMethod enum: BANK_CARD, ALIPAY, WECHAT
- Update WithdrawalOrderAggregate with new fiat withdrawal methods
- Add review/payment workflow methods in WalletApplicationService
- Add internal API endpoints for admin withdrawal management
- Remove blockchain withdrawal event handler (no longer needed)

Frontend (admin-web):
- Add withdrawal review management page at /withdrawals
- Add tabs for reviewing/approved/paying order states
- Add withdrawal service and React Query hooks
- Add types for withdrawal orders and payment methods
- Add sidebar menu item for withdrawal review

Frontend (mobile-app):
- Add withdrawFiat() method to WalletService
- Add PaymentMethod enum with BANK_CARD/ALIPAY/WECHAT
- Create new WithdrawFiatPage for fiat withdrawal input
- Create WithdrawFiatConfirmPage with SMS + password verification
- Add routes for /withdraw/fiat and /withdraw/fiat/confirm
- Keep existing withdraw/usdt (划转) pages unchanged

Note: The existing withdraw_usdt_page.dart is for point-to-point
transfer (划转), which is a different feature from fiat withdrawal.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 05:28:05 -08:00
hailin 036696878f feat(settlement): implement settle-to-balance with detailed source tracking
Add complete settlement-to-balance feature that transfers settleable
earnings directly to wallet USDT balance (no currency swap). Key changes:

Backend (wallet-service):
- Add SettleToBalanceCommand for settlement operations
- Add settleToBalance method to WalletAccountAggregate
- Add settleToBalance application service with ledger recording
- Add internal API endpoint POST /api/v1/wallets/settle-to-balance

Backend (reward-service):
- Add settleToBalance client method for wallet-service communication
- Add settleRewardsToBalance application service method
- Add user-facing API endpoint POST /rewards/settle-to-balance
- Build detailed settlement memo with source user tracking per reward

Frontend (mobile-app):
- Add SettleToBalanceResult model class
- Add settleToBalance() method to RewardService
- Update pending_actions_page to handle SETTLE_REWARDS action
- Add completion detection via settleableUsdt balance check

Settlement memo now includes detailed breakdown by right type with
source user accountSequence for each reward entry, e.g.:
  结算 1000.00 绿积分到钱包余额
  涉及 5 笔奖励
    - SHARE_RIGHT: 500.00 绿积分
        来自 D2512120001: 288.00 绿积分
        来自 D2512120002: 212.00 绿积分

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 04:29:38 -08:00
hailin cbbef170e8 feat(pending-actions): display accountSequence alongside userId
- Add accountSequence field to PendingActionResponseDto
- Add helper methods to fetch accountSequence from UserAccount
- Update queryActions and getAction to include accountSequence
- Update admin-web table and detail view to show both fields
- accountSequence displayed prominently, userId shown as secondary info

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 21:33:03 -08:00
hailin 13dd42d2be fix(mobile-app): fix pending action completion detection
- Change FORCE_KYC check from isCompleted to level1.verified
  (FORCE_KYC only requires real-name verification, not all KYC levels)
- Add post-navigation re-check for FORCE_KYC and BIND_PHONE actions
  (handles cases where user completes action but page doesn't return true)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 21:09:35 -08:00
hailin c5c4e1667e fix(mobile-app): fix layout constraint error in pending actions page
Wrap ElevatedButton in SizedBox(width: 72) to prevent
BoxConstraints infinite width error in Row layout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 21:02:15 -08:00
hailin f5f0ff2822 fix(mobile-app): correctly parse nested API response for pending actions
The API returns a nested structure {success, data: {code, data: [...]}}
but the service was only checking for {actions: [...]} format.

Now correctly extracts the actions list from data.data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 20:57:17 -08:00
hailin f7913cd04e chore: temporarily disable KYC and contract check logs
Comment out debugPrint statements in pending actions and contract
check services to reduce log noise during development.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 20:51:13 -08:00
hailin 789d921fd7 fix(pending-actions): support accountSequence for user lookup
Allow admin to create pending actions using accountSequence (e.g.,
D25122700022) instead of requiring numeric userId.

- Add findUserByIdOrSequence helper method
- Update createAction to use helper
- Update batchCreateActions to use helper
- Update queryActions to support accountSequence filter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 20:39:54 -08:00
hailin 47a7e4a4da feat(pending-actions): enhance multi-select creation and add pre-check
Admin Web:
- Redesign create modal to support multi-select action types
- Add drag-and-drop ordering for execution sequence
- Auto-calculate priority based on order (first = highest)
- Add @dnd-kit dependencies for sortable functionality

Flutter Mobile App:
- Add pre-check logic before executing pending actions
- Auto-complete FORCE_KYC if KYC already verified
- Auto-complete BIND_PHONE if phone already bound
- Skip unnecessary user interactions for completed tasks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 20:23:15 -08:00
hailin 06d3489b49 fix(admin-web): fix nested data access in pendingActionService
API returns nested structure: { success, data: { code, message, data: {...} } }
After apiClient interceptor unwraps response.data, we still need to access
.data.data to get the actual business data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 19:18:54 -08:00
hailin ed463d67ab fix(admin-web): fix API response data access in pendingActionService
The apiClient interceptor already unwraps response.data, so the service
was accessing .data on the already-unwrapped response. Fixed by properly
casting the response type to access the nested data field.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 19:08:57 -08:00
hailin 8c8a049f77 fix(admin-web): handle undefined data in dashboard hooks
Add null-safe access and fallback to empty arrays to prevent
"Cannot read properties of undefined" errors when API returns
unexpected data structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 19:05:54 -08:00
hailin 2e7de8a1ef feat(contracts): add DurianUSDT ERC-20 token contract
Add fixed-supply ERC-20 token contract for Durian USDT (dUSDT):
- Total supply: 1 trillion tokens with 6 decimals
- No minting capability - all tokens minted at deployment
- Includes compile and deploy scripts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 19:02:19 -08:00
hailin 582e80b750 fix(pending-actions): add @Public() decorator to AdminPendingActionController
Skip JWT auth for admin pending-actions endpoints since admin-web
authenticates through a different mechanism (admin-service tokens).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 19:00:24 -08:00
hailin ff038f31f9 fix(pending-actions): fix API response handling and add Kong route
- Fix pending_action_service.dart to access response.data instead of response
- Add Kong route for /api/v1/admin/pending-actions to identity-service

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 18:33:58 -08:00
hailin 28e0396a65 feat(pending-actions): add user pending actions system
Add a fully optional pending actions system that allows admins to configure
specific tasks that users must complete after login.

Backend (identity-service):
- Add UserPendingAction model to Prisma schema
- Add migration for user_pending_actions table
- Add PendingActionService with full CRUD operations
- Add user-facing API (GET list, POST complete)
- Add admin API (CRUD, batch create)

Admin Web:
- Add pending actions management page
- Support single/batch create, edit, cancel, delete
- View action details including completion time
- Filter by userId, actionCode, status

Flutter Mobile App:
- Add PendingActionService and PendingActionCheckService
- Add PendingActionsPage for forced task execution
- Integrate into splash_page login flow
- Users must complete all pending tasks in priority order

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 18:22:51 -08:00
hailin 04a8c56ad6 fix(identity): use correct Aliyun API for ID card verification
Change API from Id2MetaStandardVerify to Id2MetaVerify for two-factor
identity verification (name + ID card number). The previous API was
returning error 440 (no permission).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 08:05:08 -08:00
hailin e2cf3c3d7e fix(admin-service): 修复通知查询时publishedAt为null的问题
问题:当 publishedAt 为 NULL(表示立即发布)时,Prisma 的
`publishedAt: { lte: now }` 条件不匹配,导致通知无法显示

修复:将查询条件改为 OR 逻辑:
- publishedAt 为 null(立即发布)
- publishedAt <= now(定时发布且已到时间)

影响的方法:
- findNotificationsForUser
- countUnreadForUser
- markAllAsRead

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 05:56:43 -08:00
hailin fea0b42223 fix(admin-service): 修复维护拦截器路径检测和错误处理
问题:添加系统维护检测后站内通知功能失效

修复:
1. 使用 request.url 获取完整路径(包含 /api/v1 前缀)
2. 同时支持带前缀和不带前缀的路径检测
3. 添加 try-catch 错误处理,数据库错误时放行请求而非阻断
4. 添加日志记录便于调试

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 05:01:32 -08:00
hailin c392142562 feat(blockchain): 切换到dUSDT(绿积分)合约 - KAVA主网
合约信息:
- 地址: 0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3
- 名称: Durian USDT (dUSDT)
- 精度: 6位
- 网络: KAVA EVM Mainnet (Chain ID: 2222)
- 链接: https://kavascan.com/address/0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3

修改:
- blockchain.config.ts: 更新默认合约地址
- chain-config.service.ts: 更新默认合约地址
- docker-compose.yml: NETWORK_MODE改为mainnet,配置KAVA主网
- .env.example: 更新合约地址和注释
- KAVA_NETWORK.md: 标注dUSDT为当前使用合约

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 04:31:11 -08:00
hailin 8173e1f973 feat: "同僚"改为"同伴" + KYC从三要素改为二要素
mobile-app:
- profile_page.dart: 将所有"同僚"改为"同伴"

identity-service:
- 层级1实名认证从三要素(姓名+身份证+手机号)改为二要素(姓名+身份证号)
- 使用阿里云 Id2MetaStandardVerify API
- 二要素验证直接调用真实API,不使用mock
- 保留三要素验证方法(verifyIdCardThreeFactor)备用

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 04:20:42 -08:00
hailin 47e4ef2b33 feat(android): add share export and import functionality
Add ability to backup wallet shares to files and restore from backups:

- Add ShareBackup data class in Models.kt for backup format
- Add exportShareBackup() and importShareBackup() in TssRepository
- Add export/import state and methods in MainViewModel
- Add file picker integration in MainActivity using ActivityResultContracts
- Add import FAB button in WalletsScreen
- Export saves as .tss-backup file with address and timestamp in filename
- Import validates backup format and checks for duplicate wallets

The backup file contains all necessary data to restore a wallet share:
sessionId, publicKey, encryptedShare, threshold, partyIndex, address.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 03:35:37 -08:00
hailin 9f33e375d0 fix(android): add @OptIn annotation for experimental FilterChip API
Add @OptIn(ExperimentalMaterial3Api::class) to TransferInputScreen
composable to fix compilation error for FilterChip and FilterChipDefaults.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 03:06:32 -08:00
hailin 9b9612bd5f feat(token): add Green Points (绿积分) ERC-20 token support
Add support for the dUSDT token "绿积分" (Green Points) on both Android
and Electron applications:

Android changes:
- Add TokenType enum and GreenPointsToken config in Models.kt
- Implement ERC-20 balance fetching and transfer encoding in TssRepository
- Update TransactionUtils with ERC-20 transfer support
- Add dual balance display (KAVA + 绿积分) in WalletsScreen
- Add token type selector in TransferScreen

Electron changes:
- Add TokenType and GREEN_POINTS_TOKEN config in transaction.ts
- Implement fetchGreenPointsBalance and ERC-20 transfer encoding
- Update Home.tsx with dual balance display and token selector
- Add token selector styles in Home.module.css

Token contract: 0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3 (Kava mainnet)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 03:01:05 -08:00
hailin b3822e48eb fix(android): decode Base64 signature before broadcasting transaction
The TSS native bridge returns signatures in Base64 format, but the
broadcast function expected hex format. Added Base64 decoding in
broadcastTransaction() to properly parse r, s, v components.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 22:44:44 -08:00
hailin 2365a50b1b feat(tss): add real-time round progress from msg.Type() parsing
Extract current round number from tss-lib message type string using
regex pattern `Round(\d+)`. This enables real-time progress updates
(1/4, 2/4... for keygen, 1/9, 2/9... for signing) instead of only
showing completion status.

Changes across all three platforms:
- tss-wasm/main.go: Add extractRoundFromMessageType() and call
  OnProgress with parsed round on each outgoing message
- service-party-android/tsslib/tsslib.go: Same implementation for
  Android gomobile binding
- service-party-app/tss-party/main.go: Same implementation for
  Electron subprocess, with isKeygen parameter to distinguish
  keygen (4 rounds) vs signing (9 rounds)

Safe fallback: Returns 0 if parsing fails, which doesn't affect
protocol execution - only UI display.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 22:41:51 -08:00
hailin f8de55e671 fix(android): reset isLoading after signing completes to enable broadcast button
The broadcast button was disabled because isLoading remained true after
signing completed. Added isLoading = false reset in startSigningProcess
after waitForSignature succeeds or fails.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 22:21:30 -08:00
hailin 001f0ac480 fix(android): remove 0x prefix from messageHash before TSS sign
TSS native library expects pure hex string without 0x prefix.
Fix both startSigning (initiator) and executeSignAsJoiner (joiner) functions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 22:04:18 -08:00
hailin 0bd764e1d1 fix(android): ensure session event subscription active before creating sign session
Add ensureSessionEventSubscriptionActive() call at the start of createSignSession()
to prevent race condition where session_started event arrives before subscription
is ready. Also add debug logging for _signSessionId and pendingSignInitiatorInfo
in event callback to help diagnose sign initiator event matching issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 21:45:18 -08:00
hailin ecd7a2a2dc fix(android): clear pendingSessionId in resetSessionStatus to fix stale session matching
The resetSessionStatus() function was not clearing pendingSessionId,
causing events from new sessions to be ignored because pendingSessionId
still held the old session ID.

Added:
- Clear pendingSessionId = null in resetSessionStatus()
- Clear _currentSession.value = null in resetSessionStatus()
- Added debug logging for session state clearing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 21:11:24 -08:00
hailin e865153e8e fix(android): refresh session event subscription when joining sign session
The session event gRPC stream may silently disconnect without triggering
onError or onCompleted callbacks. This causes session_started events to
be lost, preventing the sign process from starting.

Changes:
- Add ensureSessionEventSubscriptionActive() to refresh event subscription
- Call it in joinSignSessionViaGrpc for sign joiner
- Call it in createSignSession for sign initiator after auto-join

This ensures a fresh event stream connection before waiting for events.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 20:47:13 -08:00
hailin da76037d04 fix(tss-wasm): correct signing rounds from 6 to 9
GG20 signing protocol has 9 rounds, not 6. This aligns WASM with
Electron (tss-party/main.go:717) and Android (tsslib/tsslib.go:477).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 20:24:47 -08:00
hailin 16e1e9159c fix(android): sign initiator event handling to match Electron flow
Changes:
- Add sign initiator handling for participant_joined events in MainViewModel
- Add sign initiator handling for session_started events in MainViewModel
- Add sign initiator handling for all_joined events in MainViewModel
- Set pendingSessionId in TssRepository.createSignSession for event matching
- Refactor initiateSignSession to wait for session_started instead of starting immediately
- Add PendingSignInitiatorInfo data class to store pending sign info
- Add sessionAlreadyInProgress flag to SignSessionResult for immediate trigger case

This fixes the issue where sign initiator couldn't detect when other parties
joined the signing session, making Android flow 100% consistent with Electron.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 20:14:32 -08:00
hailin fd56de5c00 fix(android): enable real-time progress updates for keygen/sign rounds
Connect TssNativeBridge.progress Flow to UI through:
- Add progressCallback in TssRepository with startProgressCollection/stopProgressCollection
- Subscribe to native bridge progress in keygen and sign methods
- Add setProgressCallback in MainViewModel to update appropriate round state
- Progress now flows: Go Native → TssNativeBridge → TssRepository → MainViewModel → UI

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 19:45:31 -08:00
hailin 3576af0f25 feat(android): add 5-minute countdown timer UI for keygen/sign sessions
Displays remaining time during the 5-minute polling timeout:
- Shows countdown in CreateWalletScreen (SessionScreen)
- Shows countdown in JoinKeygenScreen (JoiningScreen, KeygenProgressScreen)
- Shows countdown in CoSignJoinScreen (JoiningScreen, SigningProgressScreen)
- Format: mm:ss with Timer icon in tertiary container card
- Countdown starts on all_joined event and stops on session start/cancel

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 19:33:20 -08:00
hailin b30017f3a7 fix(android): prevent memory leaks from detached coroutine scopes
Critical fixes to prevent app crashes when screens are kept open for extended periods:

- Add repositoryScope with SupervisorJob for structured concurrency in TssRepository
- Replace detached CoroutineScope(Dispatchers.IO).launch with repositoryScope.launch:
  - Session event subscription (line 206)
  - Session status polling (line 291)
  - Message routing (line 1508)
- Add cleanup() method to properly cancel all jobs and repositoryScope
- Update disconnect() to also cancel sessionStatusPollingJob
- Update MainViewModel.onCleared() to call repository.cleanup()

This ensures all background coroutines are properly cancelled when the ViewModel
is cleared, preventing memory accumulation over time.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 19:05:13 -08:00
hailin fc86af918f feat(android): add 5-minute polling timeout mechanism for keygen/sign
Implements Electron's checkAndTriggerKeygen() polling fallback:
- Adds polling every 2 seconds with 5-minute timeout
- Triggers keygen/sign via synthetic session_started event on in_progress status
- Handles gRPC stream disconnection when app goes to background
- Shows timeout error in UI via existing error mechanism

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 18:51:02 -08:00
hailin ad79679ee2 feat(ui): add QR code display for invite code in signing session
Android TransferScreen:
- Add QR code display above invite code text
- Import QRCodeWriter and related components
- Add generateInviteQRCode helper function
- Update hint text to mention scanning

Electron CoSignSession:
- Import QRCodeSVG from qrcode.react
- Add QR code above invite code text with proper styling
- Center QR code and update hint text

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 18:37:18 -08:00
hailin ed55be2b86 fix(android): transfer flow improvements and message_hash format fix
Transfer Screen improvements:
- Add QR code scanning for recipient address (using zxing library)
- Support EIP-681 URI format (ethereum:0x...) and plain address
- Remove password requirement - TSS wallets don't need passwords
- Remove unused onScanQrCode callback parameter

WalletsScreen changes:
- Simplify onTransfer callback to only pass shareId
- Remove TransferDialog - now navigates directly to TransferScreen
- Remove unused state variables (showTransferDialog, transferWallet)

Bug fix:
- Remove 0x prefix from message_hash before sending to API
- Backend expects pure hex, not 0x-prefixed hex string

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 18:18:29 -08:00
hailin 480251b85f fix(android): remove incorrect Participant import
Participant class is already imported via domain.model.* wildcard import,
no need for separate import from data.repository (where it doesn't exist).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 11:03:31 -08:00
hailin ee1cfe082d fix(android): resolve compilation errors for walletName and Participant
- TssRepository: Use address-based wallet name since ShareRecordEntity
  doesn't have wallet_name field (unlike Electron's ShareRecord)
- MainViewModel: Add missing Participant import and simplify type reference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 11:00:36 -08:00
hailin 04eeadf7a7 fix(android): co-sign flow consistency with Electron + state reset
Changes:
- Fix Android state not resetting after successful keygen/join
  - Add resetSessionStatus() method in TssRepository
  - Call reset on success navigation in MainActivity

- Make Android co-sign flow 100% consistent with Electron:
  - Get keygen session status for participants list
  - Filter out co-managed-party-* (server backup parties)
  - Auto-join via gRPC after creating sign session
  - Start message routing BEFORE signing (prepareForSign)
  - Use gRPC response partyIndex instead of local share
  - Use original keygen thresholdN instead of signingParties.size
  - Pass parties list in join sign flow

- Update SignSessionInfoResponse to include parties array
- Update validateSignInviteCode to parse parties from API response

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 10:52:13 -08:00