251 Commits

Author SHA1 Message Date
tinkle-community
1141a3f968 Feature/custom strategy (#1173)
* feat: add Strategy Studio with multi-timeframe support

- Add Strategy Studio page with three-column layout for strategy management
- Support multi-timeframe K-line data selection (5m, 15m, 1h, 4h, etc.)
- Add GetWithTimeframes() function in market package for fetching multiple timeframes
- Add TimeframeSeriesData struct for storing per-timeframe technical indicators
- Update formatMarketData() to display all selected timeframes in AI prompt
- Add strategy API endpoints for CRUD operations and test run
- Integrate real AI test runs with configured AI models
- Support custom AI500 and OI Top API URLs from strategy config

* docs: add Strategy Studio screenshot to README files

* feat: add quant data integration and fix position click navigation

- Integrate quant data API (netflow, OI, price changes) into Strategy Studio
- Add enable_quant_data toggle in indicator editor
- Fix position symbol click to navigate to chart (sync defaultSymbol prop)
- Fix TradingView chart fullscreen flickering
2025-12-06 07:47:03 +08:00
tinkle-community
1ea1234c64 Feature/custom strategy (#1172)
* feat: add Strategy Studio with multi-timeframe support

- Add Strategy Studio page with three-column layout for strategy management
- Support multi-timeframe K-line data selection (5m, 15m, 1h, 4h, etc.)
- Add GetWithTimeframes() function in market package for fetching multiple timeframes
- Add TimeframeSeriesData struct for storing per-timeframe technical indicators
- Update formatMarketData() to display all selected timeframes in AI prompt
- Add strategy API endpoints for CRUD operations and test run
- Integrate real AI test runs with configured AI models
- Support custom AI500 and OI Top API URLs from strategy config

* docs: add Strategy Studio screenshot to README files

* fix: correct strategy-studio.png filename case in README

* refactor: remove legacy signal source config and simplify trader creation

- Remove signal source configuration from traders page (now handled by strategy)
- Remove advanced options (legacy config) from TraderConfigModal
- Rename default strategy to "默认山寨策略" with AI500 coin pool URL
- Delete SignalSourceModal and SignalSourceWarning components
- Clean up related stores, hooks, and page components
2025-12-06 07:20:11 +08:00
tinkle-community
495209a69b Refactor/trading actions (#1169)
* refactor: 简化交易动作,移除 update_stop_loss/update_take_profit/partial_close

- 移除 Decision 结构体中的 NewStopLoss, NewTakeProfit, ClosePercentage 字段
- 删除 executeUpdateStopLossWithRecord, executeUpdateTakeProfitWithRecord, executePartialCloseWithRecord 函数
- 简化 logger 中的 partial_close 聚合逻辑
- 更新 AI prompt 和验证逻辑,只保留 6 个核心动作
- 清理相关测试代码

保留的交易动作: open_long, open_short, close_long, close_short, hold, wait

* refactor: 移除 AI学习与反思 模块

- 删除前端 AILearning.tsx 组件和相关引用
- 删除后端 /performance API 接口
- 删除 logger 中 AnalyzePerformance、calculateSharpeRatio 等函数
- 删除 PerformanceAnalysis、TradeOutcome、SymbolPerformance 等结构体
- 删除 Context 中的 Performance 字段
- 移除 AI prompt 中夏普比率自我进化相关内容
- 清理 i18n 翻译文件中的相关条目

该模块基于磁盘存储计算,经常出错,做减法移除

* refactor: 将数据库操作统一迁移到 store 包

- 新增 store/ 包,统一管理所有数据库操作
  - store.go: 主 Store 结构,懒加载各子模块
  - user.go, ai_model.go, exchange.go, trader.go 等子模块
  - 支持加密/解密函数注入 (SetCryptoFuncs)

- 更新 main.go 使用 store.New() 替代 config.NewDatabase()
- 更新 api/server.go 使用 *store.Store 替代 *config.Database
- 更新 manager/trader_manager.go:
  - 新增 LoadTradersFromStore, LoadUserTradersFromStore 方法
  - 删除旧版 LoadUserTraders, LoadTraderByID, loadSingleTrader 等方法
  - 移除 nofx/config 依赖

- 删除 config/database.go 和 config/database_test.go
- 更新 api/server_test.go 使用 store.Trader 类型
- 清理 logger/ 包中未使用的 telegram 相关代码

* refactor: unify encryption key management via .env

- Remove redundant EncryptionManager and SecureStorage
- Simplify CryptoService to load keys from environment variables only
  - RSA_PRIVATE_KEY: RSA private key for client-server encryption
  - DATA_ENCRYPTION_KEY: AES-256 key for database encryption
  - JWT_SECRET: JWT signing key for authentication
- Update start.sh to auto-generate missing keys on first run
- Remove secrets/ directory and file-based key storage
- Delete obsolete encryption setup scripts
- Update .env.example with all required keys

* refactor: unify logger usage across mcp package

- Add MCPLogger adapter in logger package to implement mcp.Logger interface
- Update mcp/config.go to use global logger by default
- Remove redundant defaultLogger from mcp/logger.go
- Keep noopLogger for testing purposes

* chore: remove leftover test RSA key file

* chore: remove unused bootstrap package

* refactor: unify logging to use logger package instead of fmt/log

- Replace all fmt.Print/log.Print calls with logger package
- Add auto-initialization in logger package init() for test compatibility
- Update main.go to initialize logger at startup
- Migrate all packages: api, backtest, config, decision, manager, market, store, trader

* refactor: rename database file from config.db to data.db

- Update main.go, start.sh, docker-compose.yml
- Update migration script and documentation
- Update .gitignore and translations

* fix: add RSA_PRIVATE_KEY to docker-compose environment

* fix: add registration_enabled to /api/config response

* fix: Fix navigation between login and register pages

Use window.location.href instead of react-router's navigate() to fix
the issue where URL changes but the page doesn't reload due to App.tsx
using custom route state management.

* fix: Switch SQLite from WAL to DELETE mode for Docker compatibility

WAL mode causes data sync issues with Docker bind mounts on macOS due
to incompatible file locking mechanisms between the container and host.
DELETE mode (traditional journaling) ensures data is written directly
to the main database file.

* refactor: Remove default user from database initialization

The default user was a legacy placeholder that is no longer needed now
that proper user registration is in place.

* feat: Add order tracking system with centralized status sync

- Add trader_orders table for tracking all order lifecycle
- Implement GetOrderStatus interface for all exchanges (Binance, Bybit, Hyperliquid, Aster, Lighter)
- Create OrderSyncManager for centralized order status polling
- Add trading statistics (Sharpe ratio, win rate, profit factor) to AI context
- Include recent completed orders in AI decision input
- Remove per-order goroutine polling in favor of global sync manager

* feat: Add TradingView K-line chart to dashboard

- Create TradingViewChart component with exchange/symbol selectors
- Support Binance, Bybit, OKX, Coinbase, Kraken, KuCoin exchanges
- Add popular symbols quick selection
- Support multiple timeframes (1m to 1W)
- Add fullscreen mode
- Integrate with Dashboard page below equity chart
- Add i18n translations for zh/en

* refactor: Replace separate charts with tabbed ChartTabs component

- Create ChartTabs component with tab switching between equity curve and K-line
- Add embedded mode support for EquityChart and TradingViewChart
- User can now switch between account equity and market chart in same area

* fix: Use ChartTabs in App.tsx and fix embedded mode in EquityChart

- Replace EquityChart with ChartTabs in App.tsx (the actual dashboard renderer)
- Fix EquityChart embedded mode for error and empty data states
- Rename interval state to timeInterval to avoid shadowing window.setInterval
- Add debug logging to ChartTabs component

* feat: Add position tracking system for accurate trade history

- Add trader_positions table to track complete open/close trades
- Add PositionSyncManager to detect manual closes via polling
- Record position on open, update on close with PnL calculation
- Use positions table for trading stats and recent trades (replacing orders table)
- Fix TradingView chart symbol format (add .P suffix for futures)
- Fix DecisionCard wait/hold action color (gray instead of red)
- Auto-append USDT suffix for custom symbol input

* update

---------
2025-12-06 01:04:26 +08:00
tinkle-community
2e964d704a fix: ensure tab navigation updates page state correctly
Tab buttons were only calling navigate() which changes URL but doesn't
trigger popstate events. App.tsx listens to popstate/hashchange to
update page state, so clicks appeared to do nothing.

Now all tab buttons call both onPageChange() callback and navigate()
to ensure page state updates and URL stays in sync.
2025-11-30 12:40:14 +08:00
Professor-Chen
b71272d48b fix: resolve multiple bugs preventing trader creation (#1138)
* fix: resolve multiple bugs preventing trader creation

Bug fixes:
1. Fix time.Time scanning error - SQLite stores datetime as TEXT, now parsing manually
2. Fix foreign key mismatch - traders table referenced exchanges(id) but exchanges uses composite primary key (id, user_id)
3. Add missing backtestManager field to Server struct
4. Add missing Shutdown method to Server struct
5. Fix NewFuturesTrader call - pass userId parameter
6. Fix UpdateExchange call - pass all required parameters
7. Add migrateTradersTable() to fix existing databases

These issues prevented creating new traders with 500 errors.

* fix(api): fix balance extraction field name mismatch

Binance API returns 'availableBalance' (camelCase) but code was looking for
'available_balance' (snake_case). Now supports both formats.

Also added 'totalWalletBalance' as fallback for total balance extraction.

* fix(frontend): add missing ConfirmDialogProvider to App

The delete trader button required ConfirmDialogProvider to be wrapped
around the App component for the confirmation dialog to work.

---------

Co-authored-by: NOFX Trader <nofx@local.dev>
2025-11-30 12:22:20 +08:00
Rick
7eebb4e218 Dev backtest (#1134) 2025-11-28 21:34:27 +08:00
0xYYBB | ZYY | Bobo
46ec8f1d04 feat(exchange): add Bybit Futures support (#1100)
* feat(exchange): add Bybit Futures support

- Add Bybit Go SDK dependency (github.com/bybit-exchange/bybit.go.api)
- Create trader/bybit_trader.go implementing Trader interface for USDT perpetual futures
- Update config/database.go to include Bybit in default exchanges
- Update manager/trader_manager.go to handle Bybit API key configuration
- Update trader/auto_trader.go to add BybitAPIKey/BybitSecretKey fields and bybit case
- Add Bybit icon to frontend ExchangeIcons.tsx

Bybit uses standard API Key/Secret Key authentication (similar to Binance).
Only USDT perpetual futures (category=linear) are supported.

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* test(bybit): add comprehensive unit tests for Bybit trader

- Add BybitTraderTestSuite following existing test patterns
- Interface compliance test (Trader interface)
- Symbol format validation tests
- FormatQuantity tests with 3-decimal precision
- API response parsing tests (success, error, permission denied)
- Position side conversion tests (Buy->long, Sell->short)
- Cache duration verification test
- Mock server integration tests for API endpoints

All 12 Bybit tests pass.

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(frontend): add Bybit support to exchange config forms

修復前端對 Bybit 交易所的支持:
- 添加 Bybit 到 API Key/Secret Key 輸入欄位顯示邏輯
- 添加 Bybit 的表單驗證邏輯
- 修復 ExchangeConfigModal.tsx 和 AITradersPage.tsx

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-23 19:23:53 +08:00
0xYYBB | ZYY | Bobo
8dffff60a2 feat(lighter): 完整集成 LIGHTER DEX - SDK + 前端配置 UI (#1085)
* feat(trader): add LIGHTER DEX integration (initial implementation)

Add pure Go implementation of LIGHTER DEX trader following NOFX architecture

Features:
-  Account management with Ethereum wallet authentication
-  Order operations: market/limit orders, cancel, query
-  Position & balance queries
-  Zero-fee trading support (Standard accounts)
-  Up to 50x leverage for BTC/ETH

Implementation:
- Pure Go (no CGO dependencies) for easy deployment
- Based on hyperliquid_trader.go architecture
- Uses Ethereum ECDSA signatures (like Hyperliquid)
- API base URL: https://mainnet.zklighter.elliot.ai

Files:
- lighter_trader.go: Core trader structure & auth
- lighter_orders.go: Order management (create/cancel/query)
- lighter_account.go: Balance & position queries

Status: ⚠️ Partial implementation
-  Core structure complete
- ⏸️ Auth token generation needs implementation
- ⏸️ Transaction signing logic needs completion
- ⏸️ Config integration pending

Next steps:
1. Complete auth token generation
2. Add to config/exchange registry
3. Add frontend UI support
4. Create test suite

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat: Add LIGHTER DEX integration (快速整合階段)

## 🚀 新增功能
-  添加 LIGHTER DEX 作為第四個支持的交易所 (Binance, Hyperliquid, Aster, LIGHTER)
-  完整的數據庫配置支持(ExchangeConfig 新增 LighterWalletAddr, LighterPrivateKey 字段)
-  交易所註冊與初始化(initDefaultData 註冊 "lighter")
-  TraderManager 集成(配置傳遞邏輯完成)
-  AutoTrader 支持(NewAutoTrader 添加 "lighter" case)

## 📝 實現細節

### 後端整合
1. **數據庫層** (config/database.go):
   - ExchangeConfig 添加 LIGHTER 字段
   - 創建表時添加 lighter_wallet_addr, lighter_private_key 欄位
   - ALTER TABLE 語句用於向後兼容
   - UpdateExchange/CreateExchange/GetExchanges 支持 LIGHTER
   - migrateExchangesTable 支持 LIGHTER 字段

2. **API 層** (api/server.go, api/utils.go):
   - UpdateExchangeConfigRequest 添加 LIGHTER 字段
   - SanitizeExchangeConfigForLog 添加脫敏處理

3. **Trader 層** (trader/):
   - lighter_trader.go: 核心結構、認證、初始化
   - lighter_account.go: 餘額、持倉、市場價格查詢
   - lighter_orders.go: 訂單管理(創建、取消、查詢)
   - lighter_trading.go: 交易功能實現(開多/空、平倉、止損/盈)
   - 實現完整 Trader interface (13個方法)

4. **Manager 層** (manager/trader_manager.go):
   - addTraderFromDB 添加 LIGHTER 配置設置
   - AutoTraderConfig 添加 LIGHTER 字段

### 實現的功能(快速整合階段)
 基礎交易功能 (OpenLong, OpenShort, CloseLong, CloseShort)
 餘額查詢 (GetBalance, GetAccountBalance)
 持倉查詢 (GetPositions, GetPosition)
 訂單管理 (CreateOrder, CancelOrder, CancelAllOrders)
 止損/止盈 (SetStopLoss, SetTakeProfit, CancelStopLossOrders)
 市場數據 (GetMarketPrice)
 格式化工具 (FormatQuantity)

## ⚠️ TODO(完整實現階段)
- [ ] 完整認證令牌生成邏輯 (refreshAuthToken)
- [ ] 完整交易簽名邏輯(參考 Python SDK)
- [ ] 從 API 獲取幣種精度
- [ ] 區分止損/止盈訂單類型
- [ ] 前端 UI 支持
- [ ] 完整測試套件

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat: 完整集成 LIGHTER DEX with SDK

- 集成官方 lighter-go SDK (v0.0.0-20251104171447-78b9b55ebc48)
- 集成 Poseidon2 Goldilocks 簽名庫 (poseidon_crypto v0.0.11)
- 實現完整的 LighterTraderV2 使用官方 SDK
- 實現 17 個 Trader 接口方法(賬戶、交易、訂單管理)
- 支持雙密鑰系統(L1 錢包 + API Key)
- V1/V2 自動切換機制(向後兼容)
- 自動認證令牌管理(8小時有效期)
- 添加完整集成文檔 LIGHTER_INTEGRATION.md

新增文件:
- trader/lighter_trader_v2.go - V2 核心結構和初始化
- trader/lighter_trader_v2_account.go - 賬戶查詢方法
- trader/lighter_trader_v2_trading.go - 交易操作方法
- trader/lighter_trader_v2_orders.go - 訂單管理方法
- LIGHTER_INTEGRATION.md - 完整文檔

修改文件:
- trader/auto_trader.go - 添加 LighterAPIKeyPrivateKey 配置
- config/database.go - 添加 API Key 字段支持
- go.mod, go.sum - 添加 SDK 依賴

🤖 Generated with Claude Code

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(lighter): 實現完整 HTTP 調用與動態市場映射

### 實現的功能

#### 1. submitOrder() - 真實訂單提交
- 使用 POST /api/v1/sendTx 提交已簽名訂單
- tx_type: 14 (CREATE_ORDER)
- 價格保護機制 (price_protection)
- 完整錯誤處理與響應解析

#### 2. GetActiveOrders() - 查詢活躍訂單
- GET /api/v1/accountActiveOrders
- 使用認證令牌 (Authorization header)
- 支持按市場索引過濾

#### 3. CancelOrder() - 真實取消訂單
- 使用 SDK 簽名 CancelOrderTxReq
- POST /api/v1/sendTx with tx_type: 15 (CANCEL_ORDER)
- 自動 nonce 管理

#### 4. getMarketIndex() - 動態市場映射
- 從 GET /api/v1/orderBooks 獲取市場列表
- 內存緩存 (marketIndexMap) 提高性能
- 回退到硬編碼映射(API 失敗時)
- 線程安全 (sync.RWMutex)

### 技術實現

**數據結構**:
- SendTxRequest/SendTxResponse - sendTx 請求響應
- MarketInfo - 市場信息緩存

**並發安全**:
- marketMutex - 保護市場索引緩存
- 讀寫鎖優化性能

**錯誤處理**:
- API 失敗回退機制
- 詳細日誌記錄
- HTTP 狀態碼驗證

### 測試

 編譯通過 (CGO_ENABLED=1)
 所有 Trader 接口方法實現完整
 HTTP 調用格式符合 LIGHTER API 規範

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(lighter): 數據庫遷移與前端類型支持

### 數據庫變更

#### 新增欄位
- `exchanges.lighter_api_key_private_key` TEXT DEFAULT ''
- 支持 LIGHTER V2 的 40 字節 API Key 私鑰

#### 遷移腳本
- 📄 `migrations/002_add_lighter_api_key.sql`
- 包含完整的驗證和統計查詢
- 向後兼容現有配置(默認為空,使用 V1)

#### Schema 更新
- `config/database.go`:
  - 更新 CREATE TABLE 語句
  - 更新 exchanges_new 表結構
  - 新增 ALTER TABLE 遷移命令

### 前端類型更新

#### types.ts
- 新增 `Exchange` 接口字段:
  - `lighterWalletAddr?: string` - L1 錢包地址
  - `lighterPrivateKey?: string` - L1 私鑰
  - `lighterApiKeyPrivateKey?: string` - API Key 私鑰(新增)

### 技術細節

**數據庫兼容性**:
- 使用 ALTER TABLE ADD COLUMN IF NOT EXISTS
- 默認值為空字符串
- 不影響現有數據

**類型安全**:
- TypeScript 可選字段
- 與後端 ExchangeConfig 結構對齊

### 下一步

 **待完成**:
1. ExchangeConfigModal 組件更新
2. API 調用參數傳遞
3. V1/V2 狀態顯示

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* docs(lighter): 更新 LIGHTER_INTEGRATION.md 文檔狀態

* feat(lighter): 前端完整實現 - API Key 配置與 V1/V2 狀態

**英文**:
- `lighterWalletAddress`, `lighterPrivateKey`, `lighterApiKeyPrivateKey`
- `lighterWalletAddressDesc`, `lighterPrivateKeyDesc`, `lighterApiKeyPrivateKeyDesc`
- `lighterApiKeyOptionalNote` - V1 模式提示
- `lighterV1Description`, `lighterV2Description` - 狀態說明
- `lighterPrivateKeyImported` - 導入成功提示

**中文(繁體)**:
- 完整的中文翻譯對應
- 專業術語保留原文(L1、API Key、Poseidon2)

**Exchange 接口**:
- `lighterWalletAddr?: string`
- `lighterPrivateKey?: string`
- `lighterApiKeyPrivateKey?: string`

**UpdateExchangeConfigRequest 接口**:
- `lighter_wallet_addr?: string`
- `lighter_private_key?: string`
- `lighter_api_key_private_key?: string`

**狀態管理**:
- 添加 3 個 LIGHTER 狀態變量
- 更新 `secureInputTarget` 類型包含 'lighter'

**表單字段**:
- L1 錢包地址(必填,text input)
- L1 私鑰(必填,password + 安全輸入)
- API Key 私鑰(可選,password,40 字節)

**V1/V2 狀態顯示**:
- 動態背景顏色(V1: 橙色 #3F2E0F,V2: 綠色 #0F3F2E)
- 圖標指示(V1: ⚠️,V2: )
- 狀態說明文字

**驗證邏輯**:
- 必填字段:錢包地址 + L1 私鑰
- API Key 為可選字段
- 自動 V1/V2 檢測

**安全輸入**:
- 支持通過 TwoStageKeyModal 安全導入私鑰
- 導入成功後顯示 toast 提示

**handleSaveExchange**:
- 添加 3 個 LIGHTER 參數
- 更新交易所對象(新增/更新)
- 構建 API 請求(snake_case 字段)

**V1 模式(無 API Key)**:
```
┌────────────────────────────────────────┐
│ ⚠️ LIGHTER V1                          │
│ 基本模式 - 功能受限,僅用於測試框架       │
└────────────────────────────────────────┘
背景: #3F2E0F (橙色調)
邊框: #F59E0B (橙色)
```

**V2 模式(有 API Key)**:
```
┌────────────────────────────────────────┐
│  LIGHTER V2                          │
│ 完整模式 - 支持 Poseidon2 簽名和真實交易 │
└────────────────────────────────────────┘
背景: #0F3F2E (綠色調)
邊框: #10B981 (綠色)
```

1. **類型安全**
   - 完整的 TypeScript 類型定義
   - Props 接口正確對齊
   -  無 LIGHTER 相關編譯錯誤

2. **用戶體驗**
   - 清晰的必填/可選字段區分
   - 實時 V1/V2 狀態反饋
   - 安全私鑰輸入支持

3. **向後兼容**
   - 不影響現有交易所配置
   - 所有字段為可選(Optional)
   - API 請求格式統一

 TypeScript 編譯通過(無 LIGHTER 錯誤)
 類型定義完整且正確
 所有必需文件已更新
 與後端 API 格式對齊

Modified:
- `web/src/i18n/translations.ts` - 中英文翻譯
- `web/src/types.ts` - 類型定義
- `web/src/components/traders/ExchangeConfigModal.tsx` - Modal 組件
- `web/src/hooks/useTraderActions.ts` - Actions hook

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* test(lighter): 添加 V1 測試套件與修復 SafeFloat64 缺失

- 新增 trader/helpers.go: 添加 SafeFloat64/SafeString/SafeInt 輔助函數
- 新增 trader/lighter_trader_test.go: LIGHTER V1 測試套件
  -  測試通過 (7/10):
    - NewTrader 驗證 (無效私鑰, 有效私鑰格式)
    - FormatQuantity
    - GetExchangeType
    - InvalidQuantity 驗證
    - InvalidLeverage 驗證
    - HelperFunctions (SafeFloat64)
  - ⚠️ 待改進 (3/10):
    - GetBalance (需要調整 mock 響應格式)
    - GetPositions (需要調整 mock 響應格式)
    - GetMarketPrice (需要調整 mock 響應格式)

- 修復 Bug: lighter_account.go 和 lighter_trader_v2_account.go 中未定義的 SafeFloat64
- 測試框架: httptest.Server mock LIGHTER API
- 安全: 使用固定測試私鑰 (不含真實資金)

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-20 19:29:01 +08:00
tinkle-community
f1397c7891 update docs 2025-11-19 22:49:50 +08:00
Ember
3e19f7cc8c refactor(web): redesign httpClient with axios and unified error handling (#1061)
* fix(web): remove duplicate PasswordChecklist in error block

- Remove duplicate PasswordChecklist component from error message area
- Keep only the real-time password validation checklist
- Error block now displays only the error message text

Bug was introduced in commit aa0bd93 (PR #872)

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* refactor(web): redesign httpClient with axios and unified error handling

Major refactoring to improve error handling architecture:

## Changes

### 1. HTTP Client Redesign (httpClient.ts)
- Replaced native fetch with axios for better interceptor support
- Implemented request/response interceptors for centralized error handling
- Added automatic Bearer token injection in request interceptor
- Network errors and system errors (404, 403, 500) now intercepted and shown via toast
- Only business logic errors (4xx except 401/403/404) returned to caller
- New ApiResponse<T> interface for type-safe responses

### 2. API Migration (api.ts)
- Migrated all 31 API methods from legacy fetch-style to new httpClient
- Updated pattern: from `res.ok/res.json()` to `result.success/result.data`
- Removed getAuthHeaders() helper (token now auto-injected)
- Added TypeScript generics for better type safety

### 3. Component Updates
- AuthContext.tsx: Updated register() to use new API
- TraderConfigModal.tsx: Migrated 3 API calls (config, templates, balance)
- RegisterPage.tsx: Simplified error display (error type handling now in API layer)

### 4. Removed Legacy Code
- Removed legacyHttpClient compatibility wrapper (~30 lines)
- Removed legacyRequest() method
- Clean separation: API layer handles all error classification

## Benefits
- Centralized error handling - no need to check network/system errors in components
- Better UX - automatic toast notifications for system errors
- Type safety - generic ApiResponse<T> provides compile-time checks
- Cleaner business components - only handle business logic errors
- Consistent error messages across the application

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-17 14:48:14 +08:00
Ember
b690debf5e refactor(web): restructure AITradersPage into modular architecture (#1023)
* refactor(web): restructure AITradersPage into modular architecture

Refactored the massive 2652-line AITradersPage.tsx into a clean, modular architecture following React best practices.

**Changes:**
- Decomposed 2652-line component into 12 focused modules
- Introduced Zustand stores for config and modal state management
- Extracted all business logic into useTraderActions custom hook (633 lines)
- Created reusable section components (PageHeader, TradersGrid, etc.)
- Separated complex modal logic into dedicated components
- Added TraderConfig type, eliminated all any types
- Fixed critical bugs in configuredExchanges logic and getState() usage

**File Structure:**
- Main page reduced from 2652 → 234 lines (91% reduction)
- components/traders/: 7 UI components + 5 section components
- stores/: tradersConfigStore, tradersModalStore
- hooks/: useTraderActions (all business logic)

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* chore: ignore PR_DESCRIPTION.md

* fix(web): restore trader dashboard navigation functionality

Fixed missing navigation logic in refactored AITradersPage. The "查看" (View) button now correctly navigates to the trader dashboard.

**Root Cause:**
During refactoring, the `useNavigate` hook and default navigation logic were inadvertently omitted from the main page component.

**Changes:**
- Added `useNavigate` import from react-router-dom
- Implemented `handleTraderSelect` function with fallback navigation
- Restored original behavior: use `onTraderSelect` prop if provided, otherwise navigate to `/dashboard?trader=${traderId}`

**Testing:**
-  Click "查看" button navigates to trader dashboard
-  Query parameter correctly passed to dashboard

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(web): correct type definitions for trader configuration

Fixed TypeScript build errors by using the correct `TraderConfigData` type instead of the incorrect `TraderConfig` type.

**Root Cause:**
During refactoring, a new `TraderConfig` type was incorrectly created that extended `CreateTraderRequest` (with fields like `name`, `ai_model_id`). However, the `TraderConfigModal` component and API responses actually use `TraderConfigData` (with fields like `trader_name`, `ai_model`).

**Changes:**
- Replaced all `TraderConfig` references with `TraderConfigData`:
  - stores/tradersModalStore.ts
  - hooks/useTraderActions.ts
  - lib/api.ts
- Removed incorrect `TraderConfig` type definition from types.ts
- Added null check for `editingTrader.trader_id` to satisfy TypeScript

**Build Status:**
-  TypeScript compilation: PASS
-  Vite production build: PASS

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-15 22:21:09 -05:00
Diego
f23eaa534d fix(web): fix 401 unauthorized redirect not working properly (#997)
修复了token过期后页面一直遇到401错误、无法自动跳转登录页的问题

主要改动:
1. httpClient.ts
   - 去掉延迟跳转的setTimeout,改为立即跳转
   - 返回pending promise阻止SWR捕获401错误
   - 保存from401标记到sessionStorage,由登录页显示提示

2. LoginPage.tsx
   - 检测from401标记,显示"登录已过期"提示(永久显示)
   - 在登录成功时手动关闭过期提示toast
   - 支持管理员登录、普通登录、OTP验证三种场景

3. TraderConfigModal.tsx
   - 修复3处直接使用fetch()的问题,改为httpClient.get()
   - 确保所有API请求都经过统一的401拦截器

4. translations.ts
   - 添加sessionExpired的中英文翻译

修复效果:
- token过期时立即跳转登录页(无延迟)
- 登录页持续显示过期提示,直到用户登录成功或手动关闭
- 不会再看到401错误页面或重复的错误提示

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

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-15 22:20:06 -05:00
0xYYBB | ZYY | Bobo
79358d4776 fix(web): await mutateTraders() to eliminate 3-4s delay after operations (#989)
## Problem
When creating/editing/deleting traders, AI models, or exchanges, the UI
takes 3-4 seconds to show results, causing users to think the system is frozen.

## Root Cause
Although mutateTraders() was called after operations, it was not awaited,
causing the function to continue immediately without waiting for data refresh.
The UI relied on the refreshInterval: 5000 automatic refresh, resulting in
up to 5 seconds of delay.

## Solution
Added await before all mutateTraders() calls to ensure data is refreshed
before closing modals or showing success messages.

Changes:
- handleCreateTrader: Added await before mutateTraders()
- handleSaveEditTrader: Added await before mutateTraders()
- handleDeleteTrader: Added await before mutateTraders()
- handleToggleTrader: Added await before mutateTraders()

Impact:
- From 3-4s delay to immediate display (< 500ms)
- Significantly improved UX
- Consistent with AI model and exchange config behavior

Testing:
- Frontend build successful
- No TypeScript errors
- Ready for manual UI testing

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
2025-11-15 22:20:06 -05:00
Diego
fc8a4d3d63 fix(stats): fixed the PNL calculation (#963) 2025-11-15 22:20:06 -05:00
Lawrence Liu
10e6566947 feat(dashboard): 在交易者详情页显示系统提示词模板名称 (#775)
* feat(dashboard): display system prompt template and extract color constant

* style(api): format server.go with go fmt
2025-11-15 22:20:06 -05:00
Lawrence Liu
e497898ef1 feat: add whether to enable self registration toggle (#760)
* refactor(frontend): extract RegistrationDisabled as reusable component

- Create RegistrationDisabled component with i18n support
- Add registrationClosed and registrationClosedMessage translations
- Replace inline JSX in App.tsx with new component
- Improve code maintainability and reusability
- Add hover effect to back button for better UX

* fix(frontend): add registration toggle to LoginModal component

- Add useSystemConfig hook to LoginModal
- Conditionally render registration button based on registration_enabled config
- Ensures consistency with HeaderBar and LoginPage registration controls
- Completes registration toggle feature implementation across all entry points

* feat(frontend): add registration toggle UI support

- Add registration disabled page in App.tsx when registration is closed
- Hide registration link in LoginPage when registration is disabled
- Add registration_enabled field to SystemConfig interface
- Frontend conditionally shows/hides registration UI based on backend config

* feat: add registration toggle feature

Add system-level registration enable/disable control:
- Add registration_enabled config to system_config table (default: true)
- Add registration check in handleRegister API endpoint
- Expose registration_enabled status in /api/config endpoint
- Frontend can use this config to conditionally show/hide registration UI

This allows administrators to control user registration without code changes.

* fix(frontend): add registration toggle to HeaderBar and RegisterPage

- Add useSystemConfig hook and registrationEnabled check to HeaderBar
- Conditionally show/hide signup buttons in both desktop and mobile views
- Add registration check to RegisterPage to show RegistrationDisabled component
- This completes the registration toggle feature across all UI components

* test(frontend): add comprehensive unit tests for registration toggle feature

- Add RegistrationDisabled component tests (rendering, navigation, styling)
- Add registrationToggle logic tests (config handling, edge cases, multi-location consistency)
- Configure Vitest with jsdom environment for React component testing
- All 80 tests passing (9 new tests for RegistrationDisabled + 21 for toggle logic)
2025-11-15 22:18:57 -05:00
Icy
2a2aabf729 merge fix 2025-11-13 00:44:26 +08:00
Icy
190b0c29d4 merge dev 2025-11-12 23:40:58 +08:00
Icy
db9851b993 Merge branch 'dev' into beta
# Conflicts:
#	.github/workflows/docker-build.yml
#	.gitignore
#	api/server.go
#	config/config.go
#	config/database.go
#	decision/engine.go
#	docker-compose.yml
#	go.mod
#	go.sum
#	logger/telegram_sender.go
#	main.go
#	mcp/client.go
#	prompts/adaptive.txt
#	prompts/default.txt
#	prompts/nof1.txt
#	start.sh
#	trader/aster_trader.go
#	trader/auto_trader.go
#	trader/binance_futures.go
#	trader/hyperliquid_trader.go
#	web/package-lock.json
#	web/package.json
#	web/src/App.tsx
#	web/src/components/AILearning.tsx
#	web/src/components/AITradersPage.tsx
#	web/src/components/CompetitionPage.tsx
#	web/src/components/EquityChart.tsx
#	web/src/components/Header.tsx
#	web/src/components/LoginPage.tsx
#	web/src/components/RegisterPage.tsx
#	web/src/components/TraderConfigModal.tsx
#	web/src/components/TraderConfigViewModal.tsx
#	web/src/components/landing/FooterSection.tsx
#	web/src/components/landing/HeaderBar.tsx
#	web/src/contexts/AuthContext.tsx
#	web/src/i18n/translations.ts
#	web/src/lib/api.ts
#	web/src/lib/config.ts
#	web/src/types.ts
2025-11-12 23:20:25 +08:00
Ember
0ae3b4ed85 fix(web): unify password validation logic in RegisterPage (#943)
Remove duplicate password validation logic to ensure consistency.

Changes:
- Remove custom isStrongPassword function (RegisterPage.tsx:569-576)
- Use PasswordChecklist validation result (passwordValid state) instead
- Add comprehensive test suite with 28 test cases
- Configure Vitest with jsdom environment and setup file

Test Coverage:
- Password validation rules (length, uppercase, lowercase, number, special chars)
- Special character consistency (/[@#$%!&*?]/)
- Edge cases and boundary conditions
- Refactoring consistency verification

All 78 tests passing (25 + 25 + 28).

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

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-12 21:54:54 +08:00
0xYYBB | ZYY | Bobo
a36f92e0a7 fix: improve two-stage private key input UX (32+32 → 58+6 split) (#942)
## Problem

Users reported that the 32+32 character split design is not user-friendly:
1.  Second stage still requires entering 32 characters - hard to count
2.  Need to count many characters in both stages
3.  Easy to make mistakes when counting

## Solution

Change the split from 32+32 to **58+6**

**Stage 1**: 58 characters
- Enter the majority of the key (90%)
- Easy to copy/paste the prefix

**Stage 2**: 6 characters
-  Only need to count last 6 chars (very easy)
-  Quick verification of key suffix
-  Reduces user errors

## Changes

```typescript
// Old: Equal split
const expectedPart1Length = Math.ceil(expectedLength / 2)  // 32
const expectedPart2Length = expectedLength - expectedPart1Length  // 32

// New: Most of key + last 6 chars
const expectedPart1Length = expectedLength - 6  // 58
const expectedPart2Length = 6  // Last 6 characters
```

## Test plan

 Frontend builds successfully (npm run build)
 User-friendly: Only need to count 6 characters
 Maintains security: Two-stage input logic unchanged

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
2025-11-12 21:37:55 +08:00
0xYYBB | ZYY | Bobo
d259d40ba3 fix(web): fix button disabled validation to normalize 0x prefix (#937)
## Problem

PR #917 fixed the validation logic but missed fixing the button disabled state:

**Issue:**
- Button enabled/disabled check uses raw input length (includes "0x")
- Validation logic uses normalized length (excludes "0x")
- **Result:** Button can be enabled with insufficient hex characters

**Example scenario:**
1. User inputs: `0x` + 30 hex chars = 32 total chars
2. Button check: `32 < 32` → false →  Button enabled
3. User clicks button
4. Validation: normalized to 30 hex chars → `30 < 32` →  Error
5. Error message: "需要至少 32 個字符" (confusing!)

## Root Cause

**Lines 230 & 301**: Button disabled conditions don't normalize input

```typescript
//  Before: Checks raw length including "0x"
disabled={part1.length < expectedPart1Length || processing}
disabled={part2.length < expectedPart2Length}
```

## Solution

Normalize input before checking length in disabled conditions:

```typescript
//  After: Normalize before checking
disabled={
  (part1.startsWith('0x') ? part1.slice(2) : part1).length <
    expectedPart1Length || processing
}
disabled={
  (part2.startsWith('0x') ? part2.slice(2) : part2).length <
  expectedPart2Length
}
```

## Testing

| Input | Total Length | Normalized Length | Button (Before) | Button (After) | Click Result |
|-------|--------------|-------------------|-----------------|----------------|--------------|
| `0x` + 30 hex | 32 | 30 |  Enabled (bug) |  Disabled | N/A |
| `0x` + 32 hex | 34 | 32 |  Enabled |  Enabled |  Valid |
| 32 hex | 32 | 32 |  Enabled |  Enabled |  Valid |

## Impact

-  Button state now consistent with validation logic
-  Users won't see confusing "need 32 chars" errors when button is enabled
-  Better UX - button only enabled when input is truly valid

**Related:** Follow-up to PR #917

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

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-12 19:43:00 +08:00
0xYYBB | ZYY | Bobo
e920787d0b fix(web): add auth guards to prevent unauthorized API calls (#934)
Add `user && token` guard to all authenticated SWR calls to prevent
requests with `Authorization: Bearer null` when users refresh the page
before AuthContext finishes loading the token from localStorage.

## Problem

When users refresh the page:
1. React components mount immediately
2. SWR hooks fire API requests
3. AuthContext is still loading token from localStorage
4. Requests sent with `Authorization: Bearer null`
5. Backend returns 401 errors

This causes:
- Unnecessary 401 errors in backend logs
- Error messages in browser console
- Poor user experience on page refresh

## Solution

Add auth check to SWR key conditions using pattern:
```typescript
user && token && condition ? key : null
```

When `user` or `token` is null, SWR key becomes `null`, preventing the request.
Once AuthContext loads, SWR automatically revalidates and fetches data.

## Changes

**TraderDashboard.tsx** (5 auth guards added):
- status: `user && token && selectedTraderId ? 'status-...' : null`
- account: `user && token && selectedTraderId ? 'account-...' : null`
- positions: `user && token && selectedTraderId ? 'positions-...' : null`
- decisions: `user && token && selectedTraderId ? 'decisions/...' : null`
- stats: `user && token && selectedTraderId ? 'statistics-...' : null`

**EquityChart.tsx** (2 auth guards added + useAuth import):
- Import `useAuth` from '../contexts/AuthContext'
- Add `const { user, token } = useAuth()`
- history: `user && token && traderId ? 'equity-history-...' : null`
- account: `user && token && traderId ? 'account-...' : null`

**apiGuard.test.ts** (new file, 370 lines):
- Comprehensive unit tests covering all auth guard scenarios
- Tests for null user, null token, valid auth states
- Tests for all 7 SWR calls (5 in TraderDashboard + 2 in EquityChart)

## Testing

-  TypeScript compilation passed
-  Vite build passed (2.81s)
-  All modifications are additive (no logic changes)
-  SWR auto-revalidation ensures data loads after auth completes

## Benefits

1. **No more 401 errors on refresh**: Auth guards prevent premature requests
2. **Cleaner logs**: Backend no longer receives invalid Bearer null requests
3. **Better UX**: No error flashes in console on page load
4. **Consistent pattern**: All authenticated endpoints use same guard logic

## Context

This PR supersedes closed PR #881, which had conflicts due to PR #872
(frontend refactor with React Router). This implementation is based on
the latest upstream/dev with the new architecture.

Related: PR #881 (closed), PR #872 (Frontend Refactor)

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

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-12 17:56:36 +08:00
Ember
4934dd1168 feat(ui): Add an automated Web Crypto environment check (#908)
* feat: add web crypto environment check

* fix: auto check env

* refactor:  WebCryptoEnvironmentCheck  swtich to map
2025-11-11 21:22:55 -05:00
0xYYBB | ZYY | Bobo
d353cc2125 improve(web): improve UX messages for empty states and error feedback (#918)
## Problem

User-facing messages were too generic and uninformative:

1. **Dashboard empty state**:
   - Title: "No Traders Configured" (cold, technical)
   - Description: Generic message with no action guidance
   - Button: "Go to Traders Page" (unclear what happens next)

2. **Login error messages**:
   - "Login failed" (too vague - why did it fail?)
   - "Registration failed" (no guidance on what to do)
   - "OTP verification failed" (users don't know how to fix)

**Impact**: Users felt confused and frustrated, no clear next steps.

## Solution

### 1. Improve Dashboard Empty State
**File**: `web/src/i18n/translations.ts`

**Before**:
```typescript
dashboardEmptyTitle: 'No Traders Configured'
dashboardEmptyDescription: "You haven't created any AI traders yet..."
goToTradersPage: 'Go to Traders Page'
```

**After**:
```typescript
dashboardEmptyTitle: "Let's Get Started!"  //  Welcoming, encouraging
dashboardEmptyDescription: 'Create your first AI trader to automate your trading strategy. Connect an exchange, choose an AI model, and start trading in minutes!'  //  Clear steps
goToTradersPage: 'Create Your First Trader'  //  Clear action
```

**Changes**:
-  More welcoming tone ("Let's Get Started!")
-  Specific action steps (connect → choose → trade)
-  Time expectation ("in minutes")
-  Clear call-to-action button

---

### 2. Improve Error Messages
**File**: `web/src/i18n/translations.ts`

**Before**:
```typescript
loginFailed: 'Login failed'  //  No guidance
registrationFailed: 'Registration failed'  //  No guidance
verificationFailed: 'OTP verification failed'  //  No guidance
```

**After**:
```typescript
loginFailed: 'Login failed. Please check your email and password.'  //  Clear hint
registrationFailed: 'Registration failed. Please try again.'  //  Clear action
verificationFailed: 'OTP verification failed. Please check the code and try again.'  //  Clear steps
```

**Changes**:
-  Specific error hints (check email/password)
-  Clear remediation steps (try again, check code)
-  User-friendly tone

---

### 3. Chinese Translations
All improvements mirrored in Chinese:

**Dashboard**:
- Title: "开始使用吧!" (Let's get started!)
- Description: Clear 3-step guidance
- Button: "创建您的第一个交易员" (Create your first trader)

**Errors**:
- "登录失败,请检查您的邮箱和密码。"
- "注册失败,请重试。"
- "OTP 验证失败,请检查验证码后重试。"

---

## Impact

### User Experience Improvements

| Message Type | Before | After | Benefit |
|--------------|--------|-------|---------|
| **Empty dashboard** | Cold, technical | Welcoming, actionable |  Reduces confusion |
| **Login errors** | Vague | Specific hints |  Faster problem resolution |
| **Registration errors** | No guidance | Clear next steps |  Lower support burden |
| **OTP errors** | Confusing | Actionable |  Higher success rate |

### Tone Shift

**Before**: Technical, system-centric
- "No Traders Configured"
- "Login failed"

**After**: User-centric, helpful
- "Let's Get Started!"
- "Login failed. Please check your email and password."

---

## Testing

**Manual Testing**:
- [x] Empty dashboard displays new messages correctly
- [x] Login error shows improved message
- [x] Registration error shows improved message
- [x] OTP error shows improved message
- [x] Chinese translations display correctly
- [x] Button text updated appropriately

**Language Coverage**:
- [x] English 
- [x] Chinese 

---

## Files Changed

**1 frontend file**:
- `web/src/i18n/translations.ts` (+12 lines, -6 lines)

**Lines affected**:
- English: Lines 149-152, 461-464
- Chinese: Lines 950-953, 1227-1229

---

**By submitting this PR, I confirm:**

- [x] I have read the Contributing Guidelines
- [x] I agree to the Code of Conduct
- [x] My contribution is licensed under AGPL-3.0

---

🌟 **Thank you for reviewing!**

This PR improves user experience with clearer, more helpful messages.

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

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-11 21:21:07 -05:00
0xYYBB | ZYY | Bobo
d68714ed83 fix(web): restore missing system_prompt_template field in trader edit request (#922)
* fix(web): restore missing system_prompt_template in handleSaveEditTrader

修復編輯交易員時策略模板無法保存的問題。

Issue:
- 用戶編輯交易員時,選擇的策略模板(system_prompt_template)沒有被保存
- 重新打開編輯窗口,總是顯示默認值
- 用戶困惑為什麼策略模板無法持久化

Root Cause:
- PR #872 在 UI 重構時遺漏了 system_prompt_template 字段
- handleSaveEditTrader 的 request 對象缺少 system_prompt_template
- 導致更新請求不包含策略模板信息

Fix:
- 在 handleSaveEditTrader 的 request 對象中添加 system_prompt_template 字段
- 位置:override_base_prompt 之後,is_cross_margin 之前
- 與後端 API 和 TraderConfigModal 保持一致

Result:
- 編輯交易員時,策略模板正確保存
- 重新打開編輯窗口,顯示正確的已保存值
- 用戶可以成功切換和保存不同的策略模板

Technical Details:
- web/src/types.ts TraderConfigData 接口已有 system_prompt_template ✓
- Backend handleUpdateTrader 接收並保存 SystemPromptTemplate ✓
- Frontend TraderConfigModal 表單提交包含 system_prompt_template ✓
- Frontend handleSaveEditTrader request 缺失此字段 ✗ → ✓ (已修復)

Related:
- PR #872: UI 重構時遺漏
- commit c1f080f5: 原始添加 system_prompt_template 支持
- commit e58fc3c2: 修復 types.ts 缺失字段

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(types): add missing system_prompt_template field to TraderConfigData

補充完整修復:確保 TypeScript 類型定義與 API 使用一致。

Issue:
- AITradersPage.tsx 提交時包含 system_prompt_template 字段
- 但 TraderConfigData 接口缺少此字段定義
- TypeScript 類型不匹配

Fix:
- 在 TraderConfigData 接口添加 system_prompt_template: string
- 位置:override_base_prompt 之後,is_cross_margin 之前
- 與 CreateTraderRequest 保持一致

Result:
- TypeScript 類型完整
- 編輯交易員時正確加載和保存策略模板
- 無類型錯誤

Technical:
- web/src/types.ts Line 200
- 與後端 SystemPromptTemplate 字段對應

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-11 21:00:42 -05:00
0xYYBB | ZYY | Bobo
bc5eeb3e92 fix(ui): remove duplicate exchange configuration fields (Aster & Hyperliquid) (#921)
* fix(ui): remove duplicate Aster exchange form rendering

修復 Aster 交易所配置表單重複渲染問題。

Issue:
- Aster 表單代碼在 AITradersPage.tsx 中出現兩次(lines 2334 和 2559)
- 導致用戶界面顯示 6 個輸入欄位(應該是 3 個)
- 用戶體驗混亂

Fix:
- 刪除重複的 Aster 表單代碼塊(lines 2559-2710,共 153 行)
- 保留第一個表單塊(lines 2334-2419)
- 修復 prettier 格式問題

Result:
- Aster 配置現在正確顯示 3 個欄位:user, signer, private key
- Lint 檢查通過
- Hyperliquid Agent Wallet 翻譯已存在無需修改

Technical:
- 刪除了完全重複的 JSX 條件渲染塊
- 移除空白行以符合 prettier 規範

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(ui): remove legacy Hyperliquid single private key field

修復 Hyperliquid 配置頁面顯示舊版私鑰欄位的問題。

Issue:
- Hyperliquid 配置同時顯示舊版和新版欄位
- 舊版:單一「私钥」欄位(不安全,已廢棄)
- 新版:「代理私钥」+「主钱包地址」(Agent Wallet 安全模式)
- 用戶看到重複的欄位配置,造成混淆

Root Cause:
- AITradersPage.tsx 存在兩個 Hyperliquid 條件渲染塊
- Lines 2302-2332: 舊版單私鑰模式(應刪除)
- Lines 2424-2557: 新版 Agent Wallet 模式(正確)

Fix:
- 刪除舊版 Hyperliquid 單私鑰欄位代碼塊(lines 2302-2332,共 32 行)
- 保留新版 Agent Wallet 配置(代理私鑰 + 主錢包地址)
- 移除 `t('privateKey')` 和 `t('hyperliquidPrivateKeyDesc')` 舊版翻譯引用

Result:
- Hyperliquid 配置現在只顯示正確的 Agent Wallet 欄位
- 安全提示 banner 正確顯示
- 用戶體驗改善,不再混淆

Technical Details:
- 新版使用 `apiKey` 儲存 Agent Private Key
- 新版使用 `hyperliquidWalletAddr` 儲存 Main Wallet Address
- 符合 Hyperliquid Agent Wallet 最佳安全實踐

Related:
- 之前已修復 Aster 重複渲染問題(commit 5462eba0)
- Hyperliquid 翻譯 key 已存在於 translations.ts (lines 206-216, 1017-1027)

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(i18n): add missing Hyperliquid Agent Wallet translation keys

補充 Hyperliquid 代理錢包配置的翻譯文本,修復前端顯示 key 名稱的問題。

Changes:
- 新增 8 個英文翻譯 key (Agent Wallet 配置說明)
- 新增 8 個中文翻譯 key (代理錢包配置說明)
- 修正 Hyperliquid 配置頁面顯示問題(從顯示 key 名稱改為顯示翻譯文本)

Technical Details:
- hyperliquidAgentWalletTitle: Banner 標題
- hyperliquidAgentWalletDesc: 安全說明文字
- hyperliquidAgentPrivateKey: 代理私鑰欄位標籤
- hyperliquidMainWalletAddress: 主錢包地址欄位標籤
- 相應的 placeholder 和 description 文本

Related Issue: 用戶反饋前端顯示 key 名稱而非翻譯文本

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-11 20:59:57 -05:00
0xYYBB | ZYY | Bobo
e19463a924 fix(web): fix two-stage private key input validation to support 0x prefix (#917)
## Problem

Users entering private keys with "0x" prefix failed validation incorrectly:

**Scenario:**
- User inputs: `0x1234...` (34 characters including "0x")
- Expected part1 length: 32 characters
- **Bug**: Code checks `part1.length < 32` → `34 < 32` →  FALSE → "Key too long" error
- **Actual**: Should normalize to `1234...` (32 chars) →  Valid

**Impact:**
- Users cannot paste keys from wallets (most include "0x")
- Confusing UX - valid keys rejected
- Forces manual "0x" removal

## Root Cause

**File**: `web/src/components/TwoStageKeyModal.tsx`

**Lines 77-84** (handleStage1Next):
```typescript
//  Bug: Checks length before normalizing
if (part1.length < expectedPart1Length) {
  // Fails for "0x..." inputs
}
```

**Lines 132-143** (handleStage2Complete):
```typescript
//  Bug: Same issue
if (part2.length < expectedPart2Length) {
  // Fails for "0x..." inputs
}

//  Bug: Concatenates without normalizing part1
const fullKey = part1 + part2 // May have double "0x"
```

## Solution

### Fix 1: Normalize before validation
**Lines 77-79**:
```typescript
//  Normalize first, then validate
const normalized1 = part1.startsWith('0x') ? part1.slice(2) : part1
if (normalized1.length < expectedPart1Length) {
  // Now correctly handles both "0x..." and "1234..."
}
```

**Lines 134-136**:
```typescript
//  Same for part2
const normalized2 = part2.startsWith('0x') ? part2.slice(2) : part2
if (normalized2.length < expectedPart2Length) {
  // ...
}
```

### Fix 2: Normalize before concatenation
**Lines 145-147**:
```typescript
//  Remove "0x" from both parts before concatenating
const normalized1 = part1.startsWith('0x') ? part1.slice(2) : part1
const fullKey = normalized1 + normalized2
// Result: Always 64 characters without "0x"
```

## Testing

**Manual Test Cases:**

| Input Type | Part 1 | Part 2 | Before | After |
|------------|--------|--------|--------|-------|
| **No prefix** | `1234...` (32) | `5678...` (32) |  Pass |  Pass |
| **With prefix** | `0x1234...` (34) | `0x5678...` (34) |  Fail |  Pass |
| **Mixed** | `0x1234...` (34) | `5678...` (32) |  Fail |  Pass |
| **Both prefixed** | `0x1234...` (34) | `0x5678...` (34) |  Fail |  Pass |

**Validation consistency:**
- Before: `validatePrivateKeyFormat` normalizes, but input checks don't 
- After: Both normalize the same way 

## Impact

-  Users can paste keys directly from wallets
-  Supports both `0x1234...` and `1234...` formats
-  Consistent with `validatePrivateKeyFormat` logic
-  Better UX - no manual "0x" removal needed

**Files changed**: 1 frontend file
- web/src/components/TwoStageKeyModal.tsx (+6 lines, -2 lines)

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

Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-11 20:52:14 -05:00
Lawrence Liu
33b46e8092 feat: Add decision limit selector with 5/10/20/50 options (#638)
## Summary
Allow users to select the number of decision records to display (5/10/20/50)
in the Web UI, with persistent storage in localStorage.

## Changes
### Backend
- api/server.go: Add 'limit' query parameter support to /api/decisions/latest
  - Default: 5 (maintains current behavior)
  - Max: 50 (prevents excessive data loading)
  - Fully backward compatible

### Frontend
- web/src/lib/api.ts: Update getLatestDecisions() to accept limit parameter
- web/src/pages/TraderDashboard.tsx:
  - Add decisionLimit state management with localStorage persistence
  - Add dropdown selector UI (5/10/20/50 options)
  - Pass limit to API calls and update SWR cache key

## Time Coverage
- 5 records = 15 minutes (default, quick check)
- 10 records = 30 minutes (short-term review)
- 20 records = 1 hour (medium-term analysis)
- 50 records = 2.5 hours (deep pattern analysis)
2025-11-11 20:34:29 -05:00
Ember
e1f48e4d9b fix: fix build error (#895) 2025-11-11 15:36:12 +08:00
Ember
df618f39f6 Refactor(UI) : Refactor Frontend: Unified Toasts with Sonner, Introduced Layout System, and Integrated React Router (#872) 2025-11-10 23:19:17 -05:00
Ember
a05f0547c9 fix: 修复小屏幕设备上对话框高度过高无法滚动的问题 (#681) 2025-11-10 23:17:12 -05:00
Sue
80e49994f1 fix: 修复币安白名单IP复制功能失效问题 (#680)
## 🐛 问题描述
币安交易所配置页面中的服务器IP复制功能无法正常工作

## 🔍 根因分析
原始实现仅使用 navigator.clipboard.writeText() API:
- 在某些浏览器环境下不可用或被阻止
- 需要 HTTPS 或 localhost 环境
- 缺少错误处理和用户反馈

##  修复方案
1. **双重降级机制**:
   - 优先使用现代 Clipboard API
   - 降级到传统 execCommand 方法

2. **错误处理**:
   - 添加 try-catch 错误捕获
   - 失败时显示友好的错误提示
   - 提供IP地址供用户手动复制

3. **多语言支持**:
   - 添加 copyIPFailed 翻译键(中英文)

## 📝 修改文件
- web/src/components/AITradersPage.tsx
  - handleCopyIP 函数重构为异步函数
  - 添加双重复制机制和错误处理

- web/src/i18n/translations.ts
  - 添加 copyIPFailed 错误提示翻译

## 🧪 测试验证
 TypeScript 编译通过
 Vite 构建成功
 支持现代和传统浏览器环境

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

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-10 20:34:22 -05:00
0xYYBB | ZYY | Bobo
2fcfd8a299 fix(web): display '—' for missing data instead of NaN% or 0% (#678)
* fix(web): display '—' for missing data instead of NaN% or 0% (#633)

- Add hasValidData validation for null/undefined/NaN
- Display '—' for invalid trader.total_pnl_pct
- Only show gap calculations when both values are valid
- Prevents misleading users with 0% when data is missing

Fixes #633

* test(web): add comprehensive unit tests for CompetitionPage NaN handling

- Test data validation logic (null/undefined/NaN detection)
- Test gap calculation with valid and invalid data
- Test display formatting (shows '—' instead of 'NaN%')
- Test leading/trailing message display conditions
- Test edge cases (Infinity, very small/large numbers)

All 25 test cases passed, covering:
1. hasValidData check (7 cases): valid/null/undefined/NaN/zero/negative
2. gap calculation (3 cases): valid data, invalid data, negative gap
3. display formatting (6 cases): positive/negative/null/undefined/NaN/zero
4. leading/trailing messages (5 cases): conditional display logic
5. edge cases (4 cases): Infinity, -Infinity, very small/large numbers

Related to PR #678 - ensures missing data displays as '—' instead of 'NaN%'.

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: ZhouYongyou <128128010+zhouyongyou@users.noreply.github.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-10 20:30:03 -05:00
Deloz
b06861a14a fix(auth): 修复TraderConfigModal使用错误的token key (#882) 2025-11-10 12:44:34 -05:00
CoderMageFox
b15422c3f3 fix(auth): align PasswordChecklist special chars with validation logic (#860)
修复密码验证UI组件与验证逻辑之间的特殊字符不一致问题。

问题描述:
- PasswordChecklist组件默认接受所有特殊字符(如^_-~等)
- 实际验证函数isStrongPassword()仅接受@#$%!&*?共8个特殊字符
- 导致用户输入包含其他特殊字符时,UI显示绿色勾选但注册按钮仍禁用

修改内容:
- 在RegisterPage.tsx的PasswordChecklist组件添加specialCharsRegex属性
- 限制特殊字符为/[@#$%!&*?]/,与isStrongPassword()保持一致

影响范围:
- 仅影响注册页面的密码验证UI显示
- 不影响后端验证逻辑
- 提升用户体验,避免误导性的UI反馈

Closes #859

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

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-10 08:08:52 -07:00
0xYYBB | ZYY | Bobo
20dc80ed80 fix(web): remove circular dependency causing trading symbols input bug (#632) (#671)
**Problem:**
Unable to type comma-separated trading symbols in the input field.
When typing "BTCUSDT," → comma immediately disappears → cannot add more symbols.

**Root Cause:**
Circular state dependency between `useEffect` and `handleInputChange`:

```typescript
//  Lines 146-149: useEffect syncs selectedCoins → formData
useEffect(() => {
  const symbolsString = selectedCoins.join(',')
  setFormData(prev => ({ ...prev, trading_symbols: symbolsString }))
}, [selectedCoins])

// Lines 150-153: handleInputChange syncs formData → selectedCoins
if (field === 'trading_symbols') {
  const coins = value.split(',').map(...).filter(...)
  setSelectedCoins(coins)
}
```

**Execution Flow:**
1. User types: `"BTCUSDT,"`
2. `handleInputChange` fires → splits by comma → filters empty → `selectedCoins = ["BTCUSDT"]`
3. `useEffect` fires → joins → overwrites input to `"BTCUSDT"`  **Trailing comma removed!**
4. User cannot continue typing

**Solution:**
Remove the redundant `useEffect` (lines 146-149) and update `handleCoinToggle` to directly sync both states:

```typescript
//  handleCoinToggle now updates both states
const handleCoinToggle = (coin: string) => {
  setSelectedCoins(prev => {
    const newCoins = prev.includes(coin) ? ... : ...

    // Directly update formData.trading_symbols
    const symbolsString = newCoins.join(',')
    setFormData(current => ({ ...current, trading_symbols: symbolsString }))

    return newCoins
  })
}
```

**Why This Works:**
- **Quick selector buttons** (`handleCoinToggle`): Now updates both states 
- **Manual input** (`handleInputChange`): Already updates both states 
- **No useEffect interference**: User can type freely 

**Impact:**
-  Manual typing of comma-separated symbols now works
-  Quick selector buttons still work correctly
-  No circular dependency
-  Cleaner unidirectional data flow

Fixes #632

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

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-10 11:57:55 +08:00
0xYYBB | ZYY | Bobo
ffa89857d5 feat(web): improve trader config UX for initial balance and prompt templates (#629 #630) (#673)
- Add onBlur validation for initial_balance input to enforce minimum of 100
- Add detailed prompt template descriptions with i18n support
- Fix Traditional Chinese to Simplified Chinese
- Extract hardcoded Chinese text to i18n translation system
- Add translation keys for all prompt templates and descriptions

Fixes #629, Fixes #630
2025-11-10 11:55:40 +08:00
Ember
7855dc42c3 bugfix dashboard empty state (#709) 2025-11-09 14:44:42 +08:00
Lawrence Liu
1ea0d4c331 fix: 修复token过期未重新登录的问题 (#803)
* fix: 修复token过期未重新登录的问题

实现统一的401错误处理机制:
- 创建httpClient封装fetch API,添加响应拦截器
- 401时自动清理localStorage和React状态
- 显示"请先登录"提示并延迟1.5秒后跳转登录页
- 保存当前URL到sessionStorage用于登录后返回
- 改造所有API调用使用httpClient统一处理

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix: 添加401处理的单例保护防止并发竞态

问题:
- 多个API同时返回401会导致多个通知叠加
- 多个style元素被添加到DOM造成内存泄漏
- 可能触发多次登录页跳转

解决方案:
- 添加静态标志位 isHandling401 防止重复处理
- 第一个401触发完整处理流程
- 后续401直接抛出错误,避免重复操作
- 确保只显示一次通知和一次跳转

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix: 修复isHandling401标志永不重置的问题

问题:
- isHandling401标志在401处理后永不重置
- 导致用户重新登录后,后续401会被静默忽略
- 页面刷新或取消重定向后标志仍为true

解决方案:
- 在HttpClient中添加reset401Flag()公开方法
- 登录成功后调用reset401Flag()重置标志
- 页面加载时调用reset401Flag()确保新会话正常

影响范围:
- web/src/lib/httpClient.ts: 添加reset方法和导出函数
- web/src/contexts/AuthContext.tsx: 在登录和页面加载时重置

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(auth): consume returnUrl after successful login (BLOCKING-1)

修复登录后未跳转回原页面的问题。

问题:
- httpClient在401时保存returnUrl到sessionStorage
- 但登录成功后没有读取和使用returnUrl
- 导致用户登录后停留在登录页,无法回到原页面

修复:
- 在loginAdmin、verifyOTP、completeRegistration三个登录方法中
- 添加returnUrl检查和跳转逻辑
- 登录成功后优先跳转到returnUrl,如果没有则使用默认页面

影响:
- 用户token过期后重新登录,会自动返回之前访问的页面
- 提升用户体验,避免手动导航

测试场景:
1. 用户访问/traders → token过期 → 登录 → 自动回到/traders 
2. 用户直接访问/login → 登录 → 跳转到默认页面(/dashboard或/traders) 

Related: BLOCKING-1 in PR #803 code review

---------

Co-authored-by: sue <177699783@qq.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-09 12:18:47 +08:00
Ember
c25facc587 feat(ui): add password strength validation and toggle visibility in registration and reset password forms (#773)
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-09 00:36:28 +08:00
Icyoung
394dfce646 Dev api bugfix (#740)
* feat: remove admin mode

* feat: bugfix

* feat(crypto): 添加RSA-OAEP + AES-GCM混合加密服务

- 实现CryptoService加密服务,支持RSA-OAEP-2048 + AES-256-GCM混合加密
- 集成数据库层加密,自动加密存储敏感字段(API密钥、私钥等)
- 支持环境变量DATA_ENCRYPTION_KEY配置数据加密密钥
- 适配SQLite数据库加密存储(从PostgreSQL移植)
- 保持Hyperliquid代理钱包处理兼容性
- 更新.gitignore以正确处理crypto模块代码

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(scripts): 添加加密环境一键设置脚本

- setup_encryption.sh: 一键生成RSA密钥对+数据加密密钥+JWT密钥
- generate_rsa_keys.sh: 专业的RSA-2048密钥对生成工具
- generate_data_key.sh: 生成AES-256数据加密密钥和JWT认证密钥
- ENCRYPTION_README.md: 详细的加密系统说明文档
- 支持自动检测现有密钥并只生成缺失的密钥
- 完善的权限管理和安全验证
- 兼容macOS和Linux的跨平台支持

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(api): 添加加密API端点和Gin框架集成

- 新增CryptoHandler处理加密相关API请求
- 提供/api/crypto/public-key端点获取RSA公钥
- 提供/api/crypto/decrypt端点解密敏感数据
- 适配Gin框架的HTTP处理器格式
- 集成CryptoService到API服务器
- 支持前端加密数据传输和解密

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(web): 添加前端加密服务和两阶段密钥输入组件

- CryptoService: Web Crypto API集成,支持RSA-OAEP加密
- TwoStageKeyModal: 安全的两阶段私钥输入组件,支持剪贴板混淆
- 完善国际化翻译支持加密相关UI文本
- 修复TypeScript类型错误和编译问题
- 支持前端敏感数据加密传输到后端
- 增强用户隐私保护和数据安全

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(auth): 增强JWT认证安全性

- 优先使用环境变量JWT_SECRET而不是数据库配置
- 支持通过.env文件安全配置JWT认证密钥
- 保留数据库配置作为回退机制
- 改进JWT密钥来源日志显示
- 增强系统启动时的安全配置检查
- 支持运行时动态JWT密钥切换

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(docker): 集成加密环境变量到Docker部署

- 添加DATA_ENCRYPTION_KEY环境变量传递到容器
- 添加JWT_SECRET环境变量支持
- 挂载secrets目录使容器可访问RSA密钥文件
- 确保容器内加密服务正常工作
- 解决容器启动失败和加密初始化问题
- 完善Docker Compose加密环境配置

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(start): 集成自动加密环境检测和设置

- 增强check_encryption()函数检测JWT_SECRET和DATA_ENCRYPTION_KEY
- 自动运行setup_encryption.sh当检测到缺失密钥时
- 改进加密状态显示,包含RSA+AES+JWT全套加密信息
- 优化用户体验,提供清晰的加密配置反馈
- 支持一键设置完整加密环境
- 确保容器启动前加密环境就绪

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat: format fix

* fix(security): 修复前端模型和交易所配置敏感数据明文传输

- 在handleSaveModelConfig中对API密钥进行RSA-OAEP加密
- 在handleSaveExchangeConfig中对API密钥、Secret密钥和Aster私钥进行加密
- 只有非空敏感数据才进行加密处理
- 添加加密失败错误处理和用户友好提示
- 增加encryptionFailed翻译键的中英文支持
- 使用用户ID和会话ID作为加密上下文增强安全性

这修复了之前敏感数据在网络传输中以明文形式发送的安全漏洞。

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(crypto): 修复后端加密服务集成和缺失的加密端点

- 添加Server结构体缺少的cryptoService字段
- 实现handleUpdateModelConfigsEncrypted处理器用于模型配置加密传输
- 修复handleUpdateExchangeConfigsEncrypted中的函数调用
- 在前端API中添加updateModelConfigsEncrypted方法
- 统一RSA密钥路径从secrets/rsa_key改为keys/rsa_private.key
- 确保前端可以使用加密端点安全传输敏感数据
- 兼容原有加密通信模式和二段输入私钥功能

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(crypto): 完善加密端点配置,简化API结构

- 移除多余的/models/encrypted端点,模型配置暂不加密
- 确认/exchanges端点已强制要求加密传输
- 统一前端使用标准端点,自动使用加密传输
- 修复前端API调用,移除不存在的updateModelConfigsEncrypted引用
- 确保后端和前端编译成功,加密功能正常工作

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(crypto): 为模型配置端点添加加密传输支持

- 前端updateModelConfigs方法现在使用加密传输
- 后端/api/models端点已强制要求加密载荷
- 模型配置界面保持普通输入,在提交时自动加密
- 确保API密钥等敏感数据通过RSA+AES混合加密传输
- 前端后端编译测试通过,加密功能正常工作

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: icy <icyoung520@gmail.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-08 11:28:51 +08:00
Diego
ddb33c7f87 Fix(encryption)/aiconfig, exchange config and the encryption setup (#735) 2025-11-08 08:41:28 +08:00
Icyoung
57af6c00a3 Dev Crypto (#730)
* feat: remove admin mode

* feat: bugfix

* feat(crypto): 添加RSA-OAEP + AES-GCM混合加密服务

- 实现CryptoService加密服务,支持RSA-OAEP-2048 + AES-256-GCM混合加密
- 集成数据库层加密,自动加密存储敏感字段(API密钥、私钥等)
- 支持环境变量DATA_ENCRYPTION_KEY配置数据加密密钥
- 适配SQLite数据库加密存储(从PostgreSQL移植)
- 保持Hyperliquid代理钱包处理兼容性
- 更新.gitignore以正确处理crypto模块代码

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(scripts): 添加加密环境一键设置脚本

- setup_encryption.sh: 一键生成RSA密钥对+数据加密密钥+JWT密钥
- generate_rsa_keys.sh: 专业的RSA-2048密钥对生成工具
- generate_data_key.sh: 生成AES-256数据加密密钥和JWT认证密钥
- ENCRYPTION_README.md: 详细的加密系统说明文档
- 支持自动检测现有密钥并只生成缺失的密钥
- 完善的权限管理和安全验证
- 兼容macOS和Linux的跨平台支持

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(api): 添加加密API端点和Gin框架集成

- 新增CryptoHandler处理加密相关API请求
- 提供/api/crypto/public-key端点获取RSA公钥
- 提供/api/crypto/decrypt端点解密敏感数据
- 适配Gin框架的HTTP处理器格式
- 集成CryptoService到API服务器
- 支持前端加密数据传输和解密

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(web): 添加前端加密服务和两阶段密钥输入组件

- CryptoService: Web Crypto API集成,支持RSA-OAEP加密
- TwoStageKeyModal: 安全的两阶段私钥输入组件,支持剪贴板混淆
- 完善国际化翻译支持加密相关UI文本
- 修复TypeScript类型错误和编译问题
- 支持前端敏感数据加密传输到后端
- 增强用户隐私保护和数据安全

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(auth): 增强JWT认证安全性

- 优先使用环境变量JWT_SECRET而不是数据库配置
- 支持通过.env文件安全配置JWT认证密钥
- 保留数据库配置作为回退机制
- 改进JWT密钥来源日志显示
- 增强系统启动时的安全配置检查
- 支持运行时动态JWT密钥切换

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(docker): 集成加密环境变量到Docker部署

- 添加DATA_ENCRYPTION_KEY环境变量传递到容器
- 添加JWT_SECRET环境变量支持
- 挂载secrets目录使容器可访问RSA密钥文件
- 确保容器内加密服务正常工作
- 解决容器启动失败和加密初始化问题
- 完善Docker Compose加密环境配置

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat(start): 集成自动加密环境检测和设置

- 增强check_encryption()函数检测JWT_SECRET和DATA_ENCRYPTION_KEY
- 自动运行setup_encryption.sh当检测到缺失密钥时
- 改进加密状态显示,包含RSA+AES+JWT全套加密信息
- 优化用户体验,提供清晰的加密配置反馈
- 支持一键设置完整加密环境
- 确保容器启动前加密环境就绪

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* feat: format fix

* fix(security): 修复前端模型和交易所配置敏感数据明文传输

- 在handleSaveModelConfig中对API密钥进行RSA-OAEP加密
- 在handleSaveExchangeConfig中对API密钥、Secret密钥和Aster私钥进行加密
- 只有非空敏感数据才进行加密处理
- 添加加密失败错误处理和用户友好提示
- 增加encryptionFailed翻译键的中英文支持
- 使用用户ID和会话ID作为加密上下文增强安全性

这修复了之前敏感数据在网络传输中以明文形式发送的安全漏洞。

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

* fix(crypto): 修复后端加密服务集成和缺失的加密端点

- 添加Server结构体缺少的cryptoService字段
- 实现handleUpdateModelConfigsEncrypted处理器用于模型配置加密传输
- 修复handleUpdateExchangeConfigsEncrypted中的函数调用
- 在前端API中添加updateModelConfigsEncrypted方法
- 统一RSA密钥路径从secrets/rsa_key改为keys/rsa_private.key
- 确保前端可以使用加密端点安全传输敏感数据
- 兼容原有加密通信模式和二段输入私钥功能

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

Co-Authored-By: tinkle-community <tinklefund@gmail.com>

---------

Co-authored-by: icy <icyoung520@gmail.com>
Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-08 02:03:09 +08:00
web3gaoyutang
cd953abf5a refactor(AITradersPage): update model and exchange configuration checks (#728)
- Simplified the logic for determining configured models and exchanges by removing reliance on sensitive fields like apiKey.
- Enhanced filtering criteria to check for enabled status and non-sensitive fields, improving clarity and security.
- Updated UI class bindings to reflect the new configuration checks without compromising functionality.

This refactor aims to streamline the configuration process while ensuring sensitive information is not exposed.
2025-11-08 01:17:16 +08:00
Icyoung
f270bc3fee Dev remove admin mode (#723)
* feat: remove admin mode

* feat: bugfix

---------

Co-authored-by: icy <icyoung520@gmail.com>
2025-11-07 23:37:23 +08:00
0xYYBB | ZYY | Bobo
26fd9c261b feat(hyperliquid): enhance Agent Wallet security model (#717)
## Background

Hyperliquid official documentation recommends using Agent Wallet pattern for API trading:
- Agent Wallet is used for signing only
- Main Wallet Address is used for querying account data
- Agent Wallet should not hold significant funds

Reference: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/nonces-and-api-wallets

## Current Implementation

Current implementation allows auto-generating wallet address from private key,
which simplifies user configuration but may lead to potential security concerns
if users accidentally use their main wallet private key.

## Enhancement

Following the proven pattern already used in Aster exchange implementation
(which uses dual-address mode), this enhancement upgrades Hyperliquid to
Agent Wallet mode:

### Core Changes

1. **Mandatory dual-address configuration**
   - Agent Private Key (for signing)
   - Main Wallet Address (holds funds)

2. **Multi-layer security checks**
   - Detect if user accidentally uses main wallet private key
   - Validate Agent wallet balance (reject if > 100 USDC)
   - Provide detailed configuration guidance

3. **Design consistency**
   - Align with Aster's dual-address pattern
   - Follow Hyperliquid official best practices

### Code Changes

**config/database.go**:
- Add inline comments clarifying Agent Wallet security model

**trader/hyperliquid_trader.go**:
- Require explicit main wallet address (no auto-generation)
- Check if agent address matches main wallet address (security risk indicator)
- Query agent wallet balance and block if excessive
- Display both agent and main wallet addresses for transparency

**web/src/components/AITradersPage.tsx**:
- Add security alert banner explaining Agent Wallet mode
- Separate required inputs for Agent Private Key and Main Wallet Address
- Add field descriptions and validation

### Benefits

-  Aligns with Hyperliquid official security recommendations
-  Maintains design consistency with Aster implementation
-  Multi-layer protection against configuration mistakes
-  Detailed logging for troubleshooting

### Breaking Change

Users must now explicitly provide main wallet address (hyperliquid_wallet_addr).
Old configurations will receive clear error messages with migration guidance.

### Migration Guide

**Before** (single private key):
```json
{
  "hyperliquid_private_key": "0x..."
}
```

**After** (Agent Wallet mode):
```json
{
  "hyperliquid_private_key": "0x...",  // Agent Wallet private key
  "hyperliquid_wallet_addr": "0x..."   // Main Wallet address
}
```

Users can create Agent Wallet on Hyperliquid official website:
https://app.hyperliquid.xyz/ → Settings → API Wallets

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

Co-authored-by: tinkle-community <tinklefund@gmail.com>
2025-11-07 23:26:56 +08:00
0xbigtang
ae8dfc3cc2 fix: admin logout button visibility (#650) 2025-11-07 22:52:03 +08:00
icy
53512a2e2f feat: exchange scroll 2025-11-07 18:34:59 +08:00
icy
b89ccb1a36 Merge branch 'origin/beta' into nofxos/test
# Conflicts:
#	config/database_pg.go
2025-11-07 16:37:21 +08:00