run-with-env.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. import { ethers } from "ethers"
  2. import * as fs from "fs"
  3. import * as path from "path"
  4. import { config } from "dotenv"
  5. // 环境配置接口
  6. interface EnvConfig {
  7. name: string
  8. rpcUrl: string
  9. chainId: number
  10. envFile: string
  11. outputDir: string
  12. description: string
  13. }
  14. // 预定义的环境配置
  15. const ENVIRONMENTS: { [key: string]: EnvConfig } = {
  16. hardhat: {
  17. name: "hardhat",
  18. rpcUrl: "http://127.0.0.1:8545",
  19. chainId: 31337,
  20. envFile: ".env.hardhat",
  21. outputDir: "./output/hardhat",
  22. description: "Hardhat本地环境"
  23. },
  24. bsctest: {
  25. name: "bsctest",
  26. rpcUrl: "https://data-seed-prebsc-1-s1.binance.org:8545/",
  27. chainId: 97,
  28. envFile: ".env.bsctest",
  29. outputDir: "./output/bsctest",
  30. description: "BSC测试网环境"
  31. },
  32. bscmainnet: {
  33. name: "bscmainnet",
  34. rpcUrl: "https://bsc-dataseed1.binance.org/",
  35. chainId: 56,
  36. envFile: ".env.bscmainnet",
  37. outputDir: "./output/bscmainnet",
  38. description: "BNB主网环境"
  39. }
  40. }
  41. // 脚本配置接口
  42. interface ScriptConfig {
  43. name: string
  44. script: string
  45. description: string
  46. }
  47. // 可用的脚本列表
  48. const AVAILABLE_SCRIPTS: ScriptConfig[] = [
  49. { name: "01:deploy", script: "01-deploy-contracts.ts", description: "部署合约" },
  50. { name: "02:distribute", script: "02-distribute-tokens.ts", description: "分发代币" },
  51. { name: "03:init", script: "03-init-sale.ts", description: "初始化销售" },
  52. { name: "04:contribute", script: "04-test-contributions.ts", description: "测试贡献" },
  53. { name: "05:claim", script: "05-test-claiming.ts", description: "测试领取" },
  54. { name: "test", script: "test-env.ts", description: "测试环境配置" }
  55. ]
  56. function printUsage() {
  57. console.log("🚀 多环境脚本执行器")
  58. console.log("\n📋 使用方法:")
  59. console.log(" npm run env <environment> <script>")
  60. console.log(" npm run env <environment> <script> [options]")
  61. console.log("\n🌍 可用环境:")
  62. Object.entries(ENVIRONMENTS).forEach(([key, env]) => {
  63. console.log(` ${key.padEnd(10)} - ${env.description}`)
  64. })
  65. console.log("\n📜 可用脚本:")
  66. AVAILABLE_SCRIPTS.forEach(script => {
  67. console.log(` ${script.name.padEnd(12)} - ${script.description}`)
  68. })
  69. console.log("\n💡 示例:")
  70. console.log(" npm run env hardhat 01:deploy")
  71. console.log(" npm run env bsctest 03:init")
  72. console.log(" npm run env bscmainnet 01:deploy")
  73. console.log(" npm run env hardhat 04:contribute SCENARIO=1")
  74. console.log("\n📁 输出目录:")
  75. Object.entries(ENVIRONMENTS).forEach(([key, env]) => {
  76. console.log(` ${key.padEnd(10)} - ${env.outputDir}`)
  77. })
  78. }
  79. function validateEnvironment(envName: string): EnvConfig {
  80. const env = ENVIRONMENTS[envName]
  81. if (!env) {
  82. console.error(`❌ 错误:未知环境 '${envName}'`)
  83. console.log("\n可用环境:")
  84. Object.keys(ENVIRONMENTS).forEach(key => console.log(` - ${key}`))
  85. process.exit(1)
  86. }
  87. return env
  88. }
  89. function validateScript(scriptName: string): ScriptConfig {
  90. const script = AVAILABLE_SCRIPTS.find(s => s.name === scriptName)
  91. if (!script) {
  92. console.error(`❌ 错误:未知脚本 '${scriptName}'`)
  93. console.log("\n可用脚本:")
  94. AVAILABLE_SCRIPTS.forEach(s => console.log(` - ${s.name}`))
  95. process.exit(1)
  96. }
  97. return script
  98. }
  99. function setupEnvironment(env: EnvConfig) {
  100. console.log(`\n🌍 切换到环境: ${env.description}`)
  101. console.log(`📁 输出目录: ${env.outputDir}`)
  102. console.log(`🔗 RPC地址: ${env.rpcUrl}`)
  103. // 创建输出目录
  104. if (!fs.existsSync(env.outputDir)) {
  105. fs.mkdirSync(env.outputDir, { recursive: true })
  106. console.log(`✅ 创建输出目录: ${env.outputDir}`)
  107. }
  108. // 加载环境变量
  109. const envPath = path.resolve(env.envFile)
  110. if (fs.existsSync(envPath)) {
  111. // 清除之前的环境变量,然后加载指定的环境文件
  112. Object.keys(process.env).forEach(key => {
  113. if (key.startsWith('PRIVATE_KEY') || key.startsWith('RPC_URL') || key.startsWith('CHAIN_ID')) {
  114. delete process.env[key]
  115. }
  116. })
  117. config({ path: envPath, override: true })
  118. console.log(`✅ 加载环境文件: ${env.envFile}`)
  119. } else {
  120. console.warn(`⚠️ 环境文件不存在: ${env.envFile}`)
  121. console.log("💡 请创建环境文件或使用默认.env文件")
  122. }
  123. // 设置环境变量
  124. process.env.ENVIRONMENT = env.name
  125. process.env.OUTPUT_DIR = env.outputDir
  126. process.env.RPC_URL = env.rpcUrl
  127. process.env.CHAIN_ID = env.chainId.toString()
  128. console.log(`✅ 环境设置完成`)
  129. }
  130. async function runScript(script: ScriptConfig, args: string[]) {
  131. console.log(`\n📜 执行脚本: ${script.description}`)
  132. console.log(`📄 脚本文件: ${script.script}`)
  133. // 构建脚本路径
  134. const scriptPath = path.resolve(`./scripts/${script.script}`)
  135. if (!fs.existsSync(scriptPath)) {
  136. console.error(`❌ 脚本文件不存在: ${scriptPath}`)
  137. process.exit(1)
  138. }
  139. // 设置脚本参数
  140. process.argv = [process.argv[0], process.argv[1], ...args]
  141. try {
  142. // 动态导入并执行脚本
  143. const scriptModule = await import(scriptPath)
  144. if (scriptModule.main) {
  145. await scriptModule.main()
  146. } else {
  147. console.error(`❌ 脚本 ${script.script} 没有导出 main 函数`)
  148. process.exit(1)
  149. }
  150. } catch (error) {
  151. console.error(`❌ 执行脚本失败:`, error)
  152. process.exit(1)
  153. }
  154. }
  155. async function main() {
  156. const args = process.argv.slice(2)
  157. // 显示帮助信息
  158. if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
  159. printUsage()
  160. return
  161. }
  162. // 解析参数
  163. const envName = args[0]
  164. const scriptName = args[1]
  165. const scriptArgs = args.slice(2)
  166. if (!envName || !scriptName) {
  167. console.error("❌ 错误:缺少环境或脚本参数")
  168. printUsage()
  169. process.exit(1)
  170. }
  171. // 验证环境
  172. const env = validateEnvironment(envName)
  173. // 验证脚本
  174. const script = validateScript(scriptName)
  175. // 设置环境
  176. setupEnvironment(env)
  177. // 执行脚本
  178. await runScript(script, scriptArgs)
  179. console.log("\n🎉 脚本执行完成!")
  180. }
  181. // 如果直接运行此脚本
  182. if (require.main === module) {
  183. main().catch(error => {
  184. console.error("❌ 执行失败:", error)
  185. process.exit(1)
  186. })
  187. }
  188. export { main, ENVIRONMENTS, AVAILABLE_SCRIPTS }