refactor: 移除 polygon.rpc.url 配置,使用 RpcNodeService 统一管理 RPC 节点
- 删除 application.properties 中的 polygon.rpc.url 配置 - 更新 ApiHealthCheckService 直接使用 RpcNodeService.getHttpUrl() - 删除所有 Docker Compose 配置中的 POLYGON_RPC_URL 环境变量 - 删除所有部署脚本中的 POLYGON_RPC_URL 环境变量 - 更新所有文档,移除 POLYGON_RPC_URL 相关说明 - 删除 application.properties 中无用的 position.push 配置项 - 修正日志配置中的包名(polyhermes -> polymarketbot) 现在系统通过 RpcNodeService 从数据库读取 RPC 节点配置,用户可以通过系统设置页面管理 RPC 节点,不再需要环境变量配置。
This commit is contained in:
@@ -270,7 +270,6 @@ DB_USERNAME=root
|
|||||||
DB_PASSWORD=your_password_here
|
DB_PASSWORD=your_password_here
|
||||||
SPRING_PROFILES_ACTIVE=prod
|
SPRING_PROFILES_ACTIVE=prod
|
||||||
SERVER_PORT=80
|
SERVER_PORT=80
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
JWT_SECRET=your-jwt-secret-key-change-in-production
|
JWT_SECRET=your-jwt-secret-key-change-in-production
|
||||||
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
||||||
EOF
|
EOF
|
||||||
@@ -337,7 +336,6 @@ cd frontend
|
|||||||
| `DB_USERNAME` | 数据库用户名 | `root` |
|
| `DB_USERNAME` | 数据库用户名 | `root` |
|
||||||
| `DB_PASSWORD` | 数据库密码 | - |
|
| `DB_PASSWORD` | 数据库密码 | - |
|
||||||
| `SERVER_PORT` | 后端服务端口 | `8000` |
|
| `SERVER_PORT` | 后端服务端口 | `8000` |
|
||||||
| `POLYGON_RPC_URL` | Polygon RPC 地址 | `https://polygon-rpc.com` |
|
|
||||||
| `JWT_SECRET` | JWT 密钥 | - |
|
| `JWT_SECRET` | JWT 密钥 | - |
|
||||||
| `ADMIN_RESET_PASSWORD_KEY` | 管理员密码重置密钥 | - |
|
| `ADMIN_RESET_PASSWORD_KEY` | 管理员密码重置密钥 | - |
|
||||||
| `CRYPTO_SECRET_KEY` | 加密密钥(用于加密存储私钥和 API Key) | - |
|
| `CRYPTO_SECRET_KEY` | 加密密钥(用于加密存储私钥和 API Key) | - |
|
||||||
|
|||||||
@@ -270,7 +270,6 @@ DB_USERNAME=root
|
|||||||
DB_PASSWORD=your_password_here
|
DB_PASSWORD=your_password_here
|
||||||
SPRING_PROFILES_ACTIVE=prod
|
SPRING_PROFILES_ACTIVE=prod
|
||||||
SERVER_PORT=80
|
SERVER_PORT=80
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
JWT_SECRET=your-jwt-secret-key-change-in-production
|
JWT_SECRET=your-jwt-secret-key-change-in-production
|
||||||
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
||||||
EOF
|
EOF
|
||||||
@@ -337,7 +336,6 @@ cd frontend
|
|||||||
| `DB_USERNAME` | Database username | `root` |
|
| `DB_USERNAME` | Database username | `root` |
|
||||||
| `DB_PASSWORD` | Database password | - |
|
| `DB_PASSWORD` | Database password | - |
|
||||||
| `SERVER_PORT` | Backend service port | `8000` |
|
| `SERVER_PORT` | Backend service port | `8000` |
|
||||||
| `POLYGON_RPC_URL` | Polygon RPC address | `https://polygon-rpc.com` |
|
|
||||||
| `JWT_SECRET` | JWT secret key | - |
|
| `JWT_SECRET` | JWT secret key | - |
|
||||||
| `ADMIN_RESET_PASSWORD_KEY` | Admin password reset key | - |
|
| `ADMIN_RESET_PASSWORD_KEY` | Admin password reset key | - |
|
||||||
| `CRYPTO_SECRET_KEY` | Encryption key (for encrypting stored private keys and API Keys) | - |
|
| `CRYPTO_SECRET_KEY` | Encryption key (for encrypting stored private keys and API Keys) | - |
|
||||||
|
|||||||
@@ -154,9 +154,6 @@ SPRING_PROFILES_ACTIVE=prod
|
|||||||
# 服务器端口
|
# 服务器端口
|
||||||
SERVER_PORT=8000
|
SERVER_PORT=8000
|
||||||
|
|
||||||
# Polygon RPC
|
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
|
|
||||||
# JWT 密钥(已自动生成随机值,生产环境建议修改)
|
# JWT 密钥(已自动生成随机值,生产环境建议修改)
|
||||||
JWT_SECRET=${JWT_SECRET}
|
JWT_SECRET=${JWT_SECRET}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ services:
|
|||||||
- DB_USERNAME=${DB_USERNAME:-root}
|
- DB_USERNAME=${DB_USERNAME:-root}
|
||||||
- DB_PASSWORD=${DB_PASSWORD:-}
|
- DB_PASSWORD=${DB_PASSWORD:-}
|
||||||
- SERVER_PORT=8000
|
- SERVER_PORT=8000
|
||||||
- POLYGON_RPC_URL=${POLYGON_RPC_URL:-https://polygon-rpc.com}
|
|
||||||
- JWT_SECRET=${JWT_SECRET:-change-me-in-production}
|
- JWT_SECRET=${JWT_SECRET:-change-me-in-production}
|
||||||
- ADMIN_RESET_PASSWORD_KEY=${ADMIN_RESET_PASSWORD_KEY:-change-me-in-production}
|
- ADMIN_RESET_PASSWORD_KEY=${ADMIN_RESET_PASSWORD_KEY:-change-me-in-production}
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
+72
-72
@@ -125,88 +125,88 @@ open class CopyOrderTrackingService(
|
|||||||
|
|
||||||
return mutex.withLock {
|
return mutex.withLock {
|
||||||
try {
|
try {
|
||||||
// 1. 检查是否已处理(去重,包括失败状态)
|
// 1. 检查是否已处理(去重,包括失败状态)
|
||||||
val existingProcessed = processedTradeRepository.findByLeaderIdAndLeaderTradeId(leaderId, trade.id)
|
val existingProcessed = processedTradeRepository.findByLeaderIdAndLeaderTradeId(leaderId, trade.id)
|
||||||
|
|
||||||
if (existingProcessed != null) {
|
if (existingProcessed != null) {
|
||||||
if (existingProcessed.status == "FAILED") {
|
if (existingProcessed.status == "FAILED") {
|
||||||
return@withLock Result.success(Unit)
|
return@withLock Result.success(Unit)
|
||||||
}
|
}
|
||||||
return@withLock Result.success(Unit)
|
return@withLock Result.success(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否已记录为失败交易
|
// 检查是否已记录为失败交易
|
||||||
val failedTrade = failedTradeRepository.findByLeaderIdAndLeaderTradeId(leaderId, trade.id)
|
val failedTrade = failedTradeRepository.findByLeaderIdAndLeaderTradeId(leaderId, trade.id)
|
||||||
if (failedTrade != null) {
|
if (failedTrade != null) {
|
||||||
return@withLock Result.success(Unit)
|
return@withLock Result.success(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 处理交易逻辑
|
// 2. 处理交易逻辑
|
||||||
val result = when (trade.side.uppercase()) {
|
val result = when (trade.side.uppercase()) {
|
||||||
"BUY" -> processBuyTrade(leaderId, trade)
|
"BUY" -> processBuyTrade(leaderId, trade)
|
||||||
"SELL" -> processSellTrade(leaderId, trade)
|
"SELL" -> processSellTrade(leaderId, trade)
|
||||||
else -> {
|
else -> {
|
||||||
logger.warn("未知的交易方向: ${trade.side}")
|
logger.warn("未知的交易方向: ${trade.side}")
|
||||||
Result.failure(IllegalArgumentException("未知的交易方向: ${trade.side}"))
|
Result.failure(IllegalArgumentException("未知的交易方向: ${trade.side}"))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result.isFailure) {
|
if (result.isFailure) {
|
||||||
logger.error(
|
logger.error(
|
||||||
"处理交易失败: leaderId=$leaderId, tradeId=${trade.id}, side=${trade.side}",
|
"处理交易失败: leaderId=$leaderId, tradeId=${trade.id}, side=${trade.side}",
|
||||||
result.exceptionOrNull()
|
result.exceptionOrNull()
|
||||||
)
|
)
|
||||||
return@withLock result
|
return@withLock result
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 标记为已处理(成功状态)
|
// 3. 标记为已处理(成功状态)
|
||||||
// 由于使用了 Mutex,这里理论上不会出现并发冲突,但保留异常处理作为兜底
|
// 由于使用了 Mutex,这里理论上不会出现并发冲突,但保留异常处理作为兜底
|
||||||
try {
|
try {
|
||||||
val processed = ProcessedTrade(
|
val processed = ProcessedTrade(
|
||||||
leaderId = leaderId,
|
leaderId = leaderId,
|
||||||
leaderTradeId = trade.id,
|
leaderTradeId = trade.id,
|
||||||
tradeType = trade.side.uppercase(),
|
tradeType = trade.side.uppercase(),
|
||||||
source = source,
|
source = source,
|
||||||
status = "SUCCESS",
|
status = "SUCCESS",
|
||||||
processedAt = System.currentTimeMillis()
|
processedAt = System.currentTimeMillis()
|
||||||
)
|
)
|
||||||
processedTradeRepository.save(processed)
|
processedTradeRepository.save(processed)
|
||||||
} catch (e: Exception) {
|
|
||||||
// 检查是否是唯一键冲突异常(理论上不会发生,但保留作为兜底)
|
|
||||||
if (isUniqueConstraintViolation(e)) {
|
|
||||||
val existing = processedTradeRepository.findByLeaderIdAndLeaderTradeId(leaderId, trade.id)
|
|
||||||
if (existing != null) {
|
|
||||||
if (existing.status == "FAILED") {
|
|
||||||
logger.debug("交易已标记为失败,跳过处理: leaderId=$leaderId, tradeId=${trade.id}")
|
|
||||||
return@withLock Result.success(Unit)
|
|
||||||
}
|
|
||||||
logger.debug("交易已处理(并发检测): leaderId=$leaderId, tradeId=${trade.id}, status=${existing.status}")
|
|
||||||
return@withLock Result.success(Unit)
|
|
||||||
} else {
|
|
||||||
// 如果检查不到,可能是事务隔离级别问题,等待一下再查询
|
|
||||||
delay(100)
|
|
||||||
val existingAfterDelay =
|
|
||||||
processedTradeRepository.findByLeaderIdAndLeaderTradeId(leaderId, trade.id)
|
|
||||||
if (existingAfterDelay != null) {
|
|
||||||
logger.debug("延迟查询到记录(并发检测): leaderId=$leaderId, tradeId=${trade.id}, status=${existingAfterDelay.status}")
|
|
||||||
return@withLock Result.success(Unit)
|
|
||||||
}
|
|
||||||
logger.warn(
|
|
||||||
"保存ProcessedTrade时发生唯一约束冲突,但查询不到记录: leaderId=$leaderId, tradeId=${trade.id}",
|
|
||||||
e
|
|
||||||
)
|
|
||||||
return@withLock Result.success(Unit)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 其他类型的异常,重新抛出
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result.success(Unit)
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.error("处理交易异常: leaderId=$leaderId, tradeId=${trade.id}", e)
|
// 检查是否是唯一键冲突异常(理论上不会发生,但保留作为兜底)
|
||||||
Result.failure(e)
|
if (isUniqueConstraintViolation(e)) {
|
||||||
|
val existing = processedTradeRepository.findByLeaderIdAndLeaderTradeId(leaderId, trade.id)
|
||||||
|
if (existing != null) {
|
||||||
|
if (existing.status == "FAILED") {
|
||||||
|
logger.debug("交易已标记为失败,跳过处理: leaderId=$leaderId, tradeId=${trade.id}")
|
||||||
|
return@withLock Result.success(Unit)
|
||||||
|
}
|
||||||
|
logger.debug("交易已处理(并发检测): leaderId=$leaderId, tradeId=${trade.id}, status=${existing.status}")
|
||||||
|
return@withLock Result.success(Unit)
|
||||||
|
} else {
|
||||||
|
// 如果检查不到,可能是事务隔离级别问题,等待一下再查询
|
||||||
|
delay(100)
|
||||||
|
val existingAfterDelay =
|
||||||
|
processedTradeRepository.findByLeaderIdAndLeaderTradeId(leaderId, trade.id)
|
||||||
|
if (existingAfterDelay != null) {
|
||||||
|
logger.debug("延迟查询到记录(并发检测): leaderId=$leaderId, tradeId=${trade.id}, status=${existingAfterDelay.status}")
|
||||||
|
return@withLock Result.success(Unit)
|
||||||
|
}
|
||||||
|
logger.warn(
|
||||||
|
"保存ProcessedTrade时发生唯一约束冲突,但查询不到记录: leaderId=$leaderId, tradeId=${trade.id}",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
return@withLock Result.success(Unit)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 其他类型的异常,重新抛出
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result.success(Unit)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("处理交易异常: leaderId=$leaderId, tradeId=${trade.id}", e)
|
||||||
|
Result.failure(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -594,7 +594,7 @@ open class CopyOrderTrackingService(
|
|||||||
)
|
)
|
||||||
|
|
||||||
copyOrderTrackingRepository.save(tracking)
|
copyOrderTrackingRepository.save(tracking)
|
||||||
|
|
||||||
logger.info("买入订单已保存,等待轮询任务获取实际数据后发送通知: orderId=$realOrderId, copyTradingId=${copyTrading.id}")
|
logger.info("买入订单已保存,等待轮询任务获取实际数据后发送通知: orderId=$realOrderId, copyTradingId=${copyTrading.id}")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.error("处理买入交易失败: copyTradingId=${copyTrading.id}, tradeId=${trade.id}", e)
|
logger.error("处理买入交易失败: copyTradingId=${copyTrading.id}, tradeId=${trade.id}", e)
|
||||||
@@ -995,7 +995,7 @@ open class CopyOrderTrackingService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val realSellOrderId = createOrderResult.getOrNull() ?: return
|
val realSellOrderId = createOrderResult.getOrNull() ?: return
|
||||||
|
|
||||||
// 12. 下单时直接使用下单价格保存,等待定时任务更新实际成交价
|
// 12. 下单时直接使用下单价格保存,等待定时任务更新实际成交价
|
||||||
// priceUpdated 统一由定时任务更新,下单时统一设置为 false(非0x开头的除外)
|
// priceUpdated 统一由定时任务更新,下单时统一设置为 false(非0x开头的除外)
|
||||||
val priceUpdated = !realSellOrderId.startsWith("0x", ignoreCase = true)
|
val priceUpdated = !realSellOrderId.startsWith("0x", ignoreCase = true)
|
||||||
|
|||||||
+3
-21
@@ -28,8 +28,6 @@ class ApiHealthCheckService(
|
|||||||
private val dataApiBaseUrl: String,
|
private val dataApiBaseUrl: String,
|
||||||
@Value("\${polymarket.gamma.base-url}")
|
@Value("\${polymarket.gamma.base-url}")
|
||||||
private val gammaBaseUrl: String,
|
private val gammaBaseUrl: String,
|
||||||
@Value("\${polygon.rpc.url:}")
|
|
||||||
private val polygonRpcUrl: String,
|
|
||||||
@Value("\${polymarket.rtds.ws-url}")
|
@Value("\${polymarket.rtds.ws-url}")
|
||||||
private val polymarketWsUrl: String,
|
private val polymarketWsUrl: String,
|
||||||
@Value("\${polymarket.builder.relayer-url:}")
|
@Value("\${polymarket.builder.relayer-url:}")
|
||||||
@@ -187,27 +185,11 @@ class ApiHealthCheckService(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查 Polygon RPC
|
* 检查 Polygon RPC
|
||||||
* 使用动态获取的可用节点,而不是固定的配置
|
* 使用动态获取的可用节点(RpcNodeService 总是返回一个有效的 URL,包括默认节点)
|
||||||
*/
|
*/
|
||||||
private suspend fun checkPolygonRpc(): ApiHealthCheckDto = withContext(Dispatchers.IO) {
|
private suspend fun checkPolygonRpc(): ApiHealthCheckDto = withContext(Dispatchers.IO) {
|
||||||
// 优先使用动态获取的可用节点
|
// 使用 RpcNodeService 获取可用节点(总是返回有效值,包括默认节点)
|
||||||
val rpcUrl = try {
|
val rpcUrl = rpcNodeService.getHttpUrl()
|
||||||
rpcNodeService.getHttpUrl()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.debug("获取可用 RPC 节点失败,使用配置的默认值: ${e.message}")
|
|
||||||
// 如果获取失败,使用配置的默认值作为兜底
|
|
||||||
if (polygonRpcUrl.isNotBlank()) {
|
|
||||||
polygonRpcUrl
|
|
||||||
} else {
|
|
||||||
return@withContext ApiHealthCheckDto(
|
|
||||||
name = "Polygon RPC",
|
|
||||||
url = "未配置",
|
|
||||||
status = "skipped",
|
|
||||||
message = "未配置 Polygon RPC URL 且没有可用的节点"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkJsonRpcApi("Polygon RPC", rpcUrl)
|
checkJsonRpcApi("Polygon RPC", rpcUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,23 +40,12 @@ polymarket.rtds.ws-url=wss://ws-subscriptions-clob.polymarket.com
|
|||||||
polymarket.data-api.base-url=https://data-api.polymarket.com
|
polymarket.data-api.base-url=https://data-api.polymarket.com
|
||||||
polymarket.gamma.base-url=https://gamma-api.polymarket.com
|
polymarket.gamma.base-url=https://gamma-api.polymarket.com
|
||||||
|
|
||||||
# Polygon RPC 配置(用于查询链上余额)
|
|
||||||
# 可选:如果未配置,将无acc法查询 USDC 余额,但仍可通过 Subgraph API 查询持仓
|
|
||||||
# 示例:https://polygon-rpc.com 或 https://polygon-mainnet.infura.io/v3/YOUR_PROJECT_ID
|
|
||||||
polygon.rpc.url=${POLYGON_RPC_URL:https://polygon-rpc.com}
|
|
||||||
|
|
||||||
# Builder Relayer 配置(用于 Gasless 交易)
|
# Builder Relayer 配置(用于 Gasless 交易)
|
||||||
# 从 polymarket.com/settings?tab=builder 获取 Builder API 凭证
|
# 从 polymarket.com/settings?tab=builder 获取 Builder API 凭证
|
||||||
# Builder API Key、Secret、Passphrase 现在通过系统设置页面配置,存储在数据库中
|
# Builder API Key、Secret、Passphrase 现在通过系统设置页面配置,存储在数据库中
|
||||||
# 如果未配置,将使用手动发送交易的方式(需要用户支付 gas)
|
# 如果未配置,将使用手动发送交易的方式(需要用户支付 gas)
|
||||||
polymarket.builder.relayer-url=${POLYMARKET_BUILDER_RELAYER_URL:https://relayer-v2.polymarket.com/}
|
polymarket.builder.relayer-url=${POLYMARKET_BUILDER_RELAYER_URL:https://relayer-v2.polymarket.com/}
|
||||||
|
|
||||||
# 仓位推送配置
|
|
||||||
# 轮询间隔(毫秒),默认3秒
|
|
||||||
position.push.polling-interval=${POSITION_PUSH_POLLING_INTERVAL:3000}
|
|
||||||
# 心跳超时时间(毫秒),默认60秒,超过此时间未收到心跳则清理连接
|
|
||||||
position.push.heartbeat-timeout=${POSITION_PUSH_HEARTBEAT_TIMEOUT:60000}
|
|
||||||
|
|
||||||
# 跟单轮询配置
|
# 跟单轮询配置
|
||||||
# 轮询间隔(毫秒),默认2秒
|
# 轮询间隔(毫秒),默认2秒
|
||||||
copy.trading.polling.interval=${COPY_TRADING_POLLING_INTERVAL:2000}
|
copy.trading.polling.interval=${COPY_TRADING_POLLING_INTERVAL:2000}
|
||||||
|
|||||||
@@ -71,9 +71,6 @@ SERVER_PORT=80
|
|||||||
# MySQL 端口(可选,用于外部连接,默认 3307 避免与本地 MySQL 冲突)
|
# MySQL 端口(可选,用于外部连接,默认 3307 避免与本地 MySQL 冲突)
|
||||||
MYSQL_PORT=3307
|
MYSQL_PORT=3307
|
||||||
|
|
||||||
# Polygon RPC
|
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
|
|
||||||
# JWT 密钥(已自动生成随机值,生产环境建议修改)
|
# JWT 密钥(已自动生成随机值,生产环境建议修改)
|
||||||
JWT_SECRET=${JWT_SECRET}
|
JWT_SECRET=${JWT_SECRET}
|
||||||
|
|
||||||
|
|||||||
@@ -38,12 +38,6 @@ SERVER_PORT=80
|
|||||||
# Optional, for external connections, default 3307 to avoid conflicts with local MySQL
|
# Optional, for external connections, default 3307 to avoid conflicts with local MySQL
|
||||||
MYSQL_PORT=3307
|
MYSQL_PORT=3307
|
||||||
|
|
||||||
# ============================================
|
|
||||||
# Polygon RPC
|
|
||||||
# ============================================
|
|
||||||
# Polygon 网络 RPC 地址 / Polygon network RPC address
|
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# 安全配置 / Security Configuration
|
# 安全配置 / Security Configuration
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ services:
|
|||||||
- DB_USERNAME=${DB_USERNAME:-root}
|
- DB_USERNAME=${DB_USERNAME:-root}
|
||||||
- DB_PASSWORD=${DB_PASSWORD:-}
|
- DB_PASSWORD=${DB_PASSWORD:-}
|
||||||
- SERVER_PORT=8000
|
- SERVER_PORT=8000
|
||||||
- POLYGON_RPC_URL=${POLYGON_RPC_URL:-https://polygon-rpc.com}
|
|
||||||
# ⚠️ 安全警告:以下两个环境变量不能使用默认值,否则容器启动会失败
|
# ⚠️ 安全警告:以下两个环境变量不能使用默认值,否则容器启动会失败
|
||||||
# 请在 .env 文件中设置,或通过环境变量传入
|
# 请在 .env 文件中设置,或通过环境变量传入
|
||||||
# 生成随机密钥:openssl rand -hex 32 (ADMIN_RESET_PASSWORD_KEY) 或 openssl rand -hex 64 (JWT_SECRET)
|
# 生成随机密钥:openssl rand -hex 32 (ADMIN_RESET_PASSWORD_KEY) 或 openssl rand -hex 64 (JWT_SECRET)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ services:
|
|||||||
- DB_USERNAME=${DB_USERNAME:-root}
|
- DB_USERNAME=${DB_USERNAME:-root}
|
||||||
- DB_PASSWORD=${DB_PASSWORD:-}
|
- DB_PASSWORD=${DB_PASSWORD:-}
|
||||||
- SERVER_PORT=8000
|
- SERVER_PORT=8000
|
||||||
- POLYGON_RPC_URL=${POLYGON_RPC_URL:-https://polygon-rpc.com}
|
|
||||||
# ⚠️ 安全警告:以下两个环境变量不能使用默认值,否则容器启动会失败
|
# ⚠️ 安全警告:以下两个环境变量不能使用默认值,否则容器启动会失败
|
||||||
# 请在 .env 文件中设置,或通过环境变量传入
|
# 请在 .env 文件中设置,或通过环境变量传入
|
||||||
# 生成随机密钥:openssl rand -hex 32 (ADMIN_RESET_PASSWORD_KEY) 或 openssl rand -hex 64 (JWT_SECRET)
|
# 生成随机密钥:openssl rand -hex 32 (ADMIN_RESET_PASSWORD_KEY) 或 openssl rand -hex 64 (JWT_SECRET)
|
||||||
|
|||||||
@@ -163,7 +163,6 @@ DB_USERNAME=root
|
|||||||
DB_PASSWORD=your_password_here
|
DB_PASSWORD=your_password_here
|
||||||
SPRING_PROFILES_ACTIVE=prod
|
SPRING_PROFILES_ACTIVE=prod
|
||||||
SERVER_PORT=80
|
SERVER_PORT=80
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
JWT_SECRET=your-jwt-secret-key-change-in-production
|
JWT_SECRET=your-jwt-secret-key-change-in-production
|
||||||
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
||||||
EOF
|
EOF
|
||||||
@@ -393,7 +392,6 @@ DB_USERNAME=root
|
|||||||
DB_PASSWORD=your_password_here
|
DB_PASSWORD=your_password_here
|
||||||
SPRING_PROFILES_ACTIVE=prod
|
SPRING_PROFILES_ACTIVE=prod
|
||||||
SERVER_PORT=8000
|
SERVER_PORT=8000
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
JWT_SECRET=your-jwt-secret-key-change-in-production
|
JWT_SECRET=your-jwt-secret-key-change-in-production
|
||||||
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
||||||
EOF
|
EOF
|
||||||
@@ -554,7 +552,6 @@ serve -s dist -l 3000
|
|||||||
| `DB_USERNAME` | Database username | `root` | Yes (Production) |
|
| `DB_USERNAME` | Database username | `root` | Yes (Production) |
|
||||||
| `DB_PASSWORD` | Database password | - | Yes (Production) |
|
| `DB_PASSWORD` | Database password | - | Yes (Production) |
|
||||||
| `SERVER_PORT` | Server port | `8000` | No |
|
| `SERVER_PORT` | Server port | `8000` | No |
|
||||||
| `POLYGON_RPC_URL` | Polygon RPC address | `https://polygon-rpc.com` | No |
|
|
||||||
| `JWT_SECRET` | JWT secret key | - | Yes (Production) |
|
| `JWT_SECRET` | JWT secret key | - | Yes (Production) |
|
||||||
| `ADMIN_RESET_PASSWORD_KEY` | Admin password reset key | - | Yes (Production) |
|
| `ADMIN_RESET_PASSWORD_KEY` | Admin password reset key | - | Yes (Production) |
|
||||||
|
|
||||||
|
|||||||
@@ -100,9 +100,6 @@ spring.datasource.password=${DB_PASSWORD:password}
|
|||||||
# Server port
|
# Server port
|
||||||
server.port=${SERVER_PORT:8000}
|
server.port=${SERVER_PORT:8000}
|
||||||
|
|
||||||
# Polygon RPC
|
|
||||||
polygon.rpc.url=${POLYGON_RPC_URL:https://polygon-rpc.com}
|
|
||||||
|
|
||||||
# JWT secret
|
# JWT secret
|
||||||
jwt.secret=${JWT_SECRET:change-me-in-production}
|
jwt.secret=${JWT_SECRET:change-me-in-production}
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ DB_USERNAME=root
|
|||||||
DB_PASSWORD=your_password_here
|
DB_PASSWORD=your_password_here
|
||||||
SPRING_PROFILES_ACTIVE=prod
|
SPRING_PROFILES_ACTIVE=prod
|
||||||
SERVER_PORT=80
|
SERVER_PORT=80
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
JWT_SECRET=your-jwt-secret-key-change-in-production
|
JWT_SECRET=your-jwt-secret-key-change-in-production
|
||||||
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
||||||
EOF
|
EOF
|
||||||
@@ -397,7 +396,6 @@ DB_USERNAME=root
|
|||||||
DB_PASSWORD=your_password_here
|
DB_PASSWORD=your_password_here
|
||||||
SPRING_PROFILES_ACTIVE=prod
|
SPRING_PROFILES_ACTIVE=prod
|
||||||
SERVER_PORT=8000
|
SERVER_PORT=8000
|
||||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
|
||||||
JWT_SECRET=your-jwt-secret-key-change-in-production
|
JWT_SECRET=your-jwt-secret-key-change-in-production
|
||||||
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
||||||
EOF
|
EOF
|
||||||
@@ -558,7 +556,6 @@ serve -s dist -l 3000
|
|||||||
| `DB_USERNAME` | 数据库用户名 | `root` | 是(生产) |
|
| `DB_USERNAME` | 数据库用户名 | `root` | 是(生产) |
|
||||||
| `DB_PASSWORD` | 数据库密码 | - | 是(生产) |
|
| `DB_PASSWORD` | 数据库密码 | - | 是(生产) |
|
||||||
| `SERVER_PORT` | 服务器端口 | `8000` | 否 |
|
| `SERVER_PORT` | 服务器端口 | `8000` | 否 |
|
||||||
| `POLYGON_RPC_URL` | Polygon RPC 地址 | `https://polygon-rpc.com` | 否 |
|
|
||||||
| `JWT_SECRET` | JWT 密钥 | - | 是(生产) |
|
| `JWT_SECRET` | JWT 密钥 | - | 是(生产) |
|
||||||
| `ADMIN_RESET_PASSWORD_KEY` | 管理员密码重置密钥 | - | 是(生产) |
|
| `ADMIN_RESET_PASSWORD_KEY` | 管理员密码重置密钥 | - | 是(生产) |
|
||||||
|
|
||||||
|
|||||||
@@ -93,9 +93,6 @@ spring.datasource.password=${DB_PASSWORD:password}
|
|||||||
# 服务器端口
|
# 服务器端口
|
||||||
server.port=${SERVER_PORT:8000}
|
server.port=${SERVER_PORT:8000}
|
||||||
|
|
||||||
# Polygon RPC
|
|
||||||
polygon.rpc.url=${POLYGON_RPC_URL:https://polygon-rpc.com}
|
|
||||||
|
|
||||||
# JWT 密钥
|
# JWT 密钥
|
||||||
jwt.secret=${JWT_SECRET:change-me-in-production}
|
jwt.secret=${JWT_SECRET:change-me-in-production}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user