cli_account_injection.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #!/usr/bin/env tsx
  2. /**
  3. * CLI 账户注入示例
  4. * 演示如何通过命令行参数动态注入单个账户
  5. */
  6. import { CLIAccountInjector } from '../src/accounts/CLIAccountInjector.js'
  7. import { UnifiedAccountManager } from '../src/accounts/UnifiedAccountManager.js'
  8. import { logger } from '../src/utils/logger.js'
  9. async function cliAccountInjectionDemo() {
  10. console.log('⚡ CLI 账户注入演示')
  11. console.log('='.repeat(50))
  12. try {
  13. // 1. 解析命令行参数
  14. console.log('\n📋 第一步: 解析命令行参数...')
  15. const cliOptions = CLIAccountInjector.parseArgs()
  16. console.log('🔍 检测到的命令行参数:')
  17. Object.entries(cliOptions).forEach(([key, value]) => {
  18. if (value !== undefined) {
  19. console.log(` ${key}: ${value}`)
  20. }
  21. })
  22. // 2. 检查必需参数
  23. if (!cliOptions.exchange) {
  24. console.log('\n❌ 错误: 未指定交易所')
  25. showUsageHelp()
  26. return
  27. }
  28. // 3. 生成账户配置
  29. console.log('\n🏗️ 第二步: 生成账户配置...')
  30. const accountConfig = CLIAccountInjector.createQuickAccount()
  31. console.log('✅ 生成的账户配置:')
  32. console.log(` 交易所: ${accountConfig.exchange}`)
  33. console.log(` 账户ID: ${accountConfig.accountId}`)
  34. console.log(` 别名: ${accountConfig.alias}`)
  35. console.log(` 优先级: ${accountConfig.priority}`)
  36. console.log(` 交易启用: ${accountConfig.tradingEnabled ? '✅' : '❌'}`)
  37. console.log(` 对冲启用: ${accountConfig.hedgingEnabled ? '✅' : '❌'}`)
  38. console.log(` 最大仓位: $${accountConfig.maxPositionUsd.toLocaleString()}`)
  39. console.log(` 最大日交易量: $${accountConfig.maxDailyVolumeUsd.toLocaleString()}`)
  40. // 4. 创建统一账户管理器
  41. console.log('\n🚀 第三步: 创建统一账户管理器并注入账户...')
  42. const unifiedManager = new UnifiedAccountManager({
  43. enableFailover: true,
  44. maxRetries: 3,
  45. retryDelayMs: 1000,
  46. })
  47. // 5. 验证账户配置
  48. console.log('\n🔍 第四步: 验证账户配置...')
  49. const validationResult = validateAccountConfig(accountConfig)
  50. if (validationResult.isValid) {
  51. console.log('✅ 账户配置验证通过')
  52. if (validationResult.warnings.length > 0) {
  53. console.log('⚠️ 警告:')
  54. validationResult.warnings.forEach(warning => {
  55. console.log(` - ${warning}`)
  56. })
  57. }
  58. } else {
  59. console.log('❌ 账户配置验证失败:')
  60. validationResult.errors.forEach(error => {
  61. console.log(` - ${error}`)
  62. })
  63. console.log('\n💡 请检查环境变量设置或命令行参数')
  64. return
  65. }
  66. // 6. 模拟注册账户 (实际环境中会连接真实交易所)
  67. console.log('\n📝 第五步: 注册账户...')
  68. if (cliOptions.dryRun) {
  69. console.log('🧪 干运行模式: 跳过实际注册')
  70. } else {
  71. console.log('⚠️ 注意: 这是演示模式,不会连接真实交易所')
  72. }
  73. try {
  74. // 在真实环境中这里会调用:
  75. // await unifiedManager.registerAccount(accountConfig)
  76. console.log(`✅ 账户 "${accountConfig.alias}" 注册成功`)
  77. console.log(` 状态: ${cliOptions.dryRun ? '模拟' : '实际'}`)
  78. console.log(` 交易所: ${accountConfig.exchange}`)
  79. console.log(` 账户ID: ${accountConfig.accountId}`)
  80. } catch (error) {
  81. console.error(`❌ 账户注册失败: ${error}`)
  82. return
  83. }
  84. // 7. 显示后续操作建议
  85. console.log('\n🎯 第六步: 后续操作建议...')
  86. console.log('✅ CLI 账户注入完成!')
  87. console.log('\n📚 接下来你可以:')
  88. console.log('1. 查看账户余额: await unifiedManager.balances()')
  89. console.log('2. 查看账户仓位: await unifiedManager.positions()')
  90. console.log('3. 下单交易: await unifiedManager.placeOrder(...)')
  91. console.log('4. 启用 WebSocket: await unifiedManager.startWebSocket()')
  92. // 8. 演示模式下的额外信息
  93. if (process.argv.includes('--verbose')) {
  94. console.log('\n🔧 详细信息:')
  95. console.log('账户配置对象:')
  96. console.log(JSON.stringify(accountConfig, null, 2))
  97. }
  98. } catch (error) {
  99. console.error('❌ CLI 账户注入演示失败:', error)
  100. logger.error('CLI account injection demo failed', { error: error.message })
  101. }
  102. }
  103. /**
  104. * 验证账户配置
  105. */
  106. function validateAccountConfig(config: any): {
  107. isValid: boolean
  108. errors: string[]
  109. warnings: string[]
  110. } {
  111. const result = {
  112. isValid: true,
  113. errors: [] as string[],
  114. warnings: [] as string[],
  115. }
  116. // 检查基本字段
  117. if (!config.exchange) {
  118. result.errors.push('交易所未指定')
  119. }
  120. if (!config.accountId) {
  121. result.errors.push('账户ID未指定')
  122. }
  123. // 检查交易所特定配置
  124. switch (config.exchange) {
  125. case 'pacifica':
  126. if (!process.env.PACIFICA_PRIVATE_KEY && !process.env.PACIFICA_PRIVATE_KEY_1) {
  127. result.errors.push('Pacifica 私钥环境变量未设置 (PACIFICA_PRIVATE_KEY 或 PACIFICA_PRIVATE_KEY_1)')
  128. }
  129. if (!process.env.PACIFICA_BASE_URL) {
  130. result.warnings.push('PACIFICA_BASE_URL 未设置,将使用默认值')
  131. }
  132. break
  133. case 'aster':
  134. if (!process.env.ASTER_ORDER_USER && !process.env.ASTER_ORDER_USER_1) {
  135. result.errors.push('Aster 用户地址环境变量未设置 (ASTER_ORDER_USER 或 ASTER_ORDER_USER_1)')
  136. }
  137. if (!process.env.PRIVATE_KEY && !process.env.ASTER_PRIVATE_KEY_1) {
  138. result.errors.push('Aster 私钥环境变量未设置 (PRIVATE_KEY 或 ASTER_PRIVATE_KEY_1)')
  139. }
  140. break
  141. case 'binance':
  142. if (!process.env.BINANCE_API_KEY && !process.env.BINANCE_API_KEY_1) {
  143. result.errors.push('Binance API密钥环境变量未设置 (BINANCE_API_KEY 或 BINANCE_API_KEY_1)')
  144. }
  145. if (!process.env.BINANCE_SECRET_KEY && !process.env.BINANCE_SECRET_KEY_1) {
  146. result.errors.push('Binance 密钥环境变量未设置 (BINANCE_SECRET_KEY 或 BINANCE_SECRET_KEY_1)')
  147. }
  148. break
  149. default:
  150. result.errors.push(`不支持的交易所: ${config.exchange}`)
  151. }
  152. // 检查数值范围
  153. if (config.maxPositionUsd <= 0) {
  154. result.warnings.push('最大仓位金额应大于0')
  155. }
  156. if (config.maxDailyVolumeUsd <= config.maxPositionUsd) {
  157. result.warnings.push('最大日交易量应大于最大仓位金额')
  158. }
  159. result.isValid = result.errors.length === 0
  160. return result
  161. }
  162. /**
  163. * 显示使用帮助信息
  164. */
  165. function showUsageHelp() {
  166. console.log('\n📚 CLI 账户注入使用说明:')
  167. console.log('\n🔹 基本用法:')
  168. console.log(' tsx cli_account_injection.ts --exchange <exchange> [options]')
  169. console.log('\n🔹 必需参数:')
  170. console.log(' --exchange, -e 交易所类型 (pacifica|aster|binance)')
  171. console.log('\n🔹 可选参数:')
  172. console.log(' --account, -a 账户ID (默认: cli-account)')
  173. console.log(' --alias 账户别名 (默认: CLI-<exchange>)')
  174. console.log(' --priority, -p 优先级 (默认: 999)')
  175. console.log(' --trading 是否启用交易 (true|false, 默认: true)')
  176. console.log(' --hedging 是否启用对冲 (true|false, 默认: true)')
  177. console.log(' --max-position 最大仓位USD (默认: 1000)')
  178. console.log(' --config, -c 配置文件路径 (可选)')
  179. console.log(' --dry-run 干运行模式,不实际注册')
  180. console.log(' --verbose 显示详细输出')
  181. console.log('\n🔹 示例:')
  182. console.log(' # 基本 Pacifica 账户注入')
  183. console.log(' tsx cli_account_injection.ts --exchange pacifica')
  184. console.log('\n # 完整参数 Aster 账户注入')
  185. console.log(' tsx cli_account_injection.ts \\')
  186. console.log(' --exchange aster \\')
  187. console.log(' --account my-aster-account \\')
  188. console.log(' --alias "我的Aster账户" \\')
  189. console.log(' --priority 1 \\')
  190. console.log(' --max-position 5000 \\')
  191. console.log(' --verbose')
  192. console.log('\n # 干运行模式 Binance 账户')
  193. console.log(' tsx cli_account_injection.ts \\')
  194. console.log(' --exchange binance \\')
  195. console.log(' --trading false \\')
  196. console.log(' --dry-run')
  197. console.log('\n🔹 环境变量配置:')
  198. console.log(' 请确保设置相应交易所的环境变量')
  199. console.log(' 参考 env.example 和 env.accounts.example 文件')
  200. }
  201. // 运行演示
  202. if (import.meta.url === `file://${process.argv[1]}`) {
  203. // 检查是否需要显示帮助
  204. if (process.argv.includes('--help') || process.argv.includes('-h')) {
  205. showUsageHelp()
  206. } else {
  207. cliAccountInjectionDemo()
  208. }
  209. }