UNPKG

caravan-x

Version:

A terminal-based utility for managing Caravan multisig wallets in regtest mode. This tool simplifies development and testing with Caravan by providing an easy-to-use interface

272 lines (271 loc) 10.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.initializeCaravanX = initializeCaravanX; const inquirer_1 = __importDefault(require("inquirer")); const chalk_1 = __importDefault(require("chalk")); const boxen_1 = __importDefault(require("boxen")); const ora_1 = __importDefault(require("ora")); const config_manager_1 = require("./config-manager"); const docker_manager_1 = require("./docker-manager"); const bitcoin_rpc_1 = require("./bitcoin-rpc"); const logger_1 = require("../utils/logger"); async function initializeCaravanX() { const configManager = new config_manager_1.ConfigManager(); // Check if config exists const existingConfig = await configManager.loadConfig(); if (existingConfig) { const { shouldReconfigure } = await inquirer_1.default.prompt([ { type: "confirm", name: "shouldReconfigure", message: `Found existing ${chalk_1.default.cyan(existingConfig.mode)} mode configuration. Reconfigure?`, default: false, }, ]); if (!shouldReconfigure) { return existingConfig; } } // Mode selection const { mode } = await inquirer_1.default.prompt([ { type: "list", name: "mode", message: "Select operation mode:", choices: [ { name: `${chalk_1.default.cyan("🐳 Docker Mode")} - Automated regtest environment (Recommended)`, value: "docker", }, { name: `${chalk_1.default.yellow("⚙️ Manual Mode")} - Use your own Bitcoin Core node`, value: "manual", }, ], }, ]); let config; if (mode === "docker") { config = await setupDockerMode(); } else { config = await setupManualMode(); } await configManager.saveConfig(config); return config; } async function setupDockerMode() { console.log((0, boxen_1.default)(chalk_1.default.white.bold("Docker Mode Setup\n\n") + chalk_1.default.gray("Caravan-X will:\n") + chalk_1.default.white(" • Create a Bitcoin Core regtest container\n") + chalk_1.default.white(" • Set up nginx reverse proxy\n") + chalk_1.default.white(" • Configure RPC authentication\n") + chalk_1.default.white(" • Generate initial blockchain\n\n") + chalk_1.default.cyan("After setup, run your Caravan coordinator locally:\n") + chalk_1.default.yellow(" cd caravan && npm start\n") + chalk_1.default.cyan("Then connect to: ") + chalk_1.default.green.bold("http://localhost:5173/"), { padding: 1, margin: 1, borderStyle: "round", borderColor: "cyan", })); const { proceed } = await inquirer_1.default.prompt([ { type: "confirm", name: "proceed", message: "Proceed with Docker setup?", default: true, }, ]); if (!proceed) { logger_1.logger.info("Docker setup cancelled"); process.exit(0); } const dockerManager = new docker_manager_1.DockerManager(); const spinner = (0, ora_1.default)("Setting up Docker environment...").start(); try { // Check Docker availability await dockerManager.checkDocker(); spinner.text = "Creating Bitcoin Core container..."; // Setup container const containerInfo = await dockerManager.setupContainer(); spinner.text = "Configuring nginx proxy..."; // Setup nginx await dockerManager.setupNginx(); spinner.text = "Initializing blockchain..."; // Initialize regtest chain await dockerManager.initializeBlockchain(); spinner.succeed(chalk_1.default.green("Docker environment ready!")); return { mode: "docker", docker: { containerId: containerInfo.containerId, rpcPort: containerInfo.rpcPort, p2pPort: containerInfo.p2pPort, nginxPort: 8332, }, bitcoin: { host: "localhost", port: 8332, username: containerInfo.username, password: containerInfo.password, network: "regtest", }, caravan: { coordinatorUrl: "http://localhost:5173", }, }; } catch (error) { spinner.fail(chalk_1.default.red("Docker setup failed")); throw error; } } async function setupManualMode() { const configManager = new config_manager_1.ConfigManager(); const existingBitcoinConfig = await configManager.loadBitcoinConfig(); if (existingBitcoinConfig) { console.log((0, boxen_1.default)(chalk_1.default.white.bold("Existing Bitcoin Configuration:\n\n") + chalk_1.default.gray("Host: ") + chalk_1.default.white(existingBitcoinConfig.host) + "\n" + chalk_1.default.gray("Port: ") + chalk_1.default.white(existingBitcoinConfig.port) + "\n" + chalk_1.default.gray("Network: ") + chalk_1.default.white(existingBitcoinConfig.network) + "\n" + chalk_1.default.gray("Username: ") + chalk_1.default.white(existingBitcoinConfig.username), { padding: 1, margin: 1, borderStyle: "round", borderColor: "yellow", })); const { useExisting } = await inquirer_1.default.prompt([ { type: "confirm", name: "useExisting", message: "Use existing configuration?", default: true, }, ]); if (useExisting) { // Test connection const isConnected = await testBitcoinConnection(existingBitcoinConfig); if (!isConnected) { console.log((0, boxen_1.default)(chalk_1.default.red.bold("⚠️ Connection Failed\n\n") + chalk_1.default.white("Make sure your Bitcoin Core node is running:\n") + chalk_1.default.yellow(" bitcoind -regtest -daemon\n\n") + chalk_1.default.gray("Then restart Caravan-X"), { padding: 1, margin: 1, borderStyle: "round", borderColor: "red", })); process.exit(1); } return { mode: "manual", bitcoin: existingBitcoinConfig, caravan: { coordinatorUrl: "http://localhost:5173", }, }; } } // Get new configuration console.log((0, boxen_1.default)(chalk_1.default.yellow.bold("⚠️ Important Notice\n\n") + chalk_1.default.white("Manual mode requires you to:\n") + chalk_1.default.gray(" • Run Bitcoin Core yourself\n") + chalk_1.default.gray(" • Manage blockchain state\n") + chalk_1.default.gray(" • Handle RPC configuration\n\n") + chalk_1.default.cyan("Caravan-X will NOT manage your node"), { padding: 1, margin: 1, borderStyle: "round", borderColor: "yellow", })); const answers = await inquirer_1.default.prompt([ { type: "input", name: "host", message: "Bitcoin RPC host:", default: "localhost", }, { type: "number", name: "port", message: "Bitcoin RPC port:", default: 18443, }, { type: "input", name: "username", message: "RPC username:", default: "bitcoin", }, { type: "password", name: "password", message: "RPC password:", mask: "*", }, { type: "list", name: "network", message: "Bitcoin network:", choices: ["regtest", "testnet", "mainnet"], default: "regtest", }, ]); const bitcoinConfig = { host: answers.host, port: answers.port, username: answers.username, password: answers.password, network: answers.network, }; // Test connection const spinner = (0, ora_1.default)("Testing connection to Bitcoin Core...").start(); const isConnected = await testBitcoinConnection(bitcoinConfig); if (!isConnected) { spinner.fail(chalk_1.default.red("Connection failed")); console.log((0, boxen_1.default)(chalk_1.default.red.bold("⚠️ Cannot Connect to Bitcoin Core\n\n") + chalk_1.default.white("Please ensure:\n") + chalk_1.default.gray(" • Bitcoin Core is running\n") + chalk_1.default.gray(" • RPC credentials are correct\n") + chalk_1.default.gray(" • Network settings match\n\n") + chalk_1.default.yellow("Start your node with:\n") + chalk_1.default.cyan(` bitcoind -${answers.network} -daemon`), { padding: 1, margin: 1, borderStyle: "round", borderColor: "red", })); process.exit(1); } spinner.succeed(chalk_1.default.green("Connected to Bitcoin Core")); return { mode: "manual", bitcoin: bitcoinConfig, caravan: { coordinatorUrl: "http://localhost:5173", }, }; } async function testBitcoinConnection(config) { try { const rpc = new bitcoin_rpc_1.BitcoinRPC(config); await rpc.getBlockchainInfo(); return true; } catch (error) { logger_1.logger.debug("Connection test failed:", error); return false; } }