diff --git a/config/database.go b/config/database.go index 3749df4d..f5b6cc8c 100644 --- a/config/database.go +++ b/config/database.go @@ -742,6 +742,48 @@ func (d *Database) GetExchanges(userID string) ([]*ExchangeConfig, error) { return exchanges, nil } +// GetExchangesForAPI 获取交易所配置(专用于API返回,排除敏感字段) +func (d *Database) GetExchangesForAPI(userID string) ([]*ExchangeConfig, error) { + rows, err := d.db.Query(` + SELECT id, user_id, name, type, enabled, + CASE + WHEN type = 'hyperliquid' THEN '' + ELSE COALESCE(api_key, '') + END as api_key, + '' as secret_key, + testnet, + COALESCE(hyperliquid_wallet_addr, '') as hyperliquid_wallet_addr, + COALESCE(aster_user, '') as aster_user, + COALESCE(aster_signer, '') as aster_signer, + '' as aster_private_key, + created_at, updated_at + FROM exchanges WHERE user_id = ? ORDER BY id + `, userID) + if err != nil { + return nil, err + } + defer rows.Close() + + // 初始化为空切片而不是nil,确保JSON序列化为[]而不是null + exchanges := make([]*ExchangeConfig, 0) + for rows.Next() { + var exchange ExchangeConfig + err := rows.Scan( + &exchange.ID, &exchange.UserID, &exchange.Name, &exchange.Type, + &exchange.Enabled, &exchange.APIKey, &exchange.SecretKey, &exchange.Testnet, + &exchange.HyperliquidWalletAddr, &exchange.AsterUser, + &exchange.AsterSigner, &exchange.AsterPrivateKey, + &exchange.CreatedAt, &exchange.UpdatedAt, + ) + if err != nil { + return nil, err + } + exchanges = append(exchanges, &exchange) + } + + return exchanges, nil +} + // UpdateExchange 更新交易所配置,如果不存在则创建用户特定配置 func (d *Database) UpdateExchange(userID, id string, enabled bool, apiKey, secretKey string, testnet bool, hyperliquidWalletAddr, asterUser, asterSigner, asterPrivateKey string) error { log.Printf("🔧 UpdateExchange: userID=%s, id=%s, enabled=%v", userID, id, enabled) diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index b691bb2f..e7184224 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -1092,6 +1092,7 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) { {showExchangeModal && ( e.id === selectedExchangeId - ) + // 获取当前选择的交易所信息 + // 编辑模式:从 configuredExchanges 查找(包含用户配置的 apiKey、secretKey 等) + // 新增模式:从 allExchanges 查找(系统支持的交易所列表) + const selectedExchange = editingExchangeId + ? configuredExchanges?.find(e => e.id === selectedExchangeId) + : allExchanges?.find(e => e.id === selectedExchangeId); // 如果是编辑现有交易所,初始化表单数据 useEffect(() => { @@ -1618,6 +1626,9 @@ function ExchangeConfigModal({ setPassphrase('') // Don't load existing passphrase for security setTestnet(selectedExchange.testnet || false) + // Hyperliquid 字段 + setHyperliquidWalletAddr(selectedExchange.hyperliquidWalletAddr || '') + // Aster 字段 setAsterUser(selectedExchange.asterUser || '') setAsterSigner(selectedExchange.asterSigner || '') @@ -2069,6 +2080,29 @@ function ExchangeConfigModal({
{t('hyperliquidPrivateKeyDesc', language)}
+ +
+ + setHyperliquidWalletAddr(e.target.value)} + placeholder="钱包地址(可选,通常由私钥自动生成)" + className="w-full px-3 py-2 rounded" + style={{ + background: '#0B0E11', + border: '1px solid #2B3139', + color: '#EAECEF', + }} + /> +
+ 钱包地址通常由私钥自动生成,编辑时可查看或修改 +
)}