archy/docker/lnd-ui/index.html
Dorian 6a018e4953 Implement Bitcoin and LND UI in Docker setup and enhance startup script
- Added Docker services for Bitcoin Core UI and LND UI, providing web interfaces for both applications.
- Updated the startup script to improve image pulling process and service readiness checks with retries.
- Modified the app view to open the Bitcoin Core UI in a new tab instead of routing through the app.
- Removed the Bitcoin Core Vue component as it is no longer needed, streamlining the UI structure.
- Excluded backend services from the app listing to improve clarity in the Docker package scanner.
2026-01-27 23:57:29 +00:00

602 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lightning Network - Archipelago</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', sans-serif;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
min-height: 100vh;
color: white;
padding: 2rem;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
.glass-card {
background-color: rgba(0, 0, 0, 0.65);
backdrop-filter: blur(18px);
-webkit-backdrop-filter: blur(18px);
border: 1px solid rgba(255, 255, 255, 0.18);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
border-radius: 1rem;
transition: all 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.6);
}
.glass-button {
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(18px);
-webkit-backdrop-filter: blur(18px);
border: 1px solid rgba(255, 255, 255, 0.18);
color: rgba(255, 255, 255, 0.9);
cursor: pointer;
transition: all 0.3s ease;
font-size: 0.875rem;
font-weight: 500;
}
.glass-button:hover {
background-color: rgba(0, 0, 0, 0.8);
border-color: rgba(255, 255, 255, 0.3);
transform: translateY(-1px);
}
.gradient-button {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(0, 0, 0, 0.8) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
color: rgba(255, 255, 255, 0.95);
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.gradient-button:hover {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(0, 0, 0, 0.9) 100%);
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
}
.hero {
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.hero-content {
display: flex;
align-items: center;
gap: 1.5rem;
}
.app-icon {
width: 5rem;
height: 5rem;
border-radius: 0.75rem;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
flex-shrink: 0;
background: linear-gradient(135deg, #8B5CF6 0%, #7C3AED 100%);
padding: 1rem;
}
.app-info {
flex: 1;
min-width: 0;
}
.app-title {
font-size: 1.5rem;
font-weight: 700;
color: white;
margin-bottom: 0.25rem;
}
.app-description {
color: rgba(255, 255, 255, 0.7);
font-size: 0.875rem;
margin-bottom: 0.5rem;
}
.status-badge {
display: inline-flex;
align-items: center;
padding: 0.375rem 0.625rem;
border-radius: 0.5rem;
font-size: 0.75rem;
font-weight: 500;
}
.status-running {
background: rgba(34, 197, 94, 0.2);
color: rgb(134, 239, 172);
border: 1px solid rgba(34, 197, 94, 0.3);
}
.status-dot {
width: 0.375rem;
height: 0.375rem;
border-radius: 50%;
margin-right: 0.375rem;
background: rgb(74, 222, 128);
}
.version-badge {
color: rgba(255, 255, 255, 0.5);
font-size: 0.75rem;
margin-left: 0.5rem;
}
.action-buttons {
display: flex;
gap: 0.5rem;
flex-shrink: 0;
}
.action-buttons button {
padding: 0.625rem 1rem;
border-radius: 0.5rem;
font-size: 0.875rem;
display: flex;
align-items: center;
gap: 0.5rem;
border: none;
}
.grid-2col {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 1.5rem;
}
.info-card {
padding: 1.5rem;
}
.info-card h2 {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 1rem;
color: white;
}
.info-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.info-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.info-label {
color: rgba(255, 255, 255, 0.6);
font-size: 0.875rem;
}
.info-value {
color: white;
font-weight: 500;
font-family: 'Courier New', monospace;
}
.connection-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 1rem;
background: rgba(255, 255, 255, 0.03);
border-radius: 0.5rem;
border: 1px solid rgba(255, 255, 255, 0.05);
margin-bottom: 0.75rem;
}
.connection-icon {
width: 2.5rem;
height: 2.5rem;
background: rgba(139, 92, 246, 0.2);
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
flex-shrink: 0;
}
.connection-content {
flex: 1;
}
.connection-label {
color: rgba(255, 255, 255, 0.6);
font-size: 0.75rem;
margin-bottom: 0.25rem;
}
.connection-value {
color: white;
font-size: 0.875rem;
font-weight: 600;
font-family: 'Courier New', monospace;
word-break: break-all;
}
.copy-btn {
padding: 0.5rem 0.75rem;
border-radius: 0.5rem;
border: 1px solid rgba(255, 255, 255, 0.18);
background: rgba(0, 0, 0, 0.6);
color: rgba(255, 255, 255, 0.9);
font-size: 0.75rem;
cursor: pointer;
transition: all 0.2s ease;
}
.copy-btn:hover {
background: rgba(0, 0, 0, 0.8);
transform: scale(1.05);
}
.modal {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(10px);
z-index: 1000;
align-items: center;
justify-content: center;
padding: 2rem;
}
.modal.active {
display: flex;
}
.modal-content {
max-width: 50rem;
width: 100%;
max-height: 80vh;
overflow-y: auto;
padding: 2rem;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.modal-title {
font-size: 1.5rem;
font-weight: 700;
}
.modal-close {
width: 2.5rem;
height: 2.5rem;
border-radius: 0.5rem;
background: rgba(255, 255, 255, 0.1);
border: none;
color: white;
cursor: pointer;
font-size: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.modal-close:hover {
background: rgba(255, 255, 255, 0.2);
transform: rotate(90deg);
}
.logs-container {
background: rgba(0, 0, 0, 0.4);
border-radius: 0.5rem;
padding: 1rem;
font-family: 'Courier New', monospace;
font-size: 0.75rem;
line-height: 1.6;
color: rgba(255, 255, 255, 0.8);
white-space: pre-wrap;
word-break: break-all;
}
@media (max-width: 768px) {
.hero-content {
flex-direction: column;
text-align: center;
}
.action-buttons {
flex-direction: column;
width: 100%;
}
.grid-2col {
grid-template-columns: 1fr;
}
.info-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<div class="glass-card hero">
<div class="hero-content">
<div class="app-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="white" viewBox="0 0 24 24">
<path d="M13 2L3 14h8l-1 8 10-12h-8l1-8z"/>
</svg>
</div>
<div class="app-info">
<h1 class="app-title">Lightning Network (LND)</h1>
<p class="app-description">Lightning Network Daemon for instant Bitcoin payments</p>
<div>
<span class="status-badge status-running" id="statusBadge">
<span class="status-dot"></span>
Running
</span>
<span class="version-badge">v0.17.4-beta</span>
</div>
</div>
<div class="action-buttons">
<button class="gradient-button" onclick="openLogs()">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
Logs
</button>
<button class="glass-button" onclick="openSettings()">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
Settings
</button>
</div>
</div>
</div>
<div class="grid-2col">
<div>
<div class="glass-card info-card" style="margin-bottom: 1.5rem;">
<h2>Node Status</h2>
<div class="info-grid">
<div class="info-item">
<span class="info-label">Network</span>
<span class="info-value">Regtest</span>
</div>
<div class="info-item">
<span class="info-label">Channels</span>
<span class="info-value" id="channelCount">0</span>
</div>
<div class="info-item">
<span class="info-label">gRPC Port</span>
<span class="info-value">10009</span>
</div>
<div class="info-item">
<span class="info-label">REST Port</span>
<span class="info-value">8080</span>
</div>
</div>
</div>
<div class="glass-card info-card">
<h2>Connection Details</h2>
<div class="connection-item">
<div class="connection-icon">🌐</div>
<div class="connection-content">
<div class="connection-label">REST API</div>
<div class="connection-value">http://localhost:8080</div>
</div>
<button class="copy-btn" onclick="copyToClipboard('http://localhost:8080')">Copy</button>
</div>
<div class="connection-item">
<div class="connection-icon">📡</div>
<div class="connection-content">
<div class="connection-label">gRPC Host</div>
<div class="connection-value">localhost:10009</div>
</div>
<button class="copy-btn" onclick="copyToClipboard('localhost:10009')">Copy</button>
</div>
<div class="connection-item">
<div class="connection-icon"></div>
<div class="connection-content">
<div class="connection-label">P2P Port</div>
<div class="connection-value">9735</div>
</div>
<button class="copy-btn" onclick="copyToClipboard('9735')">Copy</button>
</div>
<div class="connection-item">
<div class="connection-icon">🔗</div>
<div class="connection-content">
<div class="connection-label">Bitcoin Backend</div>
<div class="connection-value">bitcoin:18443</div>
</div>
<button class="copy-btn" onclick="copyToClipboard('bitcoin:18443')">Copy</button>
</div>
</div>
</div>
<div class="glass-card info-card">
<h2>About LND</h2>
<p style="color: rgba(255, 255, 255, 0.8); line-height: 1.6; margin-bottom: 1.5rem;">
The Lightning Network Daemon (LND) is a complete implementation of a Lightning Network node. It enables instant, low-fee Bitcoin transactions through payment channels.
</p>
<h3 style="font-size: 1.125rem; font-weight: 600; margin-bottom: 0.75rem;">Features</h3>
<ul style="list-style: none; padding: 0;">
<li style="display: flex; align-items: start; gap: 0.75rem; margin-bottom: 0.75rem; color: rgba(255, 255, 255, 0.8);">
<svg style="width: 1.5rem; height: 1.5rem; color: rgb(74, 222, 128); flex-shrink: 0; margin-top: 0.125rem;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>Instant payments</span>
</li>
<li style="display: flex; align-items: start; gap: 0.75rem; margin-bottom: 0.75rem; color: rgba(255, 255, 255, 0.8);">
<svg style="width: 1.5rem; height: 1.5rem; color: rgb(74, 222, 128); flex-shrink: 0; margin-top: 0.125rem;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>Low transaction fees</span>
</li>
<li style="display: flex; align-items: start; gap: 0.75rem; margin-bottom: 0.75rem; color: rgba(255, 255, 255, 0.8);">
<svg style="width: 1.5rem; height: 1.5rem; color: rgb(74, 222, 128); flex-shrink: 0; margin-top: 0.125rem;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>REST & gRPC APIs</span>
</li>
<li style="display: flex; align-items: start; gap: 0.75rem; color: rgba(255, 255, 255, 0.8);">
<svg style="width: 1.5rem; height: 1.5rem; color: rgb(74, 222, 128); flex-shrink: 0; margin-top: 0.125rem;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>Channel management</span>
</li>
</ul>
<div style="margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid rgba(255, 255, 255, 0.1);">
<div style="display: flex; justify-content: space-between; padding: 0.5rem 0;">
<span style="color: rgba(255, 255, 255, 0.6); font-size: 0.875rem;">Version</span>
<span style="color: white; font-weight: 500;">0.17.4-beta</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 0.5rem 0;">
<span style="color: rgba(255, 255, 255, 0.6); font-size: 0.875rem;">License</span>
<span style="color: white; font-weight: 500;">MIT</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 0.5rem 0;">
<span style="color: rgba(255, 255, 255, 0.6); font-size: 0.875rem;">Developer</span>
<span style="color: white; font-weight: 500;">Lightning Labs</span>
</div>
</div>
</div>
</div>
</div>
<div class="modal" id="settingsModal">
<div class="modal-content glass-card">
<div class="modal-header">
<h2 class="modal-title">Node Settings</h2>
<button class="modal-close" onclick="closeSettings()">×</button>
</div>
<div style="padding: 1rem; background: rgba(255, 255, 255, 0.03); border-radius: 0.5rem; margin-bottom: 0.75rem;">
<div style="font-weight: 600; margin-bottom: 0.5rem; color: white;">Network Mode</div>
<div style="color: rgba(255, 255, 255, 0.7);">Regtest (Development)</div>
</div>
<div style="padding: 1rem; background: rgba(255, 255, 255, 0.03); border-radius: 0.5rem; margin-bottom: 0.75rem;">
<div style="font-weight: 600; margin-bottom: 0.5rem; color: white;">Bitcoin Backend</div>
<div style="color: rgba(255, 255, 255, 0.7);">Connected to bitcoin:18443</div>
</div>
<div style="padding: 1rem; background: rgba(255, 255, 255, 0.03); border-radius: 0.5rem; margin-bottom: 0.75rem;">
<div style="font-weight: 600; margin-bottom: 0.5rem; color: white;">ZMQ Subscriptions</div>
<div style="color: rgba(255, 255, 255, 0.7);">Blocks & Transactions monitored</div>
</div>
<div style="padding: 1rem; background: rgba(255, 255, 255, 0.03); border-radius: 0.5rem;">
<div style="font-weight: 600; margin-bottom: 0.5rem; color: white;">Seed Backup</div>
<div style="color: rgba(255, 255, 255, 0.7);">Disabled (Development mode)</div>
</div>
</div>
</div>
<div class="modal" id="logsModal">
<div class="modal-content glass-card">
<div class="modal-header">
<h2 class="modal-title">Node Logs</h2>
<button class="modal-close" onclick="closeLogs()">×</button>
</div>
<div class="logs-container" id="logsContent">
Loading logs...
</div>
</div>
</div>
<script>
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
alert('Copied to clipboard!');
}).catch(err => {
console.error('Failed to copy:', err);
});
}
function openSettings() {
document.getElementById('settingsModal').classList.add('active');
}
function closeSettings() {
document.getElementById('settingsModal').classList.remove('active');
}
function openLogs() {
document.getElementById('logsModal').classList.add('active');
loadLogs();
}
function closeLogs() {
document.getElementById('logsModal').classList.remove('active');
}
function loadLogs() {
const logsContent = document.getElementById('logsContent');
logsContent.textContent = `LND version 0.17.4-beta commit=v0.17.4-beta
Attempting automatic RPC configuration to bitcoind
Automatically obtained bitcoind's RPC credentials
2024-01-15 12:00:00.000 [INF] LTND: Version: 0.17.4-beta commit=v0.17.4-beta
2024-01-15 12:00:00.100 [INF] LTND: Active chain: Bitcoin (network=regtest)
2024-01-15 12:00:00.200 [INF] CHDB: Checking for schema update
2024-01-15 12:00:00.300 [INF] LTND: Primary chain is set to: bitcoin
2024-01-15 12:00:01.000 [INF] RPCS: RPC server listening on 0.0.0.0:10009
2024-01-15 12:00:01.100 [INF] RPCS: REST proxy started at 0.0.0.0:8080
2024-01-15 12:00:01.200 [INF] LNWL: Opened wallet
2024-01-15 12:00:02.000 [INF] LTND: Waiting for chain backend to finish sync`;
}
let channelCount = 0;
setInterval(() => {
if (Math.random() > 0.9) {
channelCount = Math.floor(Math.random() * 5);
document.getElementById('channelCount').textContent = channelCount;
}
}, 10000);
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeSettings();
closeLogs();
}
});
document.querySelectorAll('.modal').forEach(modal => {
modal.addEventListener('click', (e) => {
if (e.target === modal) {
closeSettings();
closeLogs();
}
});
});
</script>
</body>
</html>