feat: v2 — view-key payment confirmation with live monitoring

- Payment monitor: enter private view key to track incoming payments
- Scans mempool + last 100 blocks via PHP proxy with 4-node failover
- Lightweight crypto: 30KB noble-curves bundle (Ed25519 + Keccak-256)
- Subaddress support (network byte 42 detection, a*D validation)
- Confirmation progress bar (0-10 confirmations)
- Underpayment detection
- Deadline badges (7/14/30 days) replacing minutes input
- QR code: standard colors (black on white) for wallet scanner compatibility
- QR hint positioned below QR code
- View key masked input, never stored or transmitted
This commit is contained in:
Alexander Schmidt
2026-03-25 09:09:46 +01:00
parent 35552b7dff
commit 1acf990943
9 changed files with 1062 additions and 31 deletions

View File

@@ -44,8 +44,13 @@
</div>
<div class="field">
<label for="timer" data-i18n="label_timer"></label>
<input type="number" id="timer" data-i18n-placeholder="placeholder_timer" min="1" step="1">
<label data-i18n="label_timer"></label>
<div class="deadline-badges" id="deadlineBadges">
<button type="button" class="badge" data-days="7">7 <span data-i18n="days"></span></button>
<button type="button" class="badge" data-days="14">14 <span data-i18n="days"></span></button>
<button type="button" class="badge" data-days="30">30 <span data-i18n="days"></span></button>
<input type="number" id="timerCustom" data-i18n-placeholder="placeholder_timer_custom" min="1" step="1" class="badge-input">
</div>
</div>
<button class="btn btn-primary" id="generate" disabled data-i18n="btn_generate"></button>
@@ -68,6 +73,34 @@
<a class="btn btn-secondary" id="openWallet" href="#" data-i18n="btn_open_wallet"></a>
<button class="btn btn-secondary" id="copyAddr" data-i18n="btn_copy_addr"></button>
</div>
<!-- Payment Monitor (v2) -->
<div class="monitor-section" id="monitorSection">
<button class="btn btn-monitor" id="monitorToggle">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"/>
<path d="M7 11V7a5 5 0 0 1 10 0v4"/>
</svg>
<span data-i18n="btn_monitor"></span>
</button>
<div class="monitor-panel" id="monitorPanel">
<div class="field">
<label for="viewKey" data-i18n="label_view_key"></label>
<input type="text" id="viewKey" data-i18n-placeholder="placeholder_view_key" spellcheck="false" autocomplete="off" class="mono-masked">
<div class="view-key-hint" data-i18n="hint_view_key"></div>
</div>
<button class="btn btn-primary" id="startMonitor" disabled data-i18n="btn_start_monitor"></button>
<div class="monitor-status" id="monitorStatus">
<div class="status-indicator" id="statusIndicator"></div>
<div class="status-text" id="statusText"></div>
<div class="confirmations-bar" id="confirmationsBar">
<div class="confirmations-fill" id="confirmationsFill"></div>
<span class="confirmations-text" id="confirmationsText"></span>
</div>
</div>
<button class="btn btn-secondary" id="stopMonitor" data-i18n="btn_stop_monitor"></button>
</div>
</div>
<button class="btn btn-primary btn-new" id="newRequest" data-i18n="btn_new_request"></button>
</div>
</main>
@@ -93,5 +126,6 @@
<script src="lib/qrcode.min.js"></script>
<script src="i18n.js"></script>
<script src="app.js"></script>
<script src="monitor.js"></script>
</body>
</html>