144 lines
8.3 KiB
HTML
144 lines
8.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>xmrpay — Monero Invoice Generator</title>
|
|
<meta name="description" content="Self-hosted Monero payment requests in seconds. No accounts, no KYC, no tracking. Generate QR codes, PDF invoices, and verify payments.">
|
|
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self'; connect-src 'self'; form-action 'none'; base-uri 'none'">
|
|
<link rel="icon" id="favicon" href="favicon.svg" type="image/svg+xml">
|
|
<link rel="preload" href="fonts/inter-400.woff2" as="font" type="font/woff2" crossorigin>
|
|
<link rel="stylesheet" href="style.css?v=20260326-3" integrity="sha384-HrVyafi6sY5wzJh/jPfdCAq5WytRoWDiUnZ/Y05Xt2Oz1C+kLZLO47euo7q3fv46" crossorigin="anonymous">
|
|
</head>
|
|
<body>
|
|
|
|
<div class="self-host-banner" id="selfHostBanner" hidden>
|
|
<span data-i18n-html="self_host_banner">This is a public demo. For real payments, <a href="https://github.com/schmidt1024/xmrpay#self-host-in-60-seconds">host your own instance</a> — it takes 60 seconds.</span>
|
|
<button id="dismissBanner" aria-label="Dismiss">×</button>
|
|
</div>
|
|
|
|
<header>
|
|
<h1><a href="/" id="homeLink">xmr<span>pay</span></a></h1>
|
|
<p data-i18n="subtitle">Monero payment request in seconds</p>
|
|
</header>
|
|
|
|
<main>
|
|
<div class="card">
|
|
<div class="field">
|
|
<label for="addr" data-i18n="label_addr">XMR Address</label>
|
|
<input type="text" id="addr" data-i18n-placeholder="placeholder_addr" placeholder="8..." spellcheck="false" autocomplete="off">
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="amount" data-i18n="label_amount">Amount</label>
|
|
<div class="amount-row">
|
|
<input type="number" id="amount" placeholder="0.00" min="0" step="any">
|
|
<select id="currency" data-i18n-aria="aria_currency" aria-label="Currency">
|
|
<option value="XMR">XMR</option>
|
|
<option value="EUR">EUR</option>
|
|
<option value="USD" selected>USD</option>
|
|
<option value="CHF">CHF</option>
|
|
<option value="GBP">GBP</option>
|
|
<option value="JPY">JPY</option>
|
|
<option value="RUB">RUB</option>
|
|
<option value="BRL">BRL</option>
|
|
</select>
|
|
</div>
|
|
<div class="fiat-hint" id="fiatHint"></div>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="desc" data-i18n="label_desc">Description (optional)</label>
|
|
<textarea id="desc" data-i18n-placeholder="placeholder_desc" placeholder="e.g. Invoice #42, freelance work..."></textarea>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label data-i18n="label_timer">Payment deadline (optional)</label>
|
|
<div class="deadline-badges" id="deadlineBadges">
|
|
<button type="button" class="badge" data-days="7">7 <span data-i18n="days">days</span></button>
|
|
<button type="button" class="badge" data-days="14">14 <span data-i18n="days">days</span></button>
|
|
<button type="button" class="badge" data-days="30">30 <span data-i18n="days">days</span></button>
|
|
<input type="number" id="timerCustom" data-i18n-placeholder="placeholder_timer_custom" placeholder="Days" min="1" step="1" class="badge-input">
|
|
</div>
|
|
</div>
|
|
|
|
<button class="btn btn-primary" id="generate" disabled data-i18n="btn_generate">Create payment request</button>
|
|
</div>
|
|
|
|
<div id="result" class="card">
|
|
<div class="qr-container" id="qr"></div>
|
|
<div class="payment-summary" id="paymentSummary"></div>
|
|
<div class="payment-status" id="paymentStatus"></div>
|
|
<div class="countdown" id="countdown"></div>
|
|
<div class="uri-box" id="uri" style="display:none"></div>
|
|
<div class="share-link-box" id="shareLinkBox">
|
|
<label data-i18n="label_share_link">Shareable link</label>
|
|
<div class="shortlink-toggle-row">
|
|
<label class="shortlink-toggle-label">
|
|
<input type="checkbox" id="useShortLink">
|
|
<span data-i18n="shortlink_toggle_label">Use short link (requires server trust)</span>
|
|
</label>
|
|
<div class="shortlink-tradeoff" data-i18n="shortlink_toggle_hint">Trade-off: short links are convenient, but a compromised server could swap invoice data on first access.</div>
|
|
</div>
|
|
<div class="share-link-row">
|
|
<input type="text" id="shareLink" readonly data-i18n-aria="label_share_link">
|
|
<button class="btn btn-secondary btn-icon" id="copyShareLink" title="Copy">
|
|
<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="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="actions">
|
|
<button class="btn btn-secondary" id="openWallet" data-i18n="btn_open_wallet">Open in wallet</button>
|
|
<button class="btn btn-secondary" id="copyUri" data-i18n="btn_copy_uri">Copy payment URI</button>
|
|
<button class="btn btn-secondary" id="copyAddr" data-i18n="btn_copy_addr">Copy address</button>
|
|
<button class="btn btn-secondary" id="downloadPdf" data-i18n="btn_download_pdf">PDF Invoice</button>
|
|
</div>
|
|
<!-- TX Proof Verification -->
|
|
<div class="proof-section" id="proofSection">
|
|
<button class="btn btn-proof" id="proofToggle">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
|
|
<polyline points="22 4 12 14.01 9 11.01"/>
|
|
</svg>
|
|
<span data-i18n="btn_prove_payment">Prove payment</span>
|
|
</button>
|
|
<div class="proof-panel" id="proofPanel">
|
|
<div class="field">
|
|
<label for="txHash" data-i18n="label_tx_hash">Transaction ID (TX Hash)</label>
|
|
<input type="text" id="txHash" data-i18n-placeholder="placeholder_tx_hash" placeholder="64 hex characters..." spellcheck="false" autocomplete="off">
|
|
</div>
|
|
<div class="field">
|
|
<label for="txKey" data-i18n="label_tx_key">Transaction Key (TX Key)</label>
|
|
<input type="text" id="txKey" data-i18n-placeholder="placeholder_tx_key" placeholder="64 hex characters..." spellcheck="false" autocomplete="off">
|
|
</div>
|
|
<button class="btn btn-primary" id="verifyProof" disabled data-i18n="btn_verify_proof">Verify payment</button>
|
|
<div class="proof-result" id="proofResult"></div>
|
|
</div>
|
|
</div>
|
|
<button class="btn btn-primary btn-new" id="newRequest" data-i18n="btn_new_request">New payment request</button>
|
|
</div>
|
|
</main>
|
|
|
|
<footer>
|
|
<p data-i18n-html="footer">Open Source · No Tracking · No KYC<br /><a href="https://github.com/schmidt1024/xmrpay" target="_blank" rel="noopener noreferrer">Source</a> · <a href="http://mc6wfeaqc7oijgdcudrr5zsotmwok3jzk3tu2uezzyjisn7nzzjjizyd.onion" title="Tor Hidden Service">Onion</a> · <a href="/privacy.html">Privacy & Terms</a><br /><span class="version">v1.1.1</span></p>
|
|
</footer>
|
|
|
|
<div class="lang-picker" id="langPicker">
|
|
<button class="lang-toggle" id="langToggle" aria-label="Language">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M2 12h20"/>
|
|
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10A15.3 15.3 0 0 1 12 2z"/>
|
|
</svg>
|
|
</button>
|
|
<div class="lang-dropdown" id="langDropdown"></div>
|
|
</div>
|
|
|
|
<div class="toast" id="toast"></div>
|
|
|
|
<script src="lib/qrcode.min.js?v=20260326-3" integrity="sha384-3zSEDfvllQohrq0PHL1fOXJuC/jSOO34H46t6UQfobFOmxE5BpjjaIJY5F2/bMnU" crossorigin="anonymous" defer></script>
|
|
<script src="i18n.min.js?v=20260326-3" integrity="sha384-GS62r/FP1LcB9Ec+ow+45oUWdQsjZKKwtPT6D/YXBfgGjUCjtpuxeLE3GMtbItgx" crossorigin="anonymous" defer></script>
|
|
<script src="app.min.js?v=20260326-3" integrity="sha384-JORIDcn40te850GEco3PPlCjpMXhAbHLSVu8t5BSX4g7XaQyUsGK3IaXLC+1AUYk" crossorigin="anonymous" defer></script>
|
|
</body>
|
|
</html>
|