From d55f5e293c5bf6bea4319cca3e53591200ce00f0 Mon Sep 17 00:00:00 2001 From: sue <177699783@qq.com> Date: Wed, 5 Nov 2025 21:36:37 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20enhance=20Exchange=20configuration=20sec?= =?UTF-8?q?urity=20and=20UI=20display=20=E4=BF=AE=E5=A4=8D=E4=BA=A4?= =?UTF-8?q?=E6=98=93=E6=89=80=E9=85=8D=E7=BD=AE=E7=9A=84=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E5=B9=B6=E5=8A=A0=E5=BC=BAAPI?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=AE=89=E5=85=A8=E6=80=A7=EF=BC=9A=20?= =?UTF-8?q?=F0=9F=8E=A8=20UI=E6=94=B9=E8=BF=9B=EF=BC=9A=20-=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BA=A4=E6=98=93=E6=89=80=E9=85=8D=E7=BD=AE=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E7=9A=84=E7=BC=96=E8=BE=91=E5=92=8C=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E9=80=BB=E8=BE=91=20-=20=E6=94=B9=E8=BF=9B=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E4=BA=A4=E6=98=93=E6=89=80=E9=85=8D=E7=BD=AE=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E7=9A=84=E4=BA=A4=E4=BA=92=E4=BD=93=E9=AA=8C=20=F0=9F=9B=A1?= =?UTF-8?q?=EF=B8=8F=20=E5=AE=89=E5=85=A8=E5=8A=A0=E5=9B=BA=EF=BC=9A=20-?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E4=BA=A4=E6=98=93=E6=89=80=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=8E=A5=E5=8F=A3=E4=B8=AD=E7=9A=84=E6=95=8F=E6=84=9F?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=B3=84=E9=9C=B2=E6=BC=8F=E6=B4=9E=20-=20ha?= =?UTF-8?q?ndleGetExchangeConfigs:=20=E6=B8=85=E7=A9=BA=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E4=B8=AD=E7=9A=84=E6=95=8F=E6=84=9F=E5=AF=86?= =?UTF-8?q?=E9=92=A5=20-=20handleGetSupportedExchanges:=20=E5=8A=A0?= =?UTF-8?q?=E5=9B=BA=E6=97=A0=E8=AE=A4=E8=AF=81=E5=85=AC=E5=BC=80=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=AE=89=E5=85=A8=E6=80=A7=20=F0=9F=93=8B=20=E5=AF=86?= =?UTF-8?q?=E9=92=A5=E8=BF=87=E6=BB=A4=E7=AD=96=E7=95=A5=EF=BC=9A=20-=20as?= =?UTF-8?q?ter:=20=E6=B8=85=E7=A9=BA=20asterPrivateKey=20=E7=A7=81?= =?UTF-8?q?=E9=92=A5=20-=20binance:=20=E6=B8=85=E7=A9=BA=20secretKey=20API?= =?UTF-8?q?=E5=AF=86=E9=92=A5=20-=20hyperliquid:=20=E6=B8=85=E7=A9=BA=20ap?= =?UTF-8?q?iKey=20API=E5=AF=86=E9=92=A5=20=F0=9F=94=92=20=E5=BD=B1?= =?UTF-8?q?=E5=93=8D=E8=8C=83=E5=9B=B4=EF=BC=9A=20-=20GET=20/api/exchanges?= =?UTF-8?q?=20(=E9=9C=80=E8=AE=A4=E8=AF=81)=20-=20GET=20/api/supported-exc?= =?UTF-8?q?hanges=20(=E5=85=AC=E5=BC=80=E6=8E=A5=E5=8F=A3)=20-=20=E4=BA=A4?= =?UTF-8?q?=E6=98=93=E6=89=80=E9=85=8D=E7=BD=AE=E5=89=8D=E7=AB=AF=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=20Co-Authored-By:=20tinkle-community=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/server.go | 30 ++++++++++++++++++++++++++++ web/src/components/AITradersPage.tsx | 15 ++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/api/server.go b/api/server.go index bb0a6eaf..e6463472 100644 --- a/api/server.go +++ b/api/server.go @@ -697,6 +697,21 @@ func (s *Server) handleGetExchangeConfigs(c *gin.Context) { } log.Printf("✅ 找到 %d 个交易所配置", len(exchanges)) + // 🛡️ 安全过滤:根据交易所类型清空对应的敏感密钥字段 + for _, exchange := range exchanges { + switch exchange.ID { + case "aster": + // Aster交易所:清空私钥 + exchange.AsterPrivateKey = "" + case "binance": + // Binance交易所:清空Secret Key + exchange.SecretKey = "" + case "hyperliquid": + // Hyperliquid交易所:清空API Key + exchange.APIKey = "" + } + } + c.JSON(http.StatusOK, exchanges) } @@ -1458,6 +1473,21 @@ func (s *Server) handleGetSupportedExchanges(c *gin.Context) { return } + // 🛡️ 安全过滤:根据交易所类型清空对应的敏感密钥字段(此接口无需认证,风险更高) + for _, exchange := range exchanges { + switch exchange.ID { + case "aster": + // Aster交易所:清空私钥 + exchange.AsterPrivateKey = "" + case "binance": + // Binance交易所:清空Secret Key + exchange.SecretKey = "" + case "hyperliquid": + // Hyperliquid交易所:清空API Key + exchange.APIKey = "" + } + } + c.JSON(http.StatusOK, exchanges) } diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index 6965d8f8..fa55704d 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -812,6 +812,7 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) { {showExchangeModal && ( Promise; onDelete: (exchangeId: string) => void; @@ -1171,8 +1174,12 @@ function ExchangeConfigModal({ const [asterSigner, setAsterSigner] = useState(''); const [asterPrivateKey, setAsterPrivateKey] = useState(''); - // 获取当前编辑的交易所信息 - const selectedExchange = allExchanges?.find(e => e.id === selectedExchangeId); + // 获取当前选择的交易所信息 + // 编辑模式:从 configuredExchanges 查找(包含用户配置的 apiKey、secretKey 等) + // 新增模式:从 allExchanges 查找(系统支持的交易所列表) + const selectedExchange = editingExchangeId + ? configuredExchanges?.find(e => e.id === selectedExchangeId) + : allExchanges?.find(e => e.id === selectedExchangeId); // 如果是编辑现有交易所,初始化表单数据 useEffect(() => { @@ -1181,10 +1188,10 @@ function ExchangeConfigModal({ setSecretKey(selectedExchange.secretKey || ''); setPassphrase(''); // Don't load existing passphrase for security setTestnet(selectedExchange.testnet || false); - + // Hyperliquid 字段 setHyperliquidWalletAddr(selectedExchange.hyperliquidWalletAddr || ''); - + // Aster 字段 setAsterUser(selectedExchange.asterUser || ''); setAsterSigner(selectedExchange.asterSigner || '');