|
@@ -1,657 +0,0 @@
|
|
|
-import 'dotenv/config'
|
|
|
-
|
|
|
-/**
|
|
|
- * 简化的环境变量管理器
|
|
|
- * 统一处理所有环境变量读取,避免重复的 process.env 调用
|
|
|
- */
|
|
|
-export class SimpleEnv {
|
|
|
- private static cache = new Map<string, string | undefined>()
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取环境变量值
|
|
|
- */
|
|
|
- static get(key: string, defaultValue?: string): string | undefined {
|
|
|
- if (this.cache.has(key)) {
|
|
|
- return this.cache.get(key)
|
|
|
- }
|
|
|
-
|
|
|
- const value = process.env[key] || defaultValue
|
|
|
- this.cache.set(key, value)
|
|
|
- return value
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取必需的环境变量值,如果不存在则抛出错误
|
|
|
- */
|
|
|
- static require(key: string): string {
|
|
|
- const value = this.get(key)
|
|
|
- if (!value) {
|
|
|
- throw new Error(`Required environment variable ${key} is not set`)
|
|
|
- }
|
|
|
- return value
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取布尔值环境变量
|
|
|
- */
|
|
|
- static bool(key: string, defaultValue: boolean = false): boolean {
|
|
|
- const value = this.get(key)
|
|
|
- if (!value) return defaultValue
|
|
|
- return ['true', '1', 'yes', 'on'].includes(value.toLowerCase())
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取数字环境变量
|
|
|
- */
|
|
|
- static number(key: string, defaultValue?: number): number | undefined {
|
|
|
- const value = this.get(key)
|
|
|
- if (!value) return defaultValue
|
|
|
- const num = parseInt(value, 10)
|
|
|
- return isNaN(num) ? defaultValue : num
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取 JSON 环境变量
|
|
|
- */
|
|
|
- static json<T = any>(key: string, defaultValue?: T): T | undefined {
|
|
|
- const value = this.get(key)
|
|
|
- if (!value) return defaultValue
|
|
|
- try {
|
|
|
- return JSON.parse(value)
|
|
|
- } catch {
|
|
|
- return defaultValue
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取数组环境变量(逗号分隔)
|
|
|
- */
|
|
|
- static array(key: string, defaultValue: string[] = []): string[] {
|
|
|
- const value = this.get(key)
|
|
|
- if (!value) return defaultValue
|
|
|
- return value
|
|
|
- .split(',')
|
|
|
- .map(s => s.trim())
|
|
|
- .filter(s => s.length > 0)
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 清除缓存
|
|
|
- */
|
|
|
- static clearCache(): void {
|
|
|
- this.cache.clear()
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 批量获取带前缀的环境变量
|
|
|
- */
|
|
|
- static getPrefix(prefix: string): Record<string, string> {
|
|
|
- const result: Record<string, string> = {}
|
|
|
-
|
|
|
- Object.keys(process.env).forEach(key => {
|
|
|
- if (key.startsWith(prefix)) {
|
|
|
- const shortKey = key.slice(prefix.length)
|
|
|
- const value = process.env[key]
|
|
|
- if (value) {
|
|
|
- result[shortKey] = value
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- return result
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 预定义的配置键,只包含需要从环境变量读取的配置
|
|
|
- */
|
|
|
-export const EnvKeys = {
|
|
|
- // 基础配置 (可选,有默认值)
|
|
|
- NODE_ENV: 'NODE_ENV',
|
|
|
- LOG_LEVEL: 'LOG_LEVEL',
|
|
|
-
|
|
|
- // Aster DEX 认证 (必需)
|
|
|
- ASTER_ORDER_USER: 'ASTER_ORDER_USER',
|
|
|
- ASTER_API_KEY: 'ASTER_API_KEY',
|
|
|
- ASTER_API_SECRET: 'ASTER_API_SECRET',
|
|
|
-
|
|
|
- // Aster 第二账户 (可选)
|
|
|
- ASTER2_ORDER_USER: 'ASTER2_ORDER_USER',
|
|
|
- ASTER2_ORDER_SIGNER: 'ASTER2_ORDER_SIGNER',
|
|
|
- PRIVATE_KEY2: 'PRIVATE_KEY2',
|
|
|
-
|
|
|
- // Pacifica DEX 认证 (必需)
|
|
|
- PACIFICA_ACCOUNT: 'PACIFICA_ACCOUNT',
|
|
|
- PACIFICA_ACCOUNT_PRIVATE_KEY: 'PACIFICA_ACCOUNT_PRIVATE_KEY',
|
|
|
-
|
|
|
- // 测试配置 (可选)
|
|
|
- PACIFICA_ENABLE_TEST_ORDER: 'PACIFICA_ENABLE_TEST_ORDER',
|
|
|
- PACIFICA_TEST_QTY: 'PACIFICA_TEST_QTY',
|
|
|
-
|
|
|
- // Binance (可选)
|
|
|
- BINANCE_API_KEY: 'BINANCE_API_KEY',
|
|
|
- BINANCE_SECRET_KEY: 'BINANCE_SECRET_KEY',
|
|
|
-
|
|
|
- // Proxy 配置 (可选)
|
|
|
- PROXY_ENABLED: 'PROXY_ENABLED',
|
|
|
- PROXY_PROTOCOL: 'PROXY_PROTOCOL',
|
|
|
- PROXY_HOST: 'PROXY_HOST',
|
|
|
- PROXY_PORT: 'PROXY_PORT',
|
|
|
- PROXY_USERNAME: 'PROXY_USERNAME',
|
|
|
- PROXY_PASSWORD: 'PROXY_PASSWORD',
|
|
|
-
|
|
|
- // 高级代理配置 (会话管理)
|
|
|
- PROXY_SESSION_PREFIX: 'PROXY_SESSION_PREFIX',
|
|
|
- PROXY_SESSION_SUFFIX: 'PROXY_SESSION_SUFFIX',
|
|
|
- PROXY_SESSION_STATIC: 'PROXY_SESSION_STATIC',
|
|
|
-
|
|
|
- // 交易所专用代理 (可选,优先级高于全局代理)
|
|
|
- ASTER_PROXY_PROTOCOL: 'ASTER_PROXY_PROTOCOL',
|
|
|
- ASTER_PROXY_HOST: 'ASTER_PROXY_HOST',
|
|
|
- ASTER_PROXY_PORT: 'ASTER_PROXY_PORT',
|
|
|
- ASTER_PROXY_USER: 'ASTER_PROXY_USER',
|
|
|
- ASTER_PROXY_PASS: 'ASTER_PROXY_PASS',
|
|
|
- ASTER_PROXY_SESSION_PREFIX: 'ASTER_PROXY_SESSION_PREFIX',
|
|
|
- ASTER_PROXY_SESSION_SUFFIX: 'ASTER_PROXY_SESSION_SUFFIX',
|
|
|
- ASTER_PROXY_SESSION_STATIC: 'ASTER_PROXY_SESSION_STATIC',
|
|
|
-
|
|
|
- // Pacifica专用代理
|
|
|
- PACIFICA_PROXY_PROTOCOL: 'PACIFICA_PROXY_PROTOCOL',
|
|
|
- PACIFICA_PROXY_HOST: 'PACIFICA_PROXY_HOST',
|
|
|
- PACIFICA_PROXY_PORT: 'PACIFICA_PROXY_PORT',
|
|
|
- PACIFICA_PROXY_USER: 'PACIFICA_PROXY_USER',
|
|
|
- PACIFICA_PROXY_PASS: 'PACIFICA_PROXY_PASS',
|
|
|
- PACIFICA_PROXY_SESSION_PREFIX: 'PACIFICA_PROXY_SESSION_PREFIX',
|
|
|
- PACIFICA_PROXY_SESSION_SUFFIX: 'PACIFICA_PROXY_SESSION_SUFFIX',
|
|
|
- PACIFICA_PROXY_SESSION_STATIC: 'PACIFICA_PROXY_SESSION_STATIC',
|
|
|
-
|
|
|
- // Binance专用代理
|
|
|
- BINANCE_PROXY_PROTOCOL: 'BINANCE_PROXY_PROTOCOL',
|
|
|
- BINANCE_PROXY_HOST: 'BINANCE_PROXY_HOST',
|
|
|
- BINANCE_PROXY_PORT: 'BINANCE_PROXY_PORT',
|
|
|
- BINANCE_PROXY_USER: 'BINANCE_PROXY_USER',
|
|
|
- BINANCE_PROXY_PASS: 'BINANCE_PROXY_PASS',
|
|
|
- BINANCE_PROXY_SESSION_PREFIX: 'BINANCE_PROXY_SESSION_PREFIX',
|
|
|
- BINANCE_PROXY_SESSION_SUFFIX: 'BINANCE_PROXY_SESSION_SUFFIX',
|
|
|
- BINANCE_PROXY_SESSION_STATIC: 'BINANCE_PROXY_SESSION_STATIC',
|
|
|
-} as const
|
|
|
-
|
|
|
-/**
|
|
|
- * 统一的配置对象 - 将固定配置写死,只有认证信息从环境变量读取
|
|
|
- */
|
|
|
-export const Config = {
|
|
|
- // 基础配置
|
|
|
- nodeEnv: () => SimpleEnv.get(EnvKeys.NODE_ENV, 'development'),
|
|
|
- logLevel: () => SimpleEnv.get(EnvKeys.LOG_LEVEL, 'info'),
|
|
|
- isDev: () => Config.nodeEnv() === 'development',
|
|
|
- isProd: () => Config.nodeEnv() === 'production',
|
|
|
-
|
|
|
- // Aster 配置 - 固定的服务端点,只有认证信息动态
|
|
|
- aster: {
|
|
|
- // 固定配置 - 不从环境变量读取
|
|
|
- wsUrl: 'wss://fstream.asterdex.com',
|
|
|
- httpBase: 'https://fapi.asterdex.com',
|
|
|
- subscribeSymbols: ['BTCUSDT', 'ETHUSDT'], // 默认订阅交易对
|
|
|
- wsPingInterval: 30000,
|
|
|
- wsPongTimeout: 10000,
|
|
|
- wsReconnectInterval: 5000,
|
|
|
- wsMaxReconnectAttempts: 10,
|
|
|
- recvWindow: 50000,
|
|
|
-
|
|
|
- // 动态配置 - 从环境变量读取
|
|
|
- orderUser: () => SimpleEnv.get(EnvKeys.ASTER_ORDER_USER),
|
|
|
- apiKey: () => SimpleEnv.get(EnvKeys.ASTER_API_KEY),
|
|
|
- apiSecret: () => SimpleEnv.get(EnvKeys.ASTER_API_SECRET),
|
|
|
-
|
|
|
- // 第二账户
|
|
|
- orderUser2: () => SimpleEnv.get(EnvKeys.ASTER2_ORDER_USER),
|
|
|
- orderSigner2: () => SimpleEnv.get(EnvKeys.ASTER2_ORDER_SIGNER),
|
|
|
- privateKey2: () => SimpleEnv.get(EnvKeys.PRIVATE_KEY2),
|
|
|
- },
|
|
|
-
|
|
|
- // Pacifica 配置 - 固定的服务端点,只有认证信息动态
|
|
|
- pacifica: {
|
|
|
- // 固定配置 - 不从环境变量读取
|
|
|
- baseUrl: 'https://api.pacifica.fi',
|
|
|
- wsUrl: 'wss://ws.pacifica.fi/ws',
|
|
|
- symbol: 'BTC-USD', // 默认交易对
|
|
|
- defaultQty: 0.001, // 默认交易数量
|
|
|
-
|
|
|
- // 动态配置 - 从环境变量读取
|
|
|
- account: () => SimpleEnv.get(EnvKeys.PACIFICA_ACCOUNT),
|
|
|
- accountPrivateKey: () => SimpleEnv.get(EnvKeys.PACIFICA_ACCOUNT_PRIVATE_KEY),
|
|
|
- enableTestOrder: () => SimpleEnv.bool(EnvKeys.PACIFICA_ENABLE_TEST_ORDER, false),
|
|
|
- testQty: () => SimpleEnv.number(EnvKeys.PACIFICA_TEST_QTY, 0.001),
|
|
|
- },
|
|
|
-
|
|
|
- // Binance 配置 - 只有认证信息
|
|
|
- binance: {
|
|
|
- // 固定配置
|
|
|
- baseUrl: 'https://api.binance.com',
|
|
|
- wsUrl: 'wss://stream.binance.com:9443/ws',
|
|
|
-
|
|
|
- // 动态配置
|
|
|
- apiKey: () => SimpleEnv.get(EnvKeys.BINANCE_API_KEY),
|
|
|
- secretKey: () => SimpleEnv.get(EnvKeys.BINANCE_SECRET_KEY),
|
|
|
- },
|
|
|
-
|
|
|
- // Proxy 配置 - 支持全局和交易所专用代理
|
|
|
- proxy: {
|
|
|
- // 全局代理配置
|
|
|
- enabled: () => SimpleEnv.bool(EnvKeys.PROXY_ENABLED, false),
|
|
|
- protocol: () => SimpleEnv.get(EnvKeys.PROXY_PROTOCOL, 'http'),
|
|
|
- host: () => SimpleEnv.get(EnvKeys.PROXY_HOST),
|
|
|
- port: () => SimpleEnv.number(EnvKeys.PROXY_PORT, 8080),
|
|
|
- username: () => SimpleEnv.get(EnvKeys.PROXY_USERNAME),
|
|
|
- password: () => SimpleEnv.get(EnvKeys.PROXY_PASSWORD),
|
|
|
-
|
|
|
- // 会话管理 (高级功能)
|
|
|
- sessionPrefix: () => SimpleEnv.get(EnvKeys.PROXY_SESSION_PREFIX),
|
|
|
- sessionSuffix: () => SimpleEnv.get(EnvKeys.PROXY_SESSION_SUFFIX),
|
|
|
- sessionStatic: () => SimpleEnv.get(EnvKeys.PROXY_SESSION_STATIC),
|
|
|
-
|
|
|
- // 交易所专用代理配置
|
|
|
- aster: {
|
|
|
- protocol: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_PROTOCOL, 'http'),
|
|
|
- host: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_HOST),
|
|
|
- port: () => SimpleEnv.number(EnvKeys.ASTER_PROXY_PORT, 12321),
|
|
|
- user: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_USER),
|
|
|
- pass: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_PASS),
|
|
|
- sessionPrefix: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_SESSION_PREFIX),
|
|
|
- sessionSuffix: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_SESSION_SUFFIX),
|
|
|
- sessionStatic: () => SimpleEnv.get(EnvKeys.ASTER_PROXY_SESSION_STATIC),
|
|
|
-
|
|
|
- isConfigured: (): boolean => {
|
|
|
- return !!Config.proxy.aster.host() && !!Config.proxy.aster.user()
|
|
|
- },
|
|
|
- },
|
|
|
-
|
|
|
- pacifica: {
|
|
|
- protocol: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_PROTOCOL, 'http'),
|
|
|
- host: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_HOST),
|
|
|
- port: () => SimpleEnv.number(EnvKeys.PACIFICA_PROXY_PORT, 8080),
|
|
|
- user: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_USER),
|
|
|
- pass: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_PASS),
|
|
|
- sessionPrefix: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_SESSION_PREFIX),
|
|
|
- sessionSuffix: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_SESSION_SUFFIX),
|
|
|
- sessionStatic: () => SimpleEnv.get(EnvKeys.PACIFICA_PROXY_SESSION_STATIC),
|
|
|
-
|
|
|
- isConfigured: (): boolean => {
|
|
|
- return !!Config.proxy.pacifica.host() && !!Config.proxy.pacifica.user()
|
|
|
- },
|
|
|
- },
|
|
|
-
|
|
|
- binance: {
|
|
|
- protocol: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_PROTOCOL, 'http'),
|
|
|
- host: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_HOST),
|
|
|
- port: () => SimpleEnv.number(EnvKeys.BINANCE_PROXY_PORT, 8080),
|
|
|
- user: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_USER),
|
|
|
- pass: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_PASS),
|
|
|
- sessionPrefix: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_SESSION_PREFIX),
|
|
|
- sessionSuffix: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_SESSION_SUFFIX),
|
|
|
- sessionStatic: () => SimpleEnv.get(EnvKeys.BINANCE_PROXY_SESSION_STATIC),
|
|
|
-
|
|
|
- isConfigured: (): boolean => {
|
|
|
- return !!Config.proxy.binance.host() && !!Config.proxy.binance.user()
|
|
|
- },
|
|
|
- },
|
|
|
-
|
|
|
- // 生成随机会话ID (8位字符)
|
|
|
- generateSessionId: (): string => {
|
|
|
- const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
|
|
|
- let result = ''
|
|
|
- for (let i = 0; i < 8; i++) {
|
|
|
- result += chars.charAt(Math.floor(Math.random() * chars.length))
|
|
|
- }
|
|
|
- return result
|
|
|
- },
|
|
|
-
|
|
|
- // 构建代理密码 (支持会话管理)
|
|
|
- buildPassword: (exchange?: 'aster' | 'pacifica' | 'binance'): string | undefined => {
|
|
|
- let config: any
|
|
|
-
|
|
|
- // 优先使用交易所专用配置
|
|
|
- if (exchange === 'aster' && Config.proxy.aster.isConfigured()) {
|
|
|
- config = {
|
|
|
- pass: Config.proxy.aster.pass(),
|
|
|
- prefix: Config.proxy.aster.sessionPrefix(),
|
|
|
- suffix: Config.proxy.aster.sessionSuffix(),
|
|
|
- static: Config.proxy.aster.sessionStatic(),
|
|
|
- }
|
|
|
- } else if (exchange === 'pacifica' && Config.proxy.pacifica.isConfigured()) {
|
|
|
- config = {
|
|
|
- pass: Config.proxy.pacifica.pass(),
|
|
|
- prefix: Config.proxy.pacifica.sessionPrefix(),
|
|
|
- suffix: Config.proxy.pacifica.sessionSuffix(),
|
|
|
- static: Config.proxy.pacifica.sessionStatic(),
|
|
|
- }
|
|
|
- } else if (exchange === 'binance' && Config.proxy.binance.isConfigured()) {
|
|
|
- config = {
|
|
|
- pass: Config.proxy.binance.pass(),
|
|
|
- prefix: Config.proxy.binance.sessionPrefix(),
|
|
|
- suffix: Config.proxy.binance.sessionSuffix(),
|
|
|
- static: Config.proxy.binance.sessionStatic(),
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 使用全局配置,如果没有则尝试使用ASTER配置作为回退
|
|
|
- config = {
|
|
|
- pass: Config.proxy.password() || Config.proxy.aster.pass(),
|
|
|
- prefix: Config.proxy.sessionPrefix() || Config.proxy.aster.sessionPrefix(),
|
|
|
- suffix: Config.proxy.sessionSuffix() || Config.proxy.aster.sessionSuffix(),
|
|
|
- static: Config.proxy.sessionStatic() || Config.proxy.aster.sessionStatic(),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 方式一:直接使用完整密码
|
|
|
- if (config.pass) {
|
|
|
- return config.pass
|
|
|
- }
|
|
|
-
|
|
|
- // 方式二:使用前后缀+会话ID
|
|
|
- if (config.prefix && config.suffix) {
|
|
|
- const sessionId = config.static || Config.proxy.generateSessionId()
|
|
|
- return `${config.prefix}${sessionId}${config.suffix}`
|
|
|
- }
|
|
|
-
|
|
|
- return undefined
|
|
|
- },
|
|
|
-
|
|
|
- // 获取代理URL (支持交易所专用配置)
|
|
|
- getUrl: (exchange?: 'aster' | 'pacifica' | 'binance'): string | undefined => {
|
|
|
- let proxyConfig: any
|
|
|
-
|
|
|
- // 优先使用交易所专用代理
|
|
|
- if (exchange === 'aster' && Config.proxy.aster.isConfigured()) {
|
|
|
- proxyConfig = {
|
|
|
- protocol: Config.proxy.aster.protocol(),
|
|
|
- host: Config.proxy.aster.host(),
|
|
|
- port: Config.proxy.aster.port(),
|
|
|
- username: Config.proxy.aster.user(),
|
|
|
- password: Config.proxy.buildPassword('aster'),
|
|
|
- }
|
|
|
- } else if (exchange === 'pacifica' && Config.proxy.pacifica.isConfigured()) {
|
|
|
- proxyConfig = {
|
|
|
- protocol: Config.proxy.pacifica.protocol(),
|
|
|
- host: Config.proxy.pacifica.host(),
|
|
|
- port: Config.proxy.pacifica.port(),
|
|
|
- username: Config.proxy.pacifica.user(),
|
|
|
- password: Config.proxy.buildPassword('pacifica'),
|
|
|
- }
|
|
|
- } else if (exchange === 'binance' && Config.proxy.binance.isConfigured()) {
|
|
|
- proxyConfig = {
|
|
|
- protocol: Config.proxy.binance.protocol(),
|
|
|
- host: Config.proxy.binance.host(),
|
|
|
- port: Config.proxy.binance.port(),
|
|
|
- username: Config.proxy.binance.user(),
|
|
|
- password: Config.proxy.buildPassword('binance'),
|
|
|
- }
|
|
|
- } else if (Config.proxy.enabled() && Config.proxy.host()) {
|
|
|
- // 全局代理
|
|
|
- proxyConfig = {
|
|
|
- protocol: Config.proxy.protocol(),
|
|
|
- host: Config.proxy.host(),
|
|
|
- port: Config.proxy.port(),
|
|
|
- username: Config.proxy.username() || Config.proxy.aster.user(),
|
|
|
- password: Config.proxy.buildPassword(),
|
|
|
- }
|
|
|
- } else if (Config.proxy.aster.isConfigured()) {
|
|
|
- // 回退使用ASTER代理配置作为全局代理
|
|
|
- proxyConfig = {
|
|
|
- protocol: Config.proxy.aster.protocol(),
|
|
|
- host: Config.proxy.aster.host(),
|
|
|
- port: Config.proxy.aster.port(),
|
|
|
- username: Config.proxy.aster.user(),
|
|
|
- password: Config.proxy.buildPassword(),
|
|
|
- }
|
|
|
- } else {
|
|
|
- return undefined
|
|
|
- }
|
|
|
-
|
|
|
- const { protocol, host, port, username, password } = proxyConfig
|
|
|
-
|
|
|
- if (username && password) {
|
|
|
- return `${protocol}://${username}:${password}@${host}:${port}`
|
|
|
- } else {
|
|
|
- return `${protocol}://${host}:${port}`
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 检查代理是否配置 (全局或交易所专用)
|
|
|
- isConfigured: (exchange?: 'aster' | 'pacifica' | 'binance'): boolean => {
|
|
|
- if (exchange === 'aster') {
|
|
|
- return Config.proxy.aster.isConfigured()
|
|
|
- } else if (exchange === 'pacifica') {
|
|
|
- return Config.proxy.pacifica.isConfigured()
|
|
|
- } else if (exchange === 'binance') {
|
|
|
- return Config.proxy.binance.isConfigured()
|
|
|
- }
|
|
|
- return Config.proxy.enabled() && !!Config.proxy.host()
|
|
|
- },
|
|
|
-
|
|
|
- // 检查任何代理是否配置
|
|
|
- isAnyConfigured: (): boolean => {
|
|
|
- return (
|
|
|
- Config.proxy.isConfigured() ||
|
|
|
- Config.proxy.aster.isConfigured() ||
|
|
|
- Config.proxy.pacifica.isConfigured() ||
|
|
|
- Config.proxy.binance.isConfigured()
|
|
|
- )
|
|
|
- },
|
|
|
- },
|
|
|
-
|
|
|
- // 获取所有配置(用于调试)
|
|
|
- getAll: () => ({
|
|
|
- nodeEnv: Config.nodeEnv(),
|
|
|
- logLevel: Config.logLevel(),
|
|
|
- aster: {
|
|
|
- wsUrl: Config.aster.wsUrl,
|
|
|
- httpBase: Config.aster.httpBase,
|
|
|
- subscribeSymbols: Config.aster.subscribeSymbols,
|
|
|
- orderUser: Config.aster.orderUser() ? '已设置' : '未设置',
|
|
|
- apiKey: Config.aster.apiKey() ? '已设置' : '未设置',
|
|
|
- },
|
|
|
- pacifica: {
|
|
|
- baseUrl: Config.pacifica.baseUrl,
|
|
|
- wsUrl: Config.pacifica.wsUrl,
|
|
|
- symbol: Config.pacifica.symbol,
|
|
|
- account: Config.pacifica.account() ? '已设置' : '未设置',
|
|
|
- enableTestOrder: Config.pacifica.enableTestOrder(),
|
|
|
- },
|
|
|
- binance: {
|
|
|
- baseUrl: Config.binance.baseUrl,
|
|
|
- wsUrl: Config.binance.wsUrl,
|
|
|
- apiKey: Config.binance.apiKey() ? '已设置' : '未设置',
|
|
|
- },
|
|
|
- proxy: {
|
|
|
- enabled: Config.proxy.enabled(),
|
|
|
- configured: Config.proxy.isConfigured(),
|
|
|
- url: Config.proxy.getUrl() ? '已配置' : '未配置',
|
|
|
- },
|
|
|
- }),
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 智能账户发现器 - 简化版
|
|
|
- */
|
|
|
-export class SmartAccountDiscovery {
|
|
|
- /**
|
|
|
- * 发现 Pacifica 账户
|
|
|
- */
|
|
|
- static discoverPacifica(): Array<{
|
|
|
- name: string
|
|
|
- account: string
|
|
|
- privateKey: string
|
|
|
- suffix: string
|
|
|
- }> {
|
|
|
- const accounts: Array<{
|
|
|
- name: string
|
|
|
- account: string
|
|
|
- privateKey: string
|
|
|
- suffix: string
|
|
|
- }> = []
|
|
|
-
|
|
|
- // 检查基础账户
|
|
|
- const baseAccount = SimpleEnv.get('PACIFICA_ACCOUNT')
|
|
|
- const baseKey = SimpleEnv.get('PACIFICA_ACCOUNT_PRIVATE_KEY')
|
|
|
- if (baseAccount && baseKey) {
|
|
|
- accounts.push({
|
|
|
- name: 'Pacifica Main',
|
|
|
- account: baseAccount,
|
|
|
- privateKey: baseKey,
|
|
|
- suffix: '',
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 检查编号账户 (1-5)
|
|
|
- for (let i = 1; i <= 5; i++) {
|
|
|
- const account = SimpleEnv.get(`PACIFICA_ACCOUNT_${i}`)
|
|
|
- const key = SimpleEnv.get(`PACIFICA_PRIVATE_KEY_${i}`)
|
|
|
- if (account && key) {
|
|
|
- accounts.push({
|
|
|
- name: `Pacifica ${i}`,
|
|
|
- account,
|
|
|
- privateKey: key,
|
|
|
- suffix: `_${i}`,
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 检查角色账户
|
|
|
- const roles = ['MAIN', 'HEDGE', 'BACKUP']
|
|
|
- roles.forEach(role => {
|
|
|
- const account = SimpleEnv.get(`PACIFICA_ACCOUNT_${role}`)
|
|
|
- const key = SimpleEnv.get(`PACIFICA_PRIVATE_KEY_${role}`)
|
|
|
- if (account && key) {
|
|
|
- accounts.push({
|
|
|
- name: `Pacifica ${role.toLowerCase()}`,
|
|
|
- account,
|
|
|
- privateKey: key,
|
|
|
- suffix: `_${role}`,
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- return accounts
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 发现 Aster 账户
|
|
|
- */
|
|
|
- static discoverAster(): Array<{
|
|
|
- name: string
|
|
|
- user: string
|
|
|
- signer?: string
|
|
|
- privateKey: string
|
|
|
- suffix: string
|
|
|
- }> {
|
|
|
- const accounts: Array<{
|
|
|
- name: string
|
|
|
- user: string
|
|
|
- signer?: string
|
|
|
- privateKey: string
|
|
|
- suffix: string
|
|
|
- }> = []
|
|
|
-
|
|
|
- // 检查基础账户
|
|
|
- const baseUser = SimpleEnv.get('ASTER_ORDER_USER')
|
|
|
- const baseSigner = SimpleEnv.get('ASTER_ORDER_SIGNER')
|
|
|
- const baseKey = SimpleEnv.get('PRIVATE_KEY')
|
|
|
- if (baseUser && baseKey) {
|
|
|
- accounts.push({
|
|
|
- name: 'Aster Main',
|
|
|
- user: baseUser,
|
|
|
- signer: baseSigner,
|
|
|
- privateKey: baseKey,
|
|
|
- suffix: '',
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 检查第二账户
|
|
|
- const user2 = SimpleEnv.get('ASTER2_ORDER_USER')
|
|
|
- const signer2 = SimpleEnv.get('ASTER2_ORDER_SIGNER')
|
|
|
- const key2 = SimpleEnv.get('PRIVATE_KEY2')
|
|
|
- if (user2 && key2) {
|
|
|
- accounts.push({
|
|
|
- name: 'Aster 2',
|
|
|
- user: user2,
|
|
|
- signer: signer2,
|
|
|
- privateKey: key2,
|
|
|
- suffix: '_2',
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 检查编号账户 (1-3)
|
|
|
- for (let i = 1; i <= 3; i++) {
|
|
|
- const user = SimpleEnv.get(`ASTER_ORDER_USER_${i}`)
|
|
|
- const signer = SimpleEnv.get(`ASTER_ORDER_SIGNER_${i}`)
|
|
|
- const key = SimpleEnv.get(`ASTER_PRIVATE_KEY_${i}`)
|
|
|
- if (user && key) {
|
|
|
- accounts.push({
|
|
|
- name: `Aster ${i}`,
|
|
|
- user,
|
|
|
- signer,
|
|
|
- privateKey: key,
|
|
|
- suffix: `_${i}`,
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return accounts
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 发现 Binance 账户
|
|
|
- */
|
|
|
- static discoverBinance(): Array<{
|
|
|
- name: string
|
|
|
- apiKey: string
|
|
|
- secretKey: string
|
|
|
- suffix: string
|
|
|
- }> {
|
|
|
- const accounts: Array<{
|
|
|
- name: string
|
|
|
- apiKey: string
|
|
|
- secretKey: string
|
|
|
- suffix: string
|
|
|
- }> = []
|
|
|
-
|
|
|
- // 检查基础账户
|
|
|
- const baseKey = SimpleEnv.get('BINANCE_API_KEY')
|
|
|
- const baseSecret = SimpleEnv.get('BINANCE_SECRET_KEY')
|
|
|
- if (baseKey && baseSecret) {
|
|
|
- accounts.push({
|
|
|
- name: 'Binance Main',
|
|
|
- apiKey: baseKey,
|
|
|
- secretKey: baseSecret,
|
|
|
- suffix: '',
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 检查编号账户 (1-3)
|
|
|
- for (let i = 1; i <= 3; i++) {
|
|
|
- const key = SimpleEnv.get(`BINANCE_API_KEY_${i}`)
|
|
|
- const secret = SimpleEnv.get(`BINANCE_SECRET_KEY_${i}`)
|
|
|
- if (key && secret) {
|
|
|
- accounts.push({
|
|
|
- name: `Binance ${i}`,
|
|
|
- apiKey: key,
|
|
|
- secretKey: secret,
|
|
|
- suffix: `_${i}`,
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return accounts
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 发现所有账户
|
|
|
- */
|
|
|
- static discoverAll() {
|
|
|
- return {
|
|
|
- pacifica: this.discoverPacifica(),
|
|
|
- aster: this.discoverAster(),
|
|
|
- binance: this.discoverBinance(),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|