+ {!editingExchangeId && (
+
+
+
+ {t('environmentSteps.checkTitle', language)}
-
- {selectedExchange.type.toUpperCase()} •{' '}
- {selectedExchange.id}
+
+
+
+
+ {t('environmentSteps.selectTitle', language)}
+
+
setSelectedExchangeId(e.target.value)}
+ className="w-full px-3 py-2 rounded"
+ style={{
+ background: '#0B0E11',
+ border: '1px solid #2B3139',
+ color: '#EAECEF',
+ }}
+ aria-label={t('selectExchange', language)}
+ disabled={webCryptoStatus !== 'secure'}
+ required
+ >
+
+ {t('pleaseSelectExchange', language)}
+
+ {availableExchanges.map((exchange) => (
+
+ {getShortName(exchange.name)} (
+ {exchange.type.toUpperCase()})
+
+ ))}
+
+
+
+ )}
+
+ {selectedExchange && (
+
+
+
+ {getExchangeIcon(selectedExchange.id, {
+ width: 32,
+ height: 32,
+ })}
+
+
+
+ {getShortName(selectedExchange.name)}
+
+
+ {selectedExchange.type.toUpperCase()} •{' '}
+ {selectedExchange.id}
+
-
- )}
+ )}
- {selectedExchange && (
- <>
- {/* Binance 和其他 CEX 交易所的字段 */}
- {(selectedExchange.id === 'binance' ||
- selectedExchange.type === 'cex') &&
- selectedExchange.id !== 'hyperliquid' &&
- selectedExchange.id !== 'aster' && (
- <>
- {/* 币安用户配置提示 (D1 方案) */}
- {selectedExchange.id === 'binance' && (
-
setShowBinanceGuide(!showBinanceGuide)}
- >
-
-
-
ℹ️
-
- 币安用户必读:
- 使用「现货与合约交易」API,不要用「统一账户 API」
+ {selectedExchange && (
+ <>
+ {/* Binance 和其他 CEX 交易所的字段 */}
+ {(selectedExchange.id === 'binance' ||
+ selectedExchange.type === 'cex') &&
+ selectedExchange.id !== 'hyperliquid' &&
+ selectedExchange.id !== 'aster' && (
+ <>
+ {/* 币安用户配置提示 (D1 方案) */}
+ {selectedExchange.id === 'binance' && (
+ setShowBinanceGuide(!showBinanceGuide)}
+ >
+
+
+ ℹ️
+
+ 币安用户必读:
+ 使用「现货与合约交易」API,不要用「统一账户
+ API」
+
+
+
+ {showBinanceGuide ? '▲' : '▼'}
-
- {showBinanceGuide ? '▲' : '▼'}
-
-
- {/* 展开的详细说明 */}
- {showBinanceGuide && (
- e.stopPropagation()}
- >
-
- 原因: 统一账户 API
- 权限结构不同,会导致订单提交失败
-
-
-
- 正确配置步骤:
-
-
-
- 登录币安 → 个人中心 → API 管理
-
-
- 创建 API → 选择「
- 系统生成的 API 密钥 」
-
-
- 勾选「现货与合约交易 」(
-
- 不选统一账户
-
- )
-
-
- IP 限制选「无限制 」或添加服务器
- IP
-
-
-
-
e.stopPropagation()}
>
- 💡 多资产模式用户注意:
- 如果您开启了多资产模式,将强制使用全仓模式。建议关闭多资产模式以支持逐仓交易。
-
+
+ 原因: 统一账户 API
+ 权限结构不同,会导致订单提交失败
+
-
- 📖 查看币安官方教程 ↗
-
-
- )}
-
- )}
+
+ 正确配置步骤:
+
+
+
+ 登录币安 → 个人中心 →{' '}
+ API 管理
+
+
+ 创建 API → 选择「
+ 系统生成的 API 密钥 」
+
+
+ 勾选「现货与合约交易 」(
+
+ 不选统一账户
+
+ )
+
+
+ IP 限制选「无限制
+ 」或添加服务器 IP
+
+
-
-
- {t('apiKey', language)}
-
- setApiKey(e.target.value)}
- placeholder={t('enterAPIKey', language)}
- className="w-full px-3 py-2 rounded"
- style={{
- background: '#0B0E11',
- border: '1px solid #2B3139',
- color: '#EAECEF',
- }}
- required
- />
-
+
+ 💡 多资产模式用户注意:
+ 如果您开启了多资产模式,将强制使用全仓模式。建议关闭多资产模式以支持逐仓交易。
+
-
-
- {t('secretKey', language)}
-
- setSecretKey(e.target.value)}
- placeholder={t('enterSecretKey', language)}
- className="w-full px-3 py-2 rounded"
- style={{
- background: '#0B0E11',
- border: '1px solid #2B3139',
- color: '#EAECEF',
- }}
- required
- />
-
+
+ 📖 查看币安官方教程 ↗
+
+
+ )}
+
+ )}
- {selectedExchange.id === 'okx' && (
- {t('passphrase', language)}
+ {t('apiKey', language)}
setPassphrase(e.target.value)}
- placeholder={t('enterPassphrase', language)}
+ value={apiKey}
+ onChange={(e) => setApiKey(e.target.value)}
+ placeholder={t('enterAPIKey', language)}
className="w-full px-3 py-2 rounded"
style={{
background: '#0B0E11',
@@ -2042,326 +2215,345 @@ function ExchangeConfigModal({
required
/>
- )}
- {/* Binance 白名单IP提示 */}
- {selectedExchange.id === 'binance' && (
-
-
+
- {t('whitelistIP', language)}
-
-
- {t('whitelistIPDesc', language)}
-
-
- {loadingIP ? (
-
- {t('loadingServerIP', language)}
-
- ) : serverIP && serverIP.public_ip ? (
-
-
- {serverIP.public_ip}
-
- handleCopyIP(serverIP.public_ip)}
- className="px-3 py-1 rounded text-xs font-semibold transition-all hover:scale-105"
- style={{
- background: 'rgba(240, 185, 11, 0.2)',
- color: '#F0B90B',
- }}
- >
- {copiedIP
- ? t('ipCopied', language)
- : t('copyIP', language)}
-
-
- ) : null}
+ {t('secretKey', language)}
+
+
setSecretKey(e.target.value)}
+ placeholder={t('enterSecretKey', language)}
+ className="w-full px-3 py-2 rounded"
+ style={{
+ background: '#0B0E11',
+ border: '1px solid #2B3139',
+ color: '#EAECEF',
+ }}
+ required
+ />
- )}
+
+ {selectedExchange.id === 'okx' && (
+
+
+ {t('passphrase', language)}
+
+ setPassphrase(e.target.value)}
+ placeholder={t('enterPassphrase', language)}
+ className="w-full px-3 py-2 rounded"
+ style={{
+ background: '#0B0E11',
+ border: '1px solid #2B3139',
+ color: '#EAECEF',
+ }}
+ required
+ />
+
+ )}
+
+ {/* Binance 白名单IP提示 */}
+ {selectedExchange.id === 'binance' && (
+
+
+ {t('whitelistIP', language)}
+
+
+ {t('whitelistIPDesc', language)}
+
+
+ {loadingIP ? (
+
+ {t('loadingServerIP', language)}
+
+ ) : serverIP && serverIP.public_ip ? (
+
+
+ {serverIP.public_ip}
+
+ handleCopyIP(serverIP.public_ip)}
+ className="px-3 py-1 rounded text-xs font-semibold transition-all hover:scale-105"
+ style={{
+ background: 'rgba(240, 185, 11, 0.2)',
+ color: '#F0B90B',
+ }}
+ >
+ {copiedIP
+ ? t('ipCopied', language)
+ : t('copyIP', language)}
+
+
+ ) : null}
+
+ )}
+ >
+ )}
+
+ {/* Aster 交易所的字段 */}
+ {selectedExchange.id === 'aster' && (
+ <>
+
+
+ {t('user', language)}
+
+
+
+
+ setAsterUser(e.target.value)}
+ placeholder={t('enterUser', language)}
+ className="w-full px-3 py-2 rounded"
+ style={{
+ background: '#0B0E11',
+ border: '1px solid #2B3139',
+ color: '#EAECEF',
+ }}
+ required
+ />
+
+
+
+
+ {t('signer', language)}
+
+
+
+
+ setAsterSigner(e.target.value)}
+ placeholder={t('enterSigner', language)}
+ className="w-full px-3 py-2 rounded"
+ style={{
+ background: '#0B0E11',
+ border: '1px solid #2B3139',
+ color: '#EAECEF',
+ }}
+ required
+ />
+
+
+
+
+ {t('privateKey', language)}
+
+
+
+
+ setAsterPrivateKey(e.target.value)}
+ placeholder={t('enterPrivateKey', language)}
+ className="w-full px-3 py-2 rounded"
+ style={{
+ background: '#0B0E11',
+ border: '1px solid #2B3139',
+ color: '#EAECEF',
+ }}
+ required
+ />
+
>
)}
- {/* Hyperliquid 交易所的字段 */}
- {selectedExchange.id === 'hyperliquid' && (
- <>
-
-
+ {/* 安全提示 banner */}
+
- {t('privateKey', language)}
-
-
-
-
-
setSecureInputTarget('hyperliquid')}
- className="px-3 py-2 rounded text-xs font-semibold transition-all hover:scale-105"
- style={{
- background: '#F0B90B',
- color: '#000',
- whiteSpace: 'nowrap',
- }}
- >
- {apiKey
- ? t('secureInputReenter', language)
- : t('secureInputButton', language)}
-
+
+
+ 🔐
+
+
+
+ {t('hyperliquidAgentWalletTitle', language)}
+
+
+ {t('hyperliquidAgentWalletDesc', language)}
+
+
+
+
+
+ {/* Agent Private Key 字段 */}
+
+
+ {t('hyperliquidAgentPrivateKey', language)}
+
+
+
+
+ setSecureInputTarget('hyperliquid')}
+ className="px-3 py-2 rounded text-xs font-semibold transition-all hover:scale-105"
+ style={{
+ background: '#F0B90B',
+ color: '#000',
+ whiteSpace: 'nowrap',
+ }}
+ >
+ {apiKey
+ ? t('secureInputReenter', language)
+ : t('secureInputButton', language)}
+
+ {apiKey && (
+ setApiKey('')}
+ className="px-3 py-2 rounded text-xs font-semibold transition-all hover:scale-105"
+ style={{
+ background: '#1B1F2B',
+ color: '#848E9C',
+ whiteSpace: 'nowrap',
+ }}
+ >
+ {t('secureInputClear', language)}
+
+ )}
+
{apiKey && (
-
setApiKey('')}
- className="px-3 py-2 rounded text-xs font-semibold transition-all hover:scale-105"
- style={{
- background: '#1B1F2B',
- color: '#848E9C',
- whiteSpace: 'nowrap',
- }}
- >
- {t('secureInputClear', language)}
-
+
+ {t('secureInputHint', language)}
+
)}
- {apiKey && (
-
- {t('secureInputHint', language)}
-
- )}
-
-
- {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',
- }}
- />
-
- 钱包地址通常由私钥自动生成,编辑时可查看或修改
-
-
- >
- )}
-
- {/* Aster 交易所的字段 */}
- {selectedExchange.id === 'aster' && (
- <>
-
-
- {t('user', language)}
-
-
-
-
- setAsterUser(e.target.value)}
- placeholder={t('enterUser', language)}
- className="w-full px-3 py-2 rounded"
- style={{
- background: '#0B0E11',
- border: '1px solid #2B3139',
- color: '#EAECEF',
- }}
- required
- />
-
-
-
-
- {t('signer', language)}
-
-
-
-
- setAsterSigner(e.target.value)}
- placeholder={t('enterSigner', language)}
- className="w-full px-3 py-2 rounded"
- style={{
- background: '#0B0E11',
- border: '1px solid #2B3139',
- color: '#EAECEF',
- }}
- required
- />
-
-
-
-
- {t('privateKey', language)}
-
-
-
-
-
-
-
-
setSecureInputTarget('aster')}
- className="px-3 py-2 rounded text-xs font-semibold transition-all hover:scale-105"
- style={{
- background: '#F0B90B',
- color: '#000',
- whiteSpace: 'nowrap',
- }}
- >
- {asterPrivateKey
- ? t('secureInputReenter', language)
- : t('secureInputButton', language)}
-
- {asterPrivateKey && (
-
setAsterPrivateKey('')}
- className="px-3 py-2 rounded text-xs font-semibold transition-all hover:scale-105"
- style={{
- background: '#1B1F2B',
- color: '#848E9C',
- whiteSpace: 'nowrap',
- }}
- >
- {t('secureInputClear', language)}
-
- )}
+
+ {t('hyperliquidAgentPrivateKeyDesc', language)}
- {asterPrivateKey && (
-
- {t('secureInputHint', language)}
-
- )}
-
- >
- )}
-
-
- setTestnet(e.target.checked)}
- className="form-checkbox rounded"
- style={{ accentColor: '#F0B90B' }}
- />
-
- {t('useTestnet', language)}
-
-
-
- {t('testnetDescription', language)}
-
-
+ {/* Main Wallet Address 字段 */}
+
+
+ {t('hyperliquidMainWalletAddress', language)}
+
+
+ setHyperliquidWalletAddr(e.target.value)
+ }
+ placeholder={t(
+ 'enterHyperliquidMainWalletAddress',
+ language
+ )}
+ className="w-full px-3 py-2 rounded"
+ style={{
+ background: '#0B0E11',
+ border: '1px solid #2B3139',
+ color: '#EAECEF',
+ }}
+ required
+ />
+
+ {t('hyperliquidMainWalletAddressDesc', language)}
+
+
+ >
+ )}
+ >
+ )}
+
-
-
-
- {' '}
- {t('securityWarning', language)}
-
-
-
- {selectedExchange.id === 'aster' && (
-
{t('asterUsdtWarning', language)}
- )}
-
{t('exchangeConfigWarning1', language)}
-
{t('exchangeConfigWarning2', language)}
-
{t('exchangeConfigWarning3', language)}
-
-
- >
- )}
-
-
{/* Binance Setup Guide Modal */}
@@ -2439,8 +2631,8 @@ function ExchangeConfigModal({
)}
-