Skip to content

Commit 70a6218

Browse files
authored
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 規範 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 5462eba) - Hyperliquid 翻譯 key 已存在於 translations.ts (lines 206-216, 1017-1027) 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 名稱而非翻譯文本 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>
1 parent 1e0da2e commit 70a6218

File tree

3 files changed

+30
-191
lines changed

3 files changed

+30
-191
lines changed

web/src/components/AITradersPage.tsx

Lines changed: 0 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,39 +2298,6 @@ function ExchangeConfigModal({
22982298
</>
22992299
)}
23002300

2301-
{/* Hyperliquid 交易所的字段 */}
2302-
{selectedExchange.id === 'hyperliquid' && (
2303-
<>
2304-
<div>
2305-
<label
2306-
className="block text-sm font-semibold mb-2"
2307-
style={{ color: '#EAECEF' }}
2308-
>
2309-
{t('privateKey', language)}
2310-
</label>
2311-
<input
2312-
type="password"
2313-
value={apiKey}
2314-
onChange={(e) => setApiKey(e.target.value)}
2315-
placeholder={t('enterPrivateKey', language)}
2316-
className="w-full px-3 py-2 rounded"
2317-
style={{
2318-
background: '#0B0E11',
2319-
border: '1px solid #2B3139',
2320-
color: '#EAECEF',
2321-
}}
2322-
required
2323-
/>
2324-
<div
2325-
className="text-xs mt-1"
2326-
style={{ color: '#848E9C' }}
2327-
>
2328-
{t('hyperliquidPrivateKeyDesc', language)}
2329-
</div>
2330-
</div>
2331-
</>
2332-
)}
2333-
23342301
{/* Aster 交易所的字段 */}
23352302
{selectedExchange.id === 'aster' && (
23362303
<>
@@ -2555,160 +2522,6 @@ function ExchangeConfigModal({
25552522
</div>
25562523
</>
25572524
)}
2558-
2559-
{/* Aster 交易所的字段 */}
2560-
{selectedExchange.id === 'aster' && (
2561-
<>
2562-
<div>
2563-
<label
2564-
className="block text-sm font-semibold mb-2 flex items-center gap-2"
2565-
style={{ color: '#EAECEF' }}
2566-
>
2567-
{t('user', language)}
2568-
<Tooltip content={t('asterUserDesc', language)}>
2569-
<HelpCircle
2570-
className="w-4 h-4 cursor-help"
2571-
style={{ color: '#F0B90B' }}
2572-
/>
2573-
</Tooltip>
2574-
</label>
2575-
<input
2576-
type="text"
2577-
value={asterUser}
2578-
onChange={(e) => setAsterUser(e.target.value)}
2579-
placeholder={t('enterUser', language)}
2580-
className="w-full px-3 py-2 rounded"
2581-
style={{
2582-
background: '#0B0E11',
2583-
border: '1px solid #2B3139',
2584-
color: '#EAECEF',
2585-
}}
2586-
required
2587-
/>
2588-
</div>
2589-
2590-
<div>
2591-
<label
2592-
className="block text-sm font-semibold mb-2 flex items-center gap-2"
2593-
style={{ color: '#EAECEF' }}
2594-
>
2595-
{t('signer', language)}
2596-
<Tooltip content={t('asterSignerDesc', language)}>
2597-
<HelpCircle
2598-
className="w-4 h-4 cursor-help"
2599-
style={{ color: '#F0B90B' }}
2600-
/>
2601-
</Tooltip>
2602-
</label>
2603-
<input
2604-
type="text"
2605-
value={asterSigner}
2606-
onChange={(e) => setAsterSigner(e.target.value)}
2607-
placeholder={t('enterSigner', language)}
2608-
className="w-full px-3 py-2 rounded"
2609-
style={{
2610-
background: '#0B0E11',
2611-
border: '1px solid #2B3139',
2612-
color: '#EAECEF',
2613-
}}
2614-
required
2615-
/>
2616-
</div>
2617-
2618-
<div>
2619-
<label
2620-
className="block text-sm font-semibold mb-2 flex items-center gap-2"
2621-
style={{ color: '#EAECEF' }}
2622-
>
2623-
{t('privateKey', language)}
2624-
<Tooltip content={t('asterPrivateKeyDesc', language)}>
2625-
<HelpCircle
2626-
className="w-4 h-4 cursor-help"
2627-
style={{ color: '#F0B90B' }}
2628-
/>
2629-
</Tooltip>
2630-
</label>
2631-
<div className="flex flex-col gap-2">
2632-
<div className="flex gap-2">
2633-
<input
2634-
type="text"
2635-
value={maskSecret(asterPrivateKey)}
2636-
readOnly
2637-
placeholder={t('enterPrivateKey', language)}
2638-
className="w-full px-3 py-2 rounded"
2639-
style={{
2640-
background: '#0B0E11',
2641-
border: '1px solid #2B3139',
2642-
color: '#EAECEF',
2643-
}}
2644-
/>
2645-
<button
2646-
type="button"
2647-
onClick={() => setSecureInputTarget('aster')}
2648-
className="px-3 py-2 rounded text-xs font-semibold transition-all hover:scale-105"
2649-
style={{
2650-
background: '#F0B90B',
2651-
color: '#000',
2652-
whiteSpace: 'nowrap',
2653-
}}
2654-
>
2655-
{asterPrivateKey
2656-
? t('secureInputReenter', language)
2657-
: t('secureInputButton', language)}
2658-
</button>
2659-
{asterPrivateKey && (
2660-
<button
2661-
type="button"
2662-
onClick={() => setAsterPrivateKey('')}
2663-
className="px-3 py-2 rounded text-xs font-semibold transition-all hover:scale-105"
2664-
style={{
2665-
background: '#1B1F2B',
2666-
color: '#848E9C',
2667-
whiteSpace: 'nowrap',
2668-
}}
2669-
>
2670-
{t('secureInputClear', language)}
2671-
</button>
2672-
)}
2673-
</div>
2674-
{asterPrivateKey && (
2675-
<div className="text-xs" style={{ color: '#848E9C' }}>
2676-
{t('secureInputHint', language)}
2677-
</div>
2678-
)}
2679-
</div>
2680-
</div>
2681-
2682-
<div
2683-
className="p-4 rounded"
2684-
style={{
2685-
background: 'rgba(240, 185, 11, 0.1)',
2686-
border: '1px solid rgba(240, 185, 11, 0.2)',
2687-
}}
2688-
>
2689-
<div
2690-
className="text-sm font-semibold mb-2"
2691-
style={{ color: '#F0B90B' }}
2692-
>
2693-
<span className="inline-flex items-center gap-1">
2694-
<AlertTriangle className="w-4 h-4" />{' '}
2695-
{t('securityWarning', language)}
2696-
</span>
2697-
</div>
2698-
<div
2699-
className="text-xs space-y-1"
2700-
style={{ color: '#848E9C' }}
2701-
>
2702-
{selectedExchange.id === 'aster' && (
2703-
<div>{t('asterUsdtWarning', language)}</div>
2704-
)}
2705-
<div>{t('exchangeConfigWarning1', language)}</div>
2706-
<div>{t('exchangeConfigWarning2', language)}</div>
2707-
<div>{t('exchangeConfigWarning3', language)}</div>
2708-
</div>
2709-
</div>
2710-
</>
2711-
)}
27122525
</>
27132526
)}
27142527
</div>

web/src/i18n/translations.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,18 @@ export const translations = {
202202
'Hyperliquid uses private key for trading authentication',
203203
hyperliquidWalletAddressDesc:
204204
'Wallet address corresponding to the private key',
205+
// Hyperliquid Agent Wallet (New Security Model)
206+
hyperliquidAgentWalletTitle: 'Hyperliquid Agent Wallet Configuration',
207+
hyperliquidAgentWalletDesc:
208+
'Use Agent Wallet for secure trading: Agent wallet signs transactions (balance ~0), Main wallet holds funds (never expose private key)',
209+
hyperliquidAgentPrivateKey: 'Agent Private Key',
210+
enterHyperliquidAgentPrivateKey: 'Enter Agent wallet private key',
211+
hyperliquidAgentPrivateKeyDesc:
212+
'Agent wallet private key for signing transactions (keep balance near 0 for security)',
213+
hyperliquidMainWalletAddress: 'Main Wallet Address',
214+
enterHyperliquidMainWalletAddress: 'Enter Main wallet address',
215+
hyperliquidMainWalletAddressDesc:
216+
'Main wallet address that holds your trading funds (never expose its private key)',
205217
asterUserDesc:
206218
'Main wallet address - The EVM wallet address you use to log in to Aster (Note: Only EVM wallets are supported, Solana wallets are not supported)',
207219
asterSignerDesc:
@@ -1000,6 +1012,18 @@ export const translations = {
10001012
enterPassphrase: '输入Passphrase (OKX必填)',
10011013
hyperliquidPrivateKeyDesc: 'Hyperliquid 使用私钥进行交易认证',
10021014
hyperliquidWalletAddressDesc: '与私钥对应的钱包地址',
1015+
// Hyperliquid 代理钱包 (新安全模型)
1016+
hyperliquidAgentWalletTitle: 'Hyperliquid 代理钱包配置',
1017+
hyperliquidAgentWalletDesc:
1018+
'使用代理钱包安全交易:代理钱包用于签名(餘額~0),主钱包持有资金(永不暴露私钥)',
1019+
hyperliquidAgentPrivateKey: '代理私钥',
1020+
enterHyperliquidAgentPrivateKey: '输入代理钱包私钥',
1021+
hyperliquidAgentPrivateKeyDesc:
1022+
'代理钱包私钥,用于签名交易(为了安全应保持余额接近0)',
1023+
hyperliquidMainWalletAddress: '主钱包地址',
1024+
enterHyperliquidMainWalletAddress: '输入主钱包地址',
1025+
hyperliquidMainWalletAddressDesc:
1026+
'持有交易资金的主钱包地址(永不暴露其私钥)',
10031027
asterUserDesc:
10041028
'主钱包地址 - 您用于登录 Aster 的 EVM 钱包地址(注意:仅支持 EVM 钱包,不支持 Solana 钱包)',
10051029
asterSignerDesc:
@@ -1080,9 +1104,11 @@ export const translations = {
10801104
promptTemplateNof1: 'NoF1 英文框架',
10811105
promptTemplateTaroLong: 'Taro 长仓',
10821106
promptDescDefault: '📊 默认稳健策略',
1083-
promptDescDefaultContent: '最大化夏普比率,平衡风险收益,适合新手和长期稳定交易',
1107+
promptDescDefaultContent:
1108+
'最大化夏普比率,平衡风险收益,适合新手和长期稳定交易',
10841109
promptDescAdaptive: '🛡️ 保守策略 (v6.0.0)',
1085-
promptDescAdaptiveContent: '严格风控,BTC 强制确认,高胜率优先,适合保守型交易者',
1110+
promptDescAdaptiveContent:
1111+
'严格风控,BTC 强制确认,高胜率优先,适合保守型交易者',
10861112
promptDescAdaptiveRelaxed: '⚡ 激进策略 (v6.0.0)',
10871113
promptDescAdaptiveRelaxedContent:
10881114
'高频交易,BTC 可选确认,追求交易机会,适合波动市场',
@@ -1092,7 +1118,8 @@ export const translations = {
10921118
promptDescNof1Content:
10931119
'Hyperliquid 交易所专用,英文提示词,风险调整回报最大化',
10941120
promptDescTaroLong: '📈 Taro 长仓策略',
1095-
promptDescTaroLongContent: '数据驱动决策,多维度验证,持续学习进化,长仓专用',
1121+
promptDescTaroLongContent:
1122+
'数据驱动决策,多维度验证,持续学习进化,长仓专用',
10961123

10971124
// Loading & Error
10981125
loading: '加载中...',

web/src/lib/api.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ export const api = {
157157
if (!res.ok) throw new Error('更新模型配置失败')
158158
},
159159

160-
161160
// 交易所配置接口
162161
async getExchangeConfigs(): Promise<Exchange[]> {
163162
const res = await httpClient.get(`${API_BASE}/exchanges`, getAuthHeaders())

0 commit comments

Comments
 (0)