mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-06-06 05:51:19 +08:00
Fix(encryption)/aiconfig, exchange config and the encryption setup (#735)
This commit is contained in:
102
api/server.go
102
api/server.go
@@ -413,9 +413,9 @@ type SafeExchangeConfig struct {
|
||||
Type string `json:"type"` // "cex" or "dex"
|
||||
Enabled bool `json:"enabled"`
|
||||
Testnet bool `json:"testnet,omitempty"`
|
||||
HyperliquidWalletAddr string `json:"hyperliquid_wallet_addr"` // Hyperliquid钱包地址(不敏感)
|
||||
AsterUser string `json:"aster_user"` // Aster用户名(不敏感)
|
||||
AsterSigner string `json:"aster_signer"` // Aster签名者(不敏感)
|
||||
HyperliquidWalletAddr string `json:"hyperliquidWalletAddr"` // Hyperliquid钱包地址(不敏感)
|
||||
AsterUser string `json:"asterUser"` // Aster用户名(不敏感)
|
||||
AsterSigner string `json:"asterSigner"` // Aster签名者(不敏感)
|
||||
}
|
||||
|
||||
type UpdateModelConfigRequest struct {
|
||||
@@ -1014,15 +1014,53 @@ func (s *Server) handleGetModelConfigs(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, safeModels)
|
||||
}
|
||||
|
||||
// handleUpdateModelConfigs 更新AI模型配置
|
||||
// handleUpdateModelConfigs 更新AI模型配置(仅支持加密数据)
|
||||
func (s *Server) handleUpdateModelConfigs(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
var req UpdateModelConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
|
||||
// 读取原始请求体
|
||||
bodyBytes, err := c.GetRawData()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "读取请求体失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 解析加密的 payload
|
||||
var encryptedPayload crypto.EncryptedPayload
|
||||
if err := json.Unmarshal(bodyBytes, &encryptedPayload); err != nil {
|
||||
log.Printf("❌ 解析加密载荷失败: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "请求格式错误,必须使用加密传输"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证是否为加密数据
|
||||
if encryptedPayload.WrappedKey == "" {
|
||||
log.Printf("❌ 检测到非加密请求 (UserID: %s)", userID)
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "此接口仅支持加密传输,请使用加密客户端",
|
||||
"code": "ENCRYPTION_REQUIRED",
|
||||
"message": "Encrypted transmission is required for security reasons",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 解密数据
|
||||
decrypted, err := s.cryptoHandler.cryptoService.DecryptSensitiveData(&encryptedPayload)
|
||||
if err != nil {
|
||||
log.Printf("❌ 解密模型配置失败 (UserID: %s): %v", userID, err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "解密数据失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 解析解密后的数据
|
||||
var req UpdateModelConfigRequest
|
||||
if err := json.Unmarshal([]byte(decrypted), &req); err != nil {
|
||||
log.Printf("❌ 解析解密数据失败: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "解析解密数据失败"})
|
||||
return
|
||||
}
|
||||
log.Printf("🔓 已解密模型配置数据 (UserID: %s)", userID)
|
||||
|
||||
// 更新每个模型的配置
|
||||
for modelID, modelData := range req.Models {
|
||||
err := s.database.UpdateAIModel(userID, modelID, modelData.Enabled, modelData.APIKey, modelData.CustomAPIURL, modelData.CustomModelName)
|
||||
@@ -1033,7 +1071,7 @@ func (s *Server) handleUpdateModelConfigs(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 重新加载该用户的所有交易员,使新配置立即生效
|
||||
err := s.traderManager.LoadUserTraders(s.database, userID)
|
||||
err = s.traderManager.LoadUserTraders(s.database, userID)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 重新加载用户交易员到内存失败: %v", err)
|
||||
// 这里不返回错误,因为模型配置已经成功更新到数据库
|
||||
@@ -1073,15 +1111,53 @@ func (s *Server) handleGetExchangeConfigs(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, safeExchanges)
|
||||
}
|
||||
|
||||
// handleUpdateExchangeConfigs 更新交易所配置
|
||||
// handleUpdateExchangeConfigs 更新交易所配置(仅支持加密数据)
|
||||
func (s *Server) handleUpdateExchangeConfigs(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
var req UpdateExchangeConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
|
||||
// 读取原始请求体
|
||||
bodyBytes, err := c.GetRawData()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "读取请求体失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 解析加密的 payload
|
||||
var encryptedPayload crypto.EncryptedPayload
|
||||
if err := json.Unmarshal(bodyBytes, &encryptedPayload); err != nil {
|
||||
log.Printf("❌ 解析加密载荷失败: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "请求格式错误,必须使用加密传输"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证是否为加密数据
|
||||
if encryptedPayload.WrappedKey == "" {
|
||||
log.Printf("❌ 检测到非加密请求 (UserID: %s)", userID)
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "此接口仅支持加密传输,请使用加密客户端",
|
||||
"code": "ENCRYPTION_REQUIRED",
|
||||
"message": "Encrypted transmission is required for security reasons",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 解密数据
|
||||
decrypted, err := s.cryptoHandler.cryptoService.DecryptSensitiveData(&encryptedPayload)
|
||||
if err != nil {
|
||||
log.Printf("❌ 解密交易所配置失败 (UserID: %s): %v", userID, err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "解密数据失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 解析解密后的数据
|
||||
var req UpdateExchangeConfigRequest
|
||||
if err := json.Unmarshal([]byte(decrypted), &req); err != nil {
|
||||
log.Printf("❌ 解析解密数据失败: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "解析解密数据失败"})
|
||||
return
|
||||
}
|
||||
log.Printf("🔓 已解密交易所配置数据 (UserID: %s)", userID)
|
||||
|
||||
// 更新每个交易所的配置
|
||||
for exchangeID, exchangeData := range req.Exchanges {
|
||||
err := s.database.UpdateExchange(userID, exchangeID, exchangeData.Enabled, exchangeData.APIKey, exchangeData.SecretKey, exchangeData.Testnet, exchangeData.HyperliquidWalletAddr, exchangeData.AsterUser, exchangeData.AsterSigner, exchangeData.AsterPrivateKey)
|
||||
@@ -1092,7 +1168,7 @@ func (s *Server) handleUpdateExchangeConfigs(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 重新加载该用户的所有交易员,使新配置立即生效
|
||||
err := s.traderManager.LoadUserTraders(s.database, userID)
|
||||
err = s.traderManager.LoadUserTraders(s.database, userID)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 重新加载用户交易员到内存失败: %v", err)
|
||||
// 这里不返回错误,因为交易所配置已经成功更新到数据库
|
||||
|
||||
@@ -58,16 +58,16 @@ echo -e " • 私钥文件: ${YELLOW}$PRIVATE_KEY_FILE${NC}"
|
||||
echo -e " • 公钥文件: ${YELLOW}$PUBLIC_KEY_FILE${NC}"
|
||||
echo -e " • AES密钥: ${YELLOW}256 bits (自动生成)${NC}"
|
||||
|
||||
# 询问用户确认
|
||||
# 显示必要性说明
|
||||
echo
|
||||
read -p "是否继续设置加密环境? [Y/n]: " -n 1 -r
|
||||
echo -e "${YELLOW}⚠️ 加密环境是系统运行的必需条件(不可跳过)${NC}"
|
||||
echo -e "${BLUE}ℹ️ 将自动检查并生成以下密钥:${NC}"
|
||||
echo -e " • RSA-2048 密钥对 (用于传输加密)"
|
||||
echo -e " • AES-256 数据加密密钥 (用于数据库加密)"
|
||||
echo -e " • JWT 认证密钥 (用于用户认证)"
|
||||
echo -e "${BLUE}ℹ️ 如果密钥已存在,将保持现有密钥;如果缺失,将自动生成${NC}"
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||
echo -e "${BLUE}ℹ️ 操作已取消${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "${CYAN}🚀 开始设置加密环境...${NC}"
|
||||
|
||||
# ============= 步骤1: 创建目录 =============
|
||||
@@ -94,20 +94,20 @@ echo
|
||||
echo -e "${YELLOW}🔐 步骤 2/4: 生成 RSA-$RSA_KEY_SIZE 密钥对...${NC}"
|
||||
|
||||
# 检查现有RSA密钥
|
||||
if [ -f "$PRIVATE_KEY_FILE" ] || [ -f "$PUBLIC_KEY_FILE" ]; then
|
||||
echo -e "${YELLOW}⚠️ 检测到现有的RSA密钥文件${NC}"
|
||||
read -p "是否重新生成RSA密钥? [y/N]: " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
rm -f "$PRIVATE_KEY_FILE" "$PUBLIC_KEY_FILE"
|
||||
echo -e "${YELLOW}🗑️ 删除旧密钥${NC}"
|
||||
if [ -f "$PRIVATE_KEY_FILE" ] && [ -f "$PUBLIC_KEY_FILE" ]; then
|
||||
echo -e "${BLUE}ℹ️ 检测到现有的RSA密钥文件,保持现有密钥${NC}"
|
||||
# 验证现有密钥
|
||||
echo -e " ${CYAN}验证现有密钥对...${NC}"
|
||||
if openssl rsa -in "$PRIVATE_KEY_FILE" -check -noout 2>/dev/null; then
|
||||
echo -e "${GREEN} ✓ 现有密钥验证通过${NC}"
|
||||
else
|
||||
echo -e "${BLUE}ℹ️ 保持现有RSA密钥${NC}"
|
||||
RSA_SKIPPED=true
|
||||
echo -e "${RED} ❌ 现有密钥验证失败,将重新生成${NC}"
|
||||
rm -f "$PRIVATE_KEY_FILE" "$PUBLIC_KEY_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$RSA_SKIPPED" != "true" ]; then
|
||||
# 如果密钥不存在或验证失败,生成新密钥
|
||||
if [ ! -f "$PRIVATE_KEY_FILE" ] || [ ! -f "$PUBLIC_KEY_FILE" ]; then
|
||||
# 生成私钥
|
||||
echo -e " ${CYAN}生成RSA私钥...${NC}"
|
||||
openssl genrsa -out "$PRIVATE_KEY_FILE" $RSA_KEY_SIZE 2>/dev/null
|
||||
@@ -143,88 +143,33 @@ if [ -f ".env" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DATA_KEY_EXISTS" = "true" ] || [ "$JWT_KEY_EXISTS" = "true" ]; then
|
||||
echo -e "${YELLOW}⚠️ 检测到现有的密钥配置${NC}"
|
||||
if [ "$DATA_KEY_EXISTS" = "true" ]; then
|
||||
echo -e " • 数据加密密钥已存在"
|
||||
fi
|
||||
if [ "$JWT_KEY_EXISTS" = "true" ]; then
|
||||
echo -e " • JWT认证密钥已存在"
|
||||
fi
|
||||
read -p "是否重新生成所有密钥? [y/N]: " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo -e "${BLUE}ℹ️ 保持现有密钥${NC}"
|
||||
KEY_SKIPPED=true
|
||||
# 读取现有密钥
|
||||
if [ "$DATA_KEY_EXISTS" = "true" ]; then
|
||||
DATA_KEY=$(grep "^DATA_ENCRYPTION_KEY=" .env | cut -d'=' -f2)
|
||||
fi
|
||||
if [ "$JWT_KEY_EXISTS" = "true" ]; then
|
||||
JWT_KEY=$(grep "^JWT_SECRET=" .env | cut -d'=' -f2)
|
||||
fi
|
||||
fi
|
||||
# 确保 .env 文件存在
|
||||
if [ ! -f ".env" ]; then
|
||||
touch .env
|
||||
fi
|
||||
|
||||
if [ "$KEY_SKIPPED" != "true" ]; then
|
||||
# 生成新的密钥
|
||||
# 生成缺失的密钥(必需,不允许跳过)
|
||||
if [ "$DATA_KEY_EXISTS" != "true" ]; then
|
||||
echo -e " ${CYAN}生成AES-256数据加密密钥...${NC}"
|
||||
DATA_KEY=$(openssl rand -base64 32)
|
||||
DATA_KEY=$(openssl rand -base64 32 | tr -d '\n')
|
||||
echo "DATA_ENCRYPTION_KEY=$DATA_KEY" >> .env
|
||||
echo -e "${GREEN} ✓ 数据加密密钥生成完成${NC}"
|
||||
|
||||
echo -e " ${CYAN}生成JWT认证密钥...${NC}"
|
||||
JWT_KEY=$(openssl rand -base64 64)
|
||||
echo -e "${GREEN} ✓ JWT认证密钥生成完成${NC}"
|
||||
|
||||
# 保存到.env文件
|
||||
if [ -f ".env" ]; then
|
||||
# 更新现有文件
|
||||
if grep -q "^DATA_ENCRYPTION_KEY=" .env; then
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' "s/^DATA_ENCRYPTION_KEY=.*/DATA_ENCRYPTION_KEY=$DATA_KEY/" .env
|
||||
else
|
||||
sed -i "s/^DATA_ENCRYPTION_KEY=.*/DATA_ENCRYPTION_KEY=$DATA_KEY/" .env
|
||||
fi
|
||||
else
|
||||
echo "DATA_ENCRYPTION_KEY=$DATA_KEY" >> .env
|
||||
fi
|
||||
|
||||
if grep -q "^JWT_SECRET=" .env; then
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' "s/^JWT_SECRET=.*/JWT_SECRET=$JWT_KEY/" .env
|
||||
else
|
||||
sed -i "s/^JWT_SECRET=.*/JWT_SECRET=$JWT_KEY/" .env
|
||||
fi
|
||||
else
|
||||
echo "JWT_SECRET=$JWT_KEY" >> .env
|
||||
fi
|
||||
else
|
||||
# 创建新文件
|
||||
echo "DATA_ENCRYPTION_KEY=$DATA_KEY" > .env
|
||||
echo "JWT_SECRET=$JWT_KEY" >> .env
|
||||
fi
|
||||
chmod 600 .env
|
||||
echo -e "${GREEN} ✓ 密钥已保存到 .env 文件${NC}"
|
||||
elif [ "$DATA_KEY_EXISTS" != "true" ] || [ "$JWT_KEY_EXISTS" != "true" ]; then
|
||||
# 生成缺失的密钥
|
||||
if [ "$DATA_KEY_EXISTS" != "true" ]; then
|
||||
echo -e " ${CYAN}生成缺失的AES-256数据加密密钥...${NC}"
|
||||
DATA_KEY=$(openssl rand -base64 32)
|
||||
echo "DATA_ENCRYPTION_KEY=$DATA_KEY" >> .env
|
||||
echo -e "${GREEN} ✓ 数据加密密钥生成完成${NC}"
|
||||
fi
|
||||
|
||||
if [ "$JWT_KEY_EXISTS" != "true" ]; then
|
||||
echo -e " ${CYAN}生成缺失的JWT认证密钥...${NC}"
|
||||
JWT_KEY=$(openssl rand -base64 64)
|
||||
echo "JWT_SECRET=$JWT_KEY" >> .env
|
||||
echo -e "${GREEN} ✓ JWT认证密钥生成完成${NC}"
|
||||
fi
|
||||
|
||||
chmod 600 .env
|
||||
echo -e "${GREEN} ✓ 密钥已保存到 .env 文件${NC}"
|
||||
else
|
||||
echo -e "${BLUE} ℹ️ 数据加密密钥已存在,保持现有密钥${NC}"
|
||||
fi
|
||||
|
||||
if [ "$JWT_KEY_EXISTS" != "true" ]; then
|
||||
echo -e " ${CYAN}生成JWT认证密钥...${NC}"
|
||||
JWT_KEY=$(openssl rand -base64 64 | tr -d '\n')
|
||||
echo "JWT_SECRET=$JWT_KEY" >> .env
|
||||
echo -e "${GREEN} ✓ JWT认证密钥生成完成${NC}"
|
||||
else
|
||||
echo -e "${BLUE} ℹ️ JWT认证密钥已存在,保持现有密钥${NC}"
|
||||
fi
|
||||
|
||||
chmod 600 .env
|
||||
echo -e "${GREEN} ✓ 密钥配置已保存到 .env 文件${NC}"
|
||||
|
||||
# ============= 步骤4: 验证和总结 =============
|
||||
echo
|
||||
echo -e "${YELLOW}✅ 步骤 4/4: 环境验证和总结...${NC}"
|
||||
|
||||
56
start.sh
56
start.sh
@@ -104,47 +104,37 @@ check_encryption() {
|
||||
|
||||
# 如果需要设置加密环境
|
||||
if [ "$need_setup" = "true" ]; then
|
||||
print_info "🔐 需要设置加密环境"
|
||||
print_info "🔐 需要设置加密环境(必需)"
|
||||
print_info "加密环境用于保护敏感数据(API密钥、私钥等)"
|
||||
print_info "系统将自动配置加密环境..."
|
||||
echo ""
|
||||
|
||||
# 询问用户是否自动设置
|
||||
read -p "是否自动设置加密环境?[Y/n]: " auto_setup
|
||||
auto_setup=${auto_setup:-Y}
|
||||
|
||||
if [[ "$auto_setup" =~ ^[Yy]$ ]]; then
|
||||
print_info "正在设置加密环境..."
|
||||
|
||||
# 检查加密设置脚本是否存在
|
||||
if [ -f "scripts/setup_encryption.sh" ]; then
|
||||
print_info "正在自动设置加密环境..."
|
||||
print_info "加密系统将保护: API密钥、私钥、Hyperliquid代理钱包"
|
||||
|
||||
# 检查加密设置脚本是否存在
|
||||
if [ -f "scripts/setup_encryption.sh" ]; then
|
||||
print_info "正在自动设置加密环境..."
|
||||
print_info "加密系统将保护: API密钥、私钥、Hyperliquid代理钱包"
|
||||
echo ""
|
||||
|
||||
# 自动运行加密设置脚本
|
||||
# n: 保持现有RSA密钥(如果存在)| n: 保持现有数据密钥(如果存在)
|
||||
echo -e "n\nn" | bash scripts/setup_encryption.sh
|
||||
if [ $? -eq 0 ]; then
|
||||
echo ""
|
||||
print_success "🔐 加密环境设置完成!"
|
||||
print_info " • RSA-2048密钥对已生成"
|
||||
print_info " • AES-256数据加密密钥已配置"
|
||||
print_info " • JWT认证密钥已配置"
|
||||
print_info " • 所有敏感数据现在都受加密保护"
|
||||
echo ""
|
||||
|
||||
# 自动运行加密设置脚本
|
||||
# Y: 继续设置加密环境 | n: 保持现有RSA密钥 | n: 保持现有密钥配置
|
||||
echo -e "Y\nn\nn" | bash scripts/setup_encryption.sh
|
||||
if [ $? -eq 0 ]; then
|
||||
echo ""
|
||||
print_success "🔐 加密环境设置完成!"
|
||||
print_info " • RSA-2048密钥对已生成"
|
||||
print_info " • AES-256数据加密密钥已配置"
|
||||
print_info " • JWT认证密钥已配置"
|
||||
print_info " • 所有敏感数据现在都受加密保护"
|
||||
echo ""
|
||||
else
|
||||
print_error "加密环境设置失败"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
print_error "加密设置脚本不存在: scripts/setup_encryption.sh"
|
||||
print_error "加密环境设置失败"
|
||||
print_info "请手动运行: ./scripts/setup_encryption.sh"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
print_warning "跳过加密环境设置"
|
||||
print_info "手动设置命令: ./scripts/setup_encryption.sh"
|
||||
print_info "系统将使用未加密模式运行(不推荐)"
|
||||
print_error "加密设置脚本不存在: scripts/setup_encryption.sh"
|
||||
print_info "请手动运行: ./scripts/setup_encryption.sh"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
print_success "🔐 加密环境已配置"
|
||||
|
||||
@@ -415,7 +415,7 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
])
|
||||
),
|
||||
}),
|
||||
updateApi: api.updateModelConfigs,
|
||||
updateApi: api.updateModelConfigsEncrypted,
|
||||
refreshApi: api.getModelConfigs,
|
||||
setItems: (items) => {
|
||||
// 使用函数式更新确保状态正确更新
|
||||
@@ -488,7 +488,7 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
),
|
||||
}
|
||||
|
||||
await api.updateModelConfigs(request)
|
||||
await api.updateModelConfigsEncrypted(request)
|
||||
|
||||
// 重新获取用户配置以确保数据同步
|
||||
const refreshedModels = await api.getModelConfigs()
|
||||
@@ -515,6 +515,10 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
...e,
|
||||
apiKey: '',
|
||||
secretKey: '',
|
||||
hyperliquidWalletAddr: '',
|
||||
asterUser: '',
|
||||
asterSigner: '',
|
||||
asterPrivateKey: '',
|
||||
enabled: false,
|
||||
}),
|
||||
buildRequest: (exchanges) => ({
|
||||
@@ -526,11 +530,15 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
api_key: exchange.apiKey || '',
|
||||
secret_key: exchange.secretKey || '',
|
||||
testnet: exchange.testnet || false,
|
||||
hyperliquid_wallet_addr: exchange.hyperliquidWalletAddr || '',
|
||||
aster_user: exchange.asterUser || '',
|
||||
aster_signer: exchange.asterSigner || '',
|
||||
aster_private_key: exchange.asterPrivateKey || '',
|
||||
},
|
||||
])
|
||||
),
|
||||
}),
|
||||
updateApi: api.updateExchangeConfigs,
|
||||
updateApi: api.updateExchangeConfigsEncrypted,
|
||||
refreshApi: api.getExchangeConfigs,
|
||||
setItems: (items) => {
|
||||
// 使用函数式更新确保状态正确更新
|
||||
|
||||
@@ -160,8 +160,7 @@ export const api = {
|
||||
sessionId
|
||||
)
|
||||
|
||||
// 发送加密数据
|
||||
const res = await fetch(`${API_BASE}/models/encrypted`, {
|
||||
const res = await fetch(`${API_BASE}/models`, {
|
||||
method: 'PUT',
|
||||
headers: getAuthHeaders(),
|
||||
body: JSON.stringify(encryptedPayload),
|
||||
@@ -217,8 +216,8 @@ export const api = {
|
||||
sessionId
|
||||
)
|
||||
|
||||
// 发送加密数据
|
||||
const res = await fetch(`${API_BASE}/exchanges/encrypted`, {
|
||||
// 发送加密数据到普通端点
|
||||
const res = await fetch(`${API_BASE}/exchanges`, {
|
||||
method: 'PUT',
|
||||
headers: getAuthHeaders(),
|
||||
body: JSON.stringify(encryptedPayload),
|
||||
|
||||
Reference in New Issue
Block a user