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

497 lines (496 loc) 18.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VisualizationServer = void 0; const http = __importStar(require("http")); const express_1 = __importDefault(require("express")); const socket_io_1 = require("socket.io"); const terminal_1 = require("../../utils/terminal"); // Content types for different file extensions const CONTENT_TYPES = { ".html": "text/html", ".css": "text/css", ".js": "text/javascript", ".json": "application/json", ".png": "image/png", ".jpg": "image/jpeg", ".svg": "image/svg+xml", ".ico": "image/x-icon", }; /** * Enhanced HTTP Server for blockchain visualization with WebSockets */ class VisualizationServer { constructor(blockchainData, staticDir, port = 3000) { this.updateInterval = null; this.connectedClients = 0; this.blockchainData = blockchainData; this.staticDir = staticDir; this.port = port; // Initialize Express app this.app = (0, express_1.default)(); // Configure middleware this.configureMiddleware(); // Create HTTP server this.server = http.createServer(this.app); // Initialize Socket.io this.io = new socket_io_1.Server(this.server); // Configure Socket.io events this.configureSocketEvents(); // Configure API routes this.configureRoutes(); } /** * Configure Express middleware */ configureMiddleware() { // Serve static files this.app.use(express_1.default.static(this.staticDir)); // Parse JSON body this.app.use(express_1.default.json()); } /** * Configure Socket.io events */ configureSocketEvents() { this.io.on("connection", (socket) => { this.connectedClients++; console.log(`Client connected. Total clients: ${this.connectedClients}`); // Send initial data this.sendInitialData(socket); // Handle disconnection socket.on("disconnect", () => { this.connectedClients--; console.log(`Client disconnected. Total clients: ${this.connectedClients}`); }); // Handle client events this.configureClientEvents(socket); }); } /** * Configure client-specific events */ configureClientEvents(socket) { // Handle mining request socket.on("mine_block", async (data) => { try { console.log("Mining request received:", data); // Notify all clients that mining has started this.io.emit("mining_started", { blocks: data.blocks, address: data.address || "default_address", }); // Call the mining method (this would be implemented in your blockchain service) const blockHashes = await this.blockchainData.mineBlocks(data.blocks, data.address); // Notify all clients that mining is complete this.io.emit("mining_complete", { blockHashes, }); // Update all clients with new blockchain data this.broadcastBlockchainUpdate(); } catch (error) { console.error("Error mining blocks:", error); socket.emit("error", { message: "Error mining blocks", error: error.message, }); } }); // Handle transaction creation request socket.on("create_transaction", async (data) => { try { console.log("Transaction creation request received:", data); // Call the transaction creation method (this would be implemented in your blockchain service) const result = await this.blockchainData.createTransaction(data.fromWallet, data.toAddress, data.amount); // Notify the client that the transaction was created socket.emit("transaction_created", result); // Notify all clients about the new transaction this.io.emit("new_transaction", { txid: result.txid, fromWallet: data.fromWallet, toAddress: data.toAddress, amount: data.amount, }); // Update all clients with new blockchain data this.broadcastBlockchainUpdate(); } catch (error) { console.error("Error creating transaction:", error); socket.emit("error", { message: "Error creating transaction", error: error.message, }); } }); } /** * Configure API routes */ configureRoutes() { // Get blockchain data this.app.get("/api/blockchain", async (req, res) => { try { const data = await this.blockchainData.getBlockchainVisualizationData(); res.json(data); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Get block details this.app.get("/api/block/:hash", async (req, res) => { try { const block = await this.blockchainData.getBlock(req.params.hash); console.log(terminal_1.colors.info("/api/blockchain2")); res.json(block); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Get transaction details this.app.get("/api/tx/:txid", async (req, res) => { try { const tx = await this.blockchainData.getTransaction(req.params.txid); console.log(terminal_1.colors.info("/api/blockchain3")); res.json(tx); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Get mempool data this.app.get("/api/mempool", async (req, res) => { try { const txids = await this.blockchainData.getMempoolTransactions(); const info = await this.blockchainData.getMempoolInfo(); res.json({ txids, info }); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Get chain info this.app.get("/api/chain-info", async (req, res) => { try { const info = await this.blockchainData.getChainInfo(); res.json(info); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Get recent blocks this.app.get("/api/recent-blocks", async (req, res) => { try { const count = parseInt(req.query.count || "10"); const blocks = await this.blockchainData.getRecentBlocks(count); res.json(blocks); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Mine blocks (POST endpoint) this.app.post("/api/mine-block", async (req, res) => { try { const { blocks, address } = req.body; // Validate input if (!blocks || isNaN(blocks) || blocks <= 0) { return res.status(400).json({ error: "Invalid number of blocks" }); } // Notify all clients that mining has started this.io.emit("mining_started", { blocks, address: address || "default_address", }); // Call the mining method (this would be implemented in your blockchain service) const blockHashes = await this.blockchainData.mineBlocks(blocks, address); // Notify all clients that mining is complete this.io.emit("mining_complete", { blockHashes, }); // Update all clients with new blockchain data this.broadcastBlockchainUpdate(); res.json({ success: true, blockHashes }); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Create transaction (POST endpoint) this.app.post("/api/create-transaction", async (req, res) => { try { const { fromWallet, toAddress, amount } = req.body; // Validate input if (!fromWallet || !toAddress || !amount || isNaN(amount) || amount <= 0) { return res.status(400).json({ error: "Invalid transaction data" }); } // Call the transaction creation method (this would be implemented in your blockchain service) const result = await this.blockchainData.createTransaction(fromWallet, toAddress, amount); // Notify all clients about the new transaction this.io.emit("new_transaction", { txid: result.txid, fromWallet, toAddress, amount, }); // Update all clients with new blockchain data this.broadcastBlockchainUpdate(); res.json(result); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Get a new address from a wallet this.app.get("/api/new-address", async (req, res) => { try { const wallet = req.query.wallet; if (!wallet) { return res .status(400) .json({ error: "Wallet parameter is required" }); } // Call the Bitcoin service to get a new address const address = await this.blockchainData.getNewAddress(wallet); res.json({ address }); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // Get wallet list this.app.get("/api/wallets", async (req, res) => { try { const wallets = await this.blockchainData.getWalletList(); res.json({ wallets }); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); this.app.get("/api/minecraft/blockchain", async (req, res) => { try { const data = await this.blockchainData.getBlockchainVisualizationData(); res.json(data); } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // API endpoint for mining blocks in Minecraft view this.app.post("/api/minecraft/mine", async (req, res) => { try { const { x, y, z, tool } = req.body; // Simulate mining success based on tool and block type const success = Math.random() > 0.3; // 70% success rate if (success) { // Return mining result res.json({ success: true, material: "stone", amount: Math.floor(Math.random() * 3) + 1, }); } else { // Mining failed res.json({ success: false, message: "Mining failed. Try a different tool or location.", }); } } catch (error) { console.error("API error:", error); res.status(500).json({ error: "Internal server error" }); } }); // API endpoint for player inventory this.app.get("/api/minecraft/inventory", (req, res) => { // Return default inventory res.json({ bitcoin: 0, tokens: { BlockToken: 10, ChainCoin: 5, }, tools: { pickaxe: { level: 1, durability: 100 }, shovel: { level: 1, durability: 100 }, }, materials: { stone: 0, goldOre: 0, }, }); }); // API endpoint for quests this.app.get("/api/minecraft/quests", (req, res) => { // Return available quests res.json([ { id: "mining_101", title: "Mining 101", description: "Mine your first block to earn a reward", reward: { bitcoin: 0.1 }, progress: 0, goal: 1, complete: false, }, { id: "transaction_tracker", title: "Transaction Tracker", description: "Interact with 5 transaction characters", reward: { tokens: { ChainCoin: 10 } }, progress: 0, goal: 5, complete: false, }, { id: "block_explorer", title: "Block Explorer", description: "Visit 10 different block buildings", reward: { materials: { goldOre: 5 } }, progress: 0, goal: 10, complete: false, }, ]); }); } /** * Send initial data to a newly connected client */ async sendInitialData(socket) { try { const data = await this.blockchainData.getBlockchainVisualizationData(); socket.emit("blockchain_update", data); } catch (error) { console.error("Error sending initial data:", error); } } /** * Broadcast blockchain update to all connected clients */ async broadcastBlockchainUpdate() { try { const data = await this.blockchainData.getBlockchainVisualizationData(); this.io.emit("blockchain_update", data); } catch (error) { console.error("Error broadcasting blockchain update:", error); } } /** * Start the real-time updates */ startRealTimeUpdates() { // Clear any existing interval if (this.updateInterval) { clearInterval(this.updateInterval); } // Set up periodic updates (every 5 seconds) this.updateInterval = setInterval(async () => { // Only send updates if there are connected clients if (this.connectedClients > 0) { try { await this.broadcastBlockchainUpdate(); } catch (error) { console.error("Error during periodic update:", error); } } }, 5000); } /** * Stop the real-time updates */ stopRealTimeUpdates() { if (this.updateInterval) { clearInterval(this.updateInterval); this.updateInterval = null; } } /** * Start the server */ async start() { return new Promise((resolve) => { this.server.listen(this.port, () => { console.log(`Visualization server running at http://localhost:${this.port}/`); this.startRealTimeUpdates(); resolve(); }); }); } /** * Stop the server */ async stop() { this.stopRealTimeUpdates(); return new Promise((resolve, reject) => { this.server.close((err) => { if (err) { reject(err); } else { resolve(); } }); }); } } exports.VisualizationServer = VisualizationServer;