const http = require('http'); const net = require('net'); const port = 8080; const fulcrumTimeoutMs = 3000; function queryFulcrum(fulcrumUrl, method, params = []) { return new Promise((resolve) => { if (!fulcrumUrl) { resolve({ ok: false, result: null, }); return; } ``` let parsed; try { parsed = new URL(fulcrumUrl); } catch { resolve({ ok: false, result: null, }); return; } if (parsed.protocol !== 'tcp:') { resolve({ ok: false, result: null, }); return; } const host = parsed.hostname; const fulcrumPort = Number(parsed.port); if (!host || !fulcrumPort) { resolve({ ok: false, result: null, }); return; } const socket = net.createConnection({ host, port: fulcrumPort, }); let response = ''; let settled = false; const finish = (value) => { if (settled) return; settled = true; socket.destroy(); resolve(value); }; socket.setTimeout(fulcrumTimeoutMs); socket.on('connect', () => { socket.write( JSON.stringify({ jsonrpc: '2.0', id: 1, method, params, }) + '\n', ); }); socket.on('data', (data) => { response += data.toString(); const lines = response.split('\n'); for (const line of lines) { if (!line.trim()) continue; let message; try { message = JSON.parse(line); } catch { continue; } if (message.error) { finish({ ok: false, result: null, }); return; } if (Object.prototype.hasOwnProperty.call(message, 'result')) { finish({ ok: true, result: message.result, }); return; } } }); socket.on('timeout', () => { finish({ ok: false, result: null, }); }); socket.on('error', () => { finish({ ok: false, result: null, }); }); socket.on('close', () => { finish({ ok: false, result: null, }); }); ``` }); } async function getFulcrumStatus(fulcrumUrl) { const version = await queryFulcrum( fulcrumUrl, 'server.version', ['Munin Bitcoin', '1.4'], ); if (!version.ok) { return { configured: Boolean(fulcrumUrl), connected: false, url: fulcrumUrl, serverVersion: null, blockchainHeight: null, }; } const headers = await queryFulcrum( fulcrumUrl, 'blockchain.headers.subscribe', [], ); return { configured: Boolean(fulcrumUrl), connected: true, url: fulcrumUrl, serverVersion: version.result, blockchainHeight: headers.ok && headers.result ? headers.result.height ?? null : null, }; } async function getStatus() { const fulcrumUrl = process.env.MUNIN_FULCRUM_URL || null; const fulcrum = await getFulcrumStatus(fulcrumUrl); return { service: 'running', fulcrum, wallet: 'not configured', labels: 0, transactions: 0, lastScan: 'never', }; } const server = http.createServer(async (req, res) => { if (req.url === '/api/status') { try { const status = await getStatus(); ``` res.writeHead(200, { 'Content-Type': 'application/json', }); res.end(JSON.stringify(status)); } catch (error) { console.error('Failed to get service status:', error); res.writeHead(500, { 'Content-Type': 'application/json', }); res.end( JSON.stringify({ service: 'running', error: 'Failed to determine service status', }), ); } return; ``` } res.writeHead(404); res.end('Not found'); }); server.listen(port, () => { console.log(`Status API listening on port ${port}`); });