diff --git a/api/rates.php b/api/rates.php index 5a274b3..d101ce5 100644 --- a/api/rates.php +++ b/api/rates.php @@ -15,7 +15,9 @@ if (file_exists($cacheFile)) { } } -$url = 'https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=eur,usd,chf'; +$currencies = $_GET['c'] ?? 'eur,usd,chf,gbp,jpy,rub,brl'; +$currencies = preg_replace('/[^a-z,]/', '', strtolower($currencies)); +$url = 'https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=' . $currencies; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, diff --git a/app.js b/app.js index 36a3100..4d69297 100644 --- a/app.js +++ b/app.js @@ -2,7 +2,7 @@ 'use strict'; // --- Config --- - const COINGECKO_API = '/api/rates.php'; + const COINGECKO_API = '/api/rates.php?c=eur,usd,chf,gbp,jpy,rub,brl'; // Standard address (4..., 95 chars), Subaddress (8..., 95 chars), Integrated address (4..., 106 chars) const XMR_STANDARD_REGEX = /^[48][1-9A-HJ-NP-Za-km-z]{94}$/; const XMR_INTEGRATED_REGEX = /^4[1-9A-HJ-NP-Za-km-z]{105}$/; @@ -13,6 +13,7 @@ let fiatRates = null; let ratesTimestamp = 0; let countdownInterval = null; + let countdownTick = null; let ratesFailed = false; let invoiceCode = null; // short URL code for this invoice @@ -53,7 +54,35 @@ let pdfLoaded = false; let lastPaidData = null; + // --- Currency Detection --- + function detectCurrency() { + var localeToCurrency = { + 'de': 'EUR', 'fr': 'EUR', 'it': 'EUR', 'es': 'EUR', 'pt': 'EUR', 'nl': 'EUR', + 'de-CH': 'CHF', 'fr-CH': 'CHF', 'it-CH': 'CHF', + 'de-AT': 'EUR', + 'en-GB': 'GBP', + 'en-US': 'USD', 'en': 'USD', + 'ja': 'JPY', + 'ru': 'RUB', + 'pt-BR': 'BRL' + }; + var langs = navigator.languages || [navigator.language || 'en']; + for (var i = 0; i < langs.length; i++) { + var tag = langs[i]; + if (localeToCurrency[tag]) { + currencySelect.value = localeToCurrency[tag]; + return; + } + var short = tag.substring(0, 2).toLowerCase(); + if (localeToCurrency[short]) { + currencySelect.value = localeToCurrency[short]; + return; + } + } + } + // --- Init --- + detectCurrency(); fetchRates(); loadFromHash() || loadSaved(); registerSW(); @@ -77,6 +106,8 @@ buildSummary(xmrAmount, desc, selectedDays); updatePageTitle(xmrAmount, desc); } + // Countdown text + if (countdownTick) countdownTick(); }); // --- Events --- @@ -410,6 +441,7 @@ } } + countdownTick = tick; tick(); countdownInterval = setInterval(tick, 60000); // Update every minute, not every second } diff --git a/app.min.js b/app.min.js index df99520..cf246e1 100644 --- a/app.min.js +++ b/app.min.js @@ -1 +1 @@ -(function(){"use strict";const St="/api/rates.php",It=/^[48][1-9A-HJ-NP-Za-km-z]{94}$/,_t=/^4[1-9A-HJ-NP-Za-km-z]{105}$/;let y=null,lt=0,_=null,B=!1,T=null;const i=e=>document.querySelector(e),u=i("#addr"),L=i("#amount"),w=i("#currency"),H=i("#desc"),F=i("#timerCustom"),M=i("#deadlineBadges");let f=0;const tt=i("#generate"),U=i("#result"),v=i("#qr"),et=i("#uri"),dt=i("#openWallet"),Tt=i("#copyAddr"),S=i("#countdown"),h=i("#fiatHint"),nt=i("#toast"),q=i("#shareLink"),Ft=i("#copyShareLink"),Et=i("#newRequest"),Rt=i("#homeLink"),bt=i("#proofToggle"),N=i("#proofPanel"),E=i("#txHash"),O=i("#txKey"),R=i("#verifyProof"),m=i("#proofResult"),W=i("#paymentStatus"),ut=i("#paymentSummary"),Pt=i("#downloadPdf");let ft=!1,kt=!1,g=null;xt(),qt()||Bt(),Ut(),I18n.onChange(function(){var e=v.querySelector(".qr-hint");e&&(e.textContent=I18n.t("qr_hint"));var t=v.querySelector(".paid-stamp");if(t&&(t.textContent=I18n.t("status_paid")),g&&rt(g),U.classList.contains("visible")){var n=ot(),a=H.value.trim();pt(n,a,f),ht(n,a)}}),u.addEventListener("input",at),L.addEventListener("input",G),w.addEventListener("change",G),tt.addEventListener("click",mt),Tt.addEventListener("click",()=>gt(u.value.trim())),Ft.addEventListener("click",()=>gt(q.value)),v.addEventListener("click",At),Et.addEventListener("click",vt),Rt.addEventListener("click",function(e){e.preventDefault(),vt()}),M.querySelectorAll(".badge").forEach(function(e){e.addEventListener("click",function(){const t=parseInt(e.getAttribute("data-days"));e.classList.contains("active")?(e.classList.remove("active"),f=0,F.value=""):(M.querySelectorAll(".badge").forEach(function(n){n.classList.remove("active")}),e.classList.add("active"),f=t,F.value="")})}),F.addEventListener("input",function(){M.querySelectorAll(".badge").forEach(function(e){e.classList.remove("active")}),f=parseInt(F.value)||0}),Pt.addEventListener("click",Wt),bt.addEventListener("click",Gt),E.addEventListener("input",Ct),O.addEventListener("input",Ct),R.addEventListener("click",Yt);function vt(){u.value="",L.value="",w.value="EUR",H.value="",f=0,F.value="",M.querySelectorAll(".badge").forEach(function(e){e.classList.remove("active")}),h.textContent="",h.classList.remove("error"),u.classList.remove("valid","invalid"),tt.disabled=!0,U.classList.remove("visible"),_&&clearInterval(_),v.innerHTML="",et.textContent="",q.value="",T=null,N.classList.remove("open"),E.value="",O.value="",R.disabled=!0,m.innerHTML="",m.className="proof-result",W.innerHTML="",W.className="payment-status",ut.innerHTML="",document.title="xmrpay.link \u2014 Monero Invoice Generator",history.replaceState(null,"",location.pathname),window.scrollTo({top:0,behavior:"smooth"}),u.focus()}function A(e){return It.test(e)||_t.test(e)}function at(){const e=u.value.trim();u.classList.remove("valid","invalid"),e.length!==0&&(A(e)?u.classList.add("valid"):e.length>=10&&u.classList.add("invalid"),Xt())}function Xt(){const e=u.value.trim();tt.disabled=!A(e)}function G(){const e=parseFloat(L.value),t=w.value;if(!e||e<=0){h.textContent="",h.classList.remove("error");return}if(t!=="XMR"&&!y){h.textContent=B?I18n.t("rates_offline"):"",h.classList.toggle("error",B);return}if(h.classList.remove("error"),t==="XMR")if(y){const n=(e*y.eur).toFixed(2);h.textContent="\u2248 "+n+" EUR"}else h.textContent="";else{const n=y[t.toLowerCase()];if(n&&n>0){const a=(e/n).toFixed(8);h.textContent="\u2248 "+a+" XMR"}}}function ot(){const e=parseFloat(L.value),t=w.value;if(!e||e<=0)return null;if(t==="XMR")return e;if(y){const n=y[t.toLowerCase()];if(n&&n>0)return e/n}return null}function Dt(e,t,n){let a="monero:"+e;const o=[];return t&&o.push("tx_amount="+t.toFixed(12)),n&&o.push("tx_description="+encodeURIComponent(n)),o.length&&(a+="?"+o.join("&")),a}function Ht(e,t,n,a){const o=new URLSearchParams;return o.set("a",e),t&&o.set("x",t.toFixed(12)),n&&o.set("d",n),a&&o.set("t",a),o.toString()}async function Mt(e){try{const t=await fetch("/api/shorten.php",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({hash:e})});if(!t.ok)throw new Error("HTTP "+t.status);const n=await t.json();return T||(T=n.code),location.origin+"/s/"+n.code}catch(t){return console.warn("Short URL failed:",t),null}}function mt(){const e=u.value.trim();if(!A(e))return;const t=ot(),n=H.value.trim(),a=f,o=Dt(e,t,n);U.classList.add("visible"),et.textContent=o,dt.onclick=function(){window.location.href=o},pt(t,n,a),ht(t,n);const c=Ht(e,t,n,a);q.value=location.origin+"/#"+c,Mt(c).then(function(l){l&&(q.value=l)}),v.innerHTML="",new QRCode(v,{text:o,width:256,height:256,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.M});const d=document.createElement("div");d.className="qr-hint",d.textContent=I18n.t("qr_hint"),v.appendChild(d),Nt(),zt(e),U.scrollIntoView({behavior:"smooth",block:"start"})}function qt(){const e=location.hash.substring(1);if(!e)return!1;const t=new URLSearchParams(e),n=t.get("a");if(!n||!A(n))return!1;u.value=n,at();const a=t.get("x");a&&(L.value=parseFloat(a),w.value="XMR");const o=t.get("d");o&&(H.value=o);const c=t.get("t");if(c&&parseInt(c)>0){f=parseInt(c);const l=M.querySelector('.badge[data-days="'+f+'"]');l?l.classList.add("active"):F.value=f}const d=t.get("c");return d&&(T=d,setTimeout(function(){Jt(d)},200)),setTimeout(mt,100),!0}function pt(e,t,n){var a="";if(e){a+='
'+e.toFixed(8)+" XMR
";var o=parseFloat(L.value),c=w.value;c!=="XMR"&&o&&(a+='
\u2248 '+o.toFixed(2)+" "+c+"
")}t&&(a+='
'+t.replace(/"),ut.innerHTML=a}function ht(e,t){var n=[];e&&n.push(e.toFixed(4)+" XMR"),t&&n.push(t),n.length&&(document.title=n.join(" \u2014 ")+" | xmrpay.link")}function Nt(){if(_&&clearInterval(_),S.textContent="",S.className="countdown",!f||f<=0)return;const e=Date.now()+f*864e5;S.classList.add("active");function t(){const n=e-Date.now();if(n<=0){clearInterval(_),S.textContent=I18n.t("countdown_expired"),S.className="countdown expired";return}const a=Math.floor(n/864e5),o=Math.floor(n%864e5/36e5),c=Math.floor(n%36e5/6e4);a>0?S.textContent=I18n.t("countdown_remaining_days").replace("{d}",a).replace("{h}",o):S.textContent=I18n.t("countdown_remaining_hours").replace("{h}",yt(o)).replace("{m}",yt(c))}t(),_=setInterval(t,6e4)}function yt(e){return e<10?"0"+e:""+e}function At(){const e=v.querySelector("canvas");if(!e)return;const t=document.createElement("a");t.download="xmrpay-qr.png",t.href=e.toDataURL("image/png"),t.click()}function gt(e){navigator.clipboard.writeText(e).then(()=>{jt(I18n.t("toast_copied"))})}function jt(e){nt.textContent=e,nt.classList.add("show"),setTimeout(()=>nt.classList.remove("show"),2e3)}function zt(e){try{localStorage.setItem("xmrpay_addr",e)}catch{}}function Bt(){try{const e=localStorage.getItem("xmrpay_addr");e&&(u.value=e,at())}catch{}}async function xt(){if(!(y&&Date.now()-lt<6e4))try{const e=await fetch(St);if(!e.ok)throw new Error("HTTP "+e.status);y=(await e.json()).monero,lt=Date.now(),B=!1,G()}catch(e){console.warn("Kurse konnten nicht geladen werden:",e),B=!0,G(),setTimeout(xt,1e4)}}function Ut(){"serviceWorker"in navigator&&navigator.serviceWorker.register("sw.js").catch(function(){})}function Ot(){return new Promise(function(e,t){if(window.jspdf){e();return}var n=document.createElement("script");n.src="lib/jspdf.min.js",n.onload=function(){kt=!0,e()},n.onerror=function(){t(new Error("Failed to load jsPDF"))},document.head.appendChild(n)})}async function Wt(){await Ot();var e=window.jspdf.jsPDF,t=new e({orientation:"portrait",unit:"mm",format:"a4"}),n=u.value.trim(),a=ot(),o=H.value.trim(),c=parseFloat(L.value),d=w.value,l=t.internal.pageSize.getWidth(),s=20,x=l-s*2,r=s;t.setFillColor(242,104,33),t.rect(0,0,l,8,"F"),r=22,t.setFont("helvetica","bold"),t.setFontSize(22),t.setTextColor(242,104,33),t.text(I18n.t("pdf_title"),s,r),t.setFont("helvetica","normal"),t.setFontSize(10),t.setTextColor(120,120,120);var it=new Date().toLocaleDateString(I18n.getLang()==="de"?"de-CH":"en-US",{year:"numeric",month:"long",day:"numeric"});t.text(I18n.t("pdf_date")+": "+it,l-s,r,{align:"right"}),r+=6,t.setDrawColor(220,220,220),t.setLineWidth(.3),t.line(s,r,l-s,r);var Y=v.querySelector("canvas"),C=50,b=l-s-C,j=r+6;if(Y){var J=Y.toDataURL("image/png");t.addImage(J,"PNG",b,j,C,C),t.setFontSize(7),t.setTextColor(150,150,150),t.text(I18n.t("pdf_scan_qr"),b+C/2,j+C+4,{align:"center"})}var P=s,V=b-s-10;r+=14;function k($t,Qt){t.setFont("helvetica","normal"),t.setFontSize(9),t.setTextColor(150,150,150),t.text($t,P,r),r+=5,t.setFont("helvetica","bold"),t.setFontSize(11),t.setTextColor(40,40,40);var wt=t.splitTextToSize(Qt,V);t.text(wt,P,r),r+=wt.length*5+4}if(a){var p=a.toFixed(8)+" XMR";d!=="XMR"&&c&&(p+=" (~ "+c.toFixed(2)+" "+d+")"),k(I18n.t("pdf_amount"),p)}if(o&&k(I18n.t("pdf_desc"),o),f>0){var I=new Date(Date.now()+f*864e5),$=I.toLocaleDateString(I18n.getLang()==="de"?"de-CH":"en-US",{year:"numeric",month:"long",day:"numeric"});k(I18n.t("pdf_deadline"),$+" ("+I18n.t("pdf_deadline_days").replace("{d}",f)+")")}r=Math.max(r,j+C+12),t.setFont("helvetica","normal"),t.setFontSize(9),t.setTextColor(150,150,150),t.text(I18n.t("pdf_address"),s,r),r+=5,t.setFillColor(245,245,245),t.roundedRect(s,r-3.5,x,10,2,2,"F"),t.setFont("courier","normal"),t.setFontSize(8),t.setTextColor(60,60,60),t.text(n,s+3,r+2.5),r+=14;var Q=et.textContent;if(Q){t.setFillColor(245,245,245),t.roundedRect(s,r-3.5,x,10,2,2,"F"),t.setFont("courier","normal"),t.setFontSize(6.5),t.setTextColor(100,100,100);var Z=t.splitTextToSize(Q,x-6);t.text(Z,s+3,r+2),r+=Z.length*3+10}if(g){r+=4;var z="";if(g.verified_at){var st=new Date(g.verified_at*1e3);z=st.toLocaleDateString(I18n.getLang()==="de"?"de-CH":"en-US",{year:"numeric",month:"long",day:"numeric"})}var ct=g.amount.toFixed(6)+" XMR \u2014 TX "+g.tx_hash.substring(0,8)+"..."+(z?" \u2014 "+z:"");t.setFillColor(76,175,80),t.roundedRect(s,r-4,x,16,2,2,"F"),t.setFont("helvetica","bold"),t.setFontSize(12),t.setTextColor(255,255,255),t.text(I18n.t("status_paid").toUpperCase(),s+x/2,r+1,{align:"center"}),t.setFont("helvetica","normal"),t.setFontSize(7.5),t.text(ct,s+x/2,r+7,{align:"center"}),r+=22}t.setDrawColor(220,220,220),t.setLineWidth(.3);var X=t.internal.pageSize.getHeight()-15;t.line(s,X,l-s,X),t.setFont("helvetica","normal"),t.setFontSize(7),t.setTextColor(180,180,180),t.text(I18n.t("pdf_footer"),l/2,X+5,{align:"center"});var D=q.value;D&&t.text(D,l/2,X+9,{align:"center"});var Lt="xmrpay-"+(o?o.replace(/[^a-zA-Z0-9]/g,"-").substring(0,30):"invoice")+".pdf";t.save(Lt)}function Gt(){if(N.classList.contains("open")){N.classList.remove("open");return}if(!ft&&!window.XmrCrypto){Kt().then(function(){ft=!0,N.classList.add("open"),E.focus()});return}N.classList.add("open"),E.focus()}function Kt(){return new Promise(function(e,t){if(window.XmrCrypto){e();return}const n=document.createElement("script");n.src="lib/xmr-crypto.bundle.js",n.onload=e,n.onerror=function(){t(new Error("Failed to load crypto module"))},document.head.appendChild(n)})}function K(e){return/^[0-9a-fA-F]{64}$/.test(e)}function Ct(){const e=E.value.trim(),t=O.value.trim();R.disabled=!(K(e)&&K(t))}async function Yt(){const e=E.value.trim(),t=O.value.trim(),n=u.value.trim();if(!(!K(e)||!K(t)||!A(n))){R.disabled=!0,m.className="proof-result active",m.textContent=I18n.t("proof_verifying");try{var a=await fetch("/api/node.php",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({method:"gettransactions",params:{txs_hashes:[e],decode_as_json:!0}})}),o=await a.json(),c=o.txs||[];if(c.length===0){m.className="proof-result active error",m.textContent=I18n.t("proof_tx_not_found"),R.disabled=!1;return}for(var d=c[0],l=JSON.parse(d.as_json),s=XmrCrypto.getKeysFromAddress(n),x=s.publicViewKey,r=s.publicSpendKey,it=XmrCrypto.bytesToScalar(XmrCrypto.hexToBytes(t)),Y=XmrCrypto.Point.fromHex(x),C=Y.multiply(it).multiply(8n),b=C.toBytes(),j=XmrCrypto.Point.fromHex(r),J=l.vout||[],P=l.rct_signatures&&l.rct_signatures.ecdhInfo||[],V=0n,k=!1,p=0;pdocument.querySelector(e),u=i("#addr"),w=i("#amount"),g=i("#currency"),D=i("#desc"),F=i("#timerCustom"),M=i("#deadlineBadges");let f=0;const et=i("#generate"),z=i("#result"),v=i("#qr"),nt=i("#uri"),ut=i("#openWallet"),Ft=i("#copyAddr"),S=i("#countdown"),h=i("#fiatHint"),at=i("#toast"),U=i("#shareLink"),Et=i("#copyShareLink"),Rt=i("#newRequest"),bt=i("#homeLink"),Pt=i("#proofToggle"),q=i("#proofPanel"),E=i("#txHash"),O=i("#txKey"),R=i("#verifyProof"),p=i("#proofResult"),W=i("#paymentStatus"),ft=i("#paymentSummary"),kt=i("#downloadPdf");let vt=!1,Ht=!1,C=null;function Xt(){for(var e={de:"EUR",fr:"EUR",it:"EUR",es:"EUR",pt:"EUR",nl:"EUR","de-CH":"CHF","fr-CH":"CHF","it-CH":"CHF","de-AT":"EUR","en-GB":"GBP","en-US":"USD",en:"USD",ja:"JPY",ru:"RUB","pt-BR":"BRL"},t=navigator.languages||[navigator.language||"en"],n=0;nCt(u.value.trim())),Et.addEventListener("click",()=>Ct(U.value)),v.addEventListener("click",Bt),Rt.addEventListener("click",pt),bt.addEventListener("click",function(e){e.preventDefault(),pt()}),M.querySelectorAll(".badge").forEach(function(e){e.addEventListener("click",function(){const t=parseInt(e.getAttribute("data-days"));e.classList.contains("active")?(e.classList.remove("active"),f=0,F.value=""):(M.querySelectorAll(".badge").forEach(function(n){n.classList.remove("active")}),e.classList.add("active"),f=t,F.value="")})}),F.addEventListener("input",function(){M.querySelectorAll(".badge").forEach(function(e){e.classList.remove("active")}),f=parseInt(F.value)||0}),kt.addEventListener("click",Kt),Pt.addEventListener("click",Yt),E.addEventListener("input",Lt),O.addEventListener("input",Lt),R.addEventListener("click",Vt);function pt(){u.value="",w.value="",g.value="EUR",D.value="",f=0,F.value="",M.querySelectorAll(".badge").forEach(function(e){e.classList.remove("active")}),h.textContent="",h.classList.remove("error"),u.classList.remove("valid","invalid"),et.disabled=!0,z.classList.remove("visible"),T&&clearInterval(T),v.innerHTML="",nt.textContent="",U.value="",_=null,q.classList.remove("open"),E.value="",O.value="",R.disabled=!0,p.innerHTML="",p.className="proof-result",W.innerHTML="",W.className="payment-status",ft.innerHTML="",document.title="xmrpay.link \u2014 Monero Invoice Generator",history.replaceState(null,"",location.pathname),window.scrollTo({top:0,behavior:"smooth"}),u.focus()}function N(e){return Tt.test(e)||_t.test(e)}function rt(){const e=u.value.trim();u.classList.remove("valid","invalid"),e.length!==0&&(N(e)?u.classList.add("valid"):e.length>=10&&u.classList.add("invalid"),Dt())}function Dt(){const e=u.value.trim();et.disabled=!N(e)}function G(){const e=parseFloat(w.value),t=g.value;if(!e||e<=0){h.textContent="",h.classList.remove("error");return}if(t!=="XMR"&&!y){h.textContent=j?I18n.t("rates_offline"):"",h.classList.toggle("error",j);return}if(h.classList.remove("error"),t==="XMR")if(y){const n=(e*y.eur).toFixed(2);h.textContent="\u2248 "+n+" EUR"}else h.textContent="";else{const n=y[t.toLowerCase()];if(n&&n>0){const a=(e/n).toFixed(8);h.textContent="\u2248 "+a+" XMR"}}}function ot(){const e=parseFloat(w.value),t=g.value;if(!e||e<=0)return null;if(t==="XMR")return e;if(y){const n=y[t.toLowerCase()];if(n&&n>0)return e/n}return null}function Mt(e,t,n){let a="monero:"+e;const r=[];return t&&r.push("tx_amount="+t.toFixed(12)),n&&r.push("tx_description="+encodeURIComponent(n)),r.length&&(a+="?"+r.join("&")),a}function Ut(e,t,n,a){const r=new URLSearchParams;return r.set("a",e),t&&r.set("x",t.toFixed(12)),n&&r.set("d",n),a&&r.set("t",a),r.toString()}async function qt(e){try{const t=await fetch("/api/shorten.php",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({hash:e})});if(!t.ok)throw new Error("HTTP "+t.status);const n=await t.json();return _||(_=n.code),location.origin+"/s/"+n.code}catch(t){return console.warn("Short URL failed:",t),null}}function mt(){const e=u.value.trim();if(!N(e))return;const t=ot(),n=D.value.trim(),a=f,r=Mt(e,t,n);z.classList.add("visible"),nt.textContent=r,ut.onclick=function(){window.location.href=r},ht(t,n,a),gt(t,n);const c=Ut(e,t,n,a);U.value=location.origin+"/#"+c,qt(c).then(function(l){l&&(U.value=l)}),v.innerHTML="",new QRCode(v,{text:r,width:256,height:256,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.M});const d=document.createElement("div");d.className="qr-hint",d.textContent=I18n.t("qr_hint"),v.appendChild(d),At(),zt(e),z.scrollIntoView({behavior:"smooth",block:"start"})}function Nt(){const e=location.hash.substring(1);if(!e)return!1;const t=new URLSearchParams(e),n=t.get("a");if(!n||!N(n))return!1;u.value=n,rt();const a=t.get("x");a&&(w.value=parseFloat(a),g.value="XMR");const r=t.get("d");r&&(D.value=r);const c=t.get("t");if(c&&parseInt(c)>0){f=parseInt(c);const l=M.querySelector('.badge[data-days="'+f+'"]');l?l.classList.add("active"):F.value=f}const d=t.get("c");return d&&(_=d,setTimeout(function(){$t(d)},200)),setTimeout(mt,100),!0}function ht(e,t,n){var a="";if(e){a+='
'+e.toFixed(8)+" XMR
";var r=parseFloat(w.value),c=g.value;c!=="XMR"&&r&&(a+='
\u2248 '+r.toFixed(2)+" "+c+"
")}t&&(a+='
'+t.replace(/"),ft.innerHTML=a}function gt(e,t){var n=[];e&&n.push(e.toFixed(4)+" XMR"),t&&n.push(t),n.length&&(document.title=n.join(" \u2014 ")+" | xmrpay.link")}function At(){if(T&&clearInterval(T),S.textContent="",S.className="countdown",!f||f<=0)return;const e=Date.now()+f*864e5;S.classList.add("active");function t(){const n=e-Date.now();if(n<=0){clearInterval(T),S.textContent=I18n.t("countdown_expired"),S.className="countdown expired";return}const a=Math.floor(n/864e5),r=Math.floor(n%864e5/36e5),c=Math.floor(n%36e5/6e4);a>0?S.textContent=I18n.t("countdown_remaining_days").replace("{d}",a).replace("{h}",r):S.textContent=I18n.t("countdown_remaining_hours").replace("{h}",yt(r)).replace("{m}",yt(c))}tt=t,t(),T=setInterval(t,6e4)}function yt(e){return e<10?"0"+e:""+e}function Bt(){const e=v.querySelector("canvas");if(!e)return;const t=document.createElement("a");t.download="xmrpay-qr.png",t.href=e.toDataURL("image/png"),t.click()}function Ct(e){navigator.clipboard.writeText(e).then(()=>{jt(I18n.t("toast_copied"))})}function jt(e){at.textContent=e,at.classList.add("show"),setTimeout(()=>at.classList.remove("show"),2e3)}function zt(e){try{localStorage.setItem("xmrpay_addr",e)}catch{}}function Ot(){try{const e=localStorage.getItem("xmrpay_addr");e&&(u.value=e,rt())}catch{}}async function xt(){if(!(y&&Date.now()-dt<6e4))try{const e=await fetch(It);if(!e.ok)throw new Error("HTTP "+e.status);y=(await e.json()).monero,dt=Date.now(),j=!1,G()}catch(e){console.warn("Kurse konnten nicht geladen werden:",e),j=!0,G(),setTimeout(xt,1e4)}}function Wt(){"serviceWorker"in navigator&&navigator.serviceWorker.register("sw.js").catch(function(){})}function Gt(){return new Promise(function(e,t){if(window.jspdf){e();return}var n=document.createElement("script");n.src="lib/jspdf.min.js",n.onload=function(){Ht=!0,e()},n.onerror=function(){t(new Error("Failed to load jsPDF"))},document.head.appendChild(n)})}async function Kt(){await Gt();var e=window.jspdf.jsPDF,t=new e({orientation:"portrait",unit:"mm",format:"a4"}),n=u.value.trim(),a=ot(),r=D.value.trim(),c=parseFloat(w.value),d=g.value,l=t.internal.pageSize.getWidth(),s=20,x=l-s*2,o=s;t.setFillColor(242,104,33),t.rect(0,0,l,8,"F"),o=22,t.setFont("helvetica","bold"),t.setFontSize(22),t.setTextColor(242,104,33),t.text(I18n.t("pdf_title"),s,o),t.setFont("helvetica","normal"),t.setFontSize(10),t.setTextColor(120,120,120);var st=new Date().toLocaleDateString(I18n.getLang()==="de"?"de-CH":"en-US",{year:"numeric",month:"long",day:"numeric"});t.text(I18n.t("pdf_date")+": "+st,l-s,o,{align:"right"}),o+=6,t.setDrawColor(220,220,220),t.setLineWidth(.3),t.line(s,o,l-s,o);var Y=v.querySelector("canvas"),L=50,b=l-s-L,A=o+6;if(Y){var J=Y.toDataURL("image/png");t.addImage(J,"PNG",b,A,L,L),t.setFontSize(7),t.setTextColor(150,150,150),t.text(I18n.t("pdf_scan_qr"),b+L/2,A+L+4,{align:"center"})}var P=s,V=b-s-10;o+=14;function k(Zt,te){t.setFont("helvetica","normal"),t.setFontSize(9),t.setTextColor(150,150,150),t.text(Zt,P,o),o+=5,t.setFont("helvetica","bold"),t.setFontSize(11),t.setTextColor(40,40,40);var St=t.splitTextToSize(te,V);t.text(St,P,o),o+=St.length*5+4}if(a){var m=a.toFixed(8)+" XMR";d!=="XMR"&&c&&(m+=" (~ "+c.toFixed(2)+" "+d+")"),k(I18n.t("pdf_amount"),m)}if(r&&k(I18n.t("pdf_desc"),r),f>0){var I=new Date(Date.now()+f*864e5),$=I.toLocaleDateString(I18n.getLang()==="de"?"de-CH":"en-US",{year:"numeric",month:"long",day:"numeric"});k(I18n.t("pdf_deadline"),$+" ("+I18n.t("pdf_deadline_days").replace("{d}",f)+")")}o=Math.max(o,A+L+12),t.setFont("helvetica","normal"),t.setFontSize(9),t.setTextColor(150,150,150),t.text(I18n.t("pdf_address"),s,o),o+=5,t.setFillColor(245,245,245),t.roundedRect(s,o-3.5,x,10,2,2,"F"),t.setFont("courier","normal"),t.setFontSize(8),t.setTextColor(60,60,60),t.text(n,s+3,o+2.5),o+=14;var Q=nt.textContent;if(Q){t.setFillColor(245,245,245),t.roundedRect(s,o-3.5,x,10,2,2,"F"),t.setFont("courier","normal"),t.setFontSize(6.5),t.setTextColor(100,100,100);var Z=t.splitTextToSize(Q,x-6);t.text(Z,s+3,o+2),o+=Z.length*3+10}if(C){o+=4;var B="";if(C.verified_at){var ct=new Date(C.verified_at*1e3);B=ct.toLocaleDateString(I18n.getLang()==="de"?"de-CH":"en-US",{year:"numeric",month:"long",day:"numeric"})}var lt=C.amount.toFixed(6)+" XMR \u2014 TX "+C.tx_hash.substring(0,8)+"..."+(B?" \u2014 "+B:"");t.setFillColor(76,175,80),t.roundedRect(s,o-4,x,16,2,2,"F"),t.setFont("helvetica","bold"),t.setFontSize(12),t.setTextColor(255,255,255),t.text(I18n.t("status_paid").toUpperCase(),s+x/2,o+1,{align:"center"}),t.setFont("helvetica","normal"),t.setFontSize(7.5),t.text(lt,s+x/2,o+7,{align:"center"}),o+=22}t.setDrawColor(220,220,220),t.setLineWidth(.3);var H=t.internal.pageSize.getHeight()-15;t.line(s,H,l-s,H),t.setFont("helvetica","normal"),t.setFontSize(7),t.setTextColor(180,180,180),t.text(I18n.t("pdf_footer"),l/2,H+5,{align:"center"});var X=U.value;X&&t.text(X,l/2,H+9,{align:"center"});var wt="xmrpay-"+(r?r.replace(/[^a-zA-Z0-9]/g,"-").substring(0,30):"invoice")+".pdf";t.save(wt)}function Yt(){if(q.classList.contains("open")){q.classList.remove("open");return}if(!vt&&!window.XmrCrypto){Jt().then(function(){vt=!0,q.classList.add("open"),E.focus()});return}q.classList.add("open"),E.focus()}function Jt(){return new Promise(function(e,t){if(window.XmrCrypto){e();return}const n=document.createElement("script");n.src="lib/xmr-crypto.bundle.js",n.onload=e,n.onerror=function(){t(new Error("Failed to load crypto module"))},document.head.appendChild(n)})}function K(e){return/^[0-9a-fA-F]{64}$/.test(e)}function Lt(){const e=E.value.trim(),t=O.value.trim();R.disabled=!(K(e)&&K(t))}async function Vt(){const e=E.value.trim(),t=O.value.trim(),n=u.value.trim();if(!(!K(e)||!K(t)||!N(n))){R.disabled=!0,p.className="proof-result active",p.textContent=I18n.t("proof_verifying");try{var a=await fetch("/api/node.php",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({method:"gettransactions",params:{txs_hashes:[e],decode_as_json:!0}})}),r=await a.json(),c=r.txs||[];if(c.length===0){p.className="proof-result active error",p.textContent=I18n.t("proof_tx_not_found"),R.disabled=!1;return}for(var d=c[0],l=JSON.parse(d.as_json),s=XmrCrypto.getKeysFromAddress(n),x=s.publicViewKey,o=s.publicSpendKey,st=XmrCrypto.bytesToScalar(XmrCrypto.hexToBytes(t)),Y=XmrCrypto.Point.fromHex(x),L=Y.multiply(st).multiply(8n),b=L.toBytes(),A=XmrCrypto.Point.fromHex(o),J=l.vout||[],P=l.rct_signatures&&l.rct_signatures.ecdhInfo||[],V=0n,k=!1,m=0;mSource · Onion',d={en:{subtitle:"Monero payment request in seconds",label_addr:"XMR Address",placeholder_addr:"8...",label_amount:"Amount",label_desc:"Description (optional)",placeholder_desc:"e.g. Invoice #42, freelance work...",label_timer:"Payment deadline (optional)",days:"days",placeholder_timer_custom:"Days",btn_generate:"Create payment request",btn_open_wallet:"Open in wallet",btn_copy_addr:"Copy address",btn_download_pdf:"PDF Invoice",pdf_title:"Payment Request",pdf_address:"XMR Address",pdf_amount:"Amount",pdf_desc:"Description",pdf_deadline:"Payment deadline",pdf_deadline_days:"{d} days",pdf_date:"Date",pdf_scan_qr:"Scan QR code to pay",pdf_footer:"Created with xmrpay.link",qr_hint:"Click QR to save",footer:t,aria_currency:"Currency",label_share_link:"Shareable link",btn_new_request:"New payment request",toast_copied:"Copied!",countdown_expired:"Payment deadline expired",countdown_remaining_days:"Deadline: {d} days, {h} hrs",countdown_remaining_hours:"Deadline: {h}:{m} hrs",rates_offline:"Rates unavailable \u2014 XMR amount only",btn_prove_payment:"Prove payment",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 hex characters...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 hex characters...",btn_verify_proof:"Verify payment",proof_verifying:"Verifying...",proof_verified:"Payment confirmed: {amount} XMR",proof_no_match:"No matching output \u2014 TX key or address mismatch",proof_tx_not_found:"Transaction not found",proof_error:"Verification error",status_paid:"Paid"},de:{subtitle:"Monero-Zahlungsanforderung in Sekunden",label_addr:"XMR-Adresse",placeholder_addr:"8...",label_amount:"Betrag",label_desc:"Beschreibung (optional)",placeholder_desc:"z.B. Rechnung #42, Freelance-Arbeit...",label_timer:"Zahlungsfrist (optional)",days:"Tage",placeholder_timer_custom:"Tage",btn_generate:"Zahlungsanforderung erstellen",btn_open_wallet:"In Wallet \xF6ffnen",btn_copy_addr:"Adresse kopieren",btn_download_pdf:"PDF Rechnung",pdf_title:"Zahlungsanforderung",pdf_address:"XMR-Adresse",pdf_amount:"Betrag",pdf_desc:"Beschreibung",pdf_deadline:"Zahlungsfrist",pdf_deadline_days:"{d} Tage",pdf_date:"Datum",pdf_scan_qr:"QR-Code scannen zum Bezahlen",pdf_footer:"Erstellt mit xmrpay.link",qr_hint:"Klick auf QR zum Speichern",footer:t,aria_currency:"W\xE4hrung",label_share_link:"Teilbarer Link",btn_new_request:"Neue Zahlungsanforderung",toast_copied:"Kopiert!",countdown_expired:"Zahlungsfrist abgelaufen",countdown_remaining_days:"Zahlungsfrist: {d} Tage, {h} Std.",countdown_remaining_hours:"Zahlungsfrist: {h}:{m} Std.",rates_offline:"Kurse nicht verf\xFCgbar \u2014 nur XMR-Betrag m\xF6glich",btn_prove_payment:"Zahlung nachweisen",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 Hex-Zeichen...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 Hex-Zeichen...",btn_verify_proof:"Zahlung verifizieren",proof_verifying:"Verifiziere...",proof_verified:"Zahlung best\xE4tigt: {amount} XMR",proof_no_match:"Kein passender Output \u2014 TX Key oder Adresse stimmt nicht",proof_tx_not_found:"Transaktion nicht gefunden",proof_error:"Fehler bei der Verifizierung",status_paid:"Bezahlt"},fr:{subtitle:"Demande de paiement Monero en quelques secondes",label_addr:"Adresse XMR",placeholder_addr:"8...",label_amount:"Montant",label_desc:"Description (facultatif)",placeholder_desc:"ex. Facture #42, travail freelance...",label_timer:"Date limite de paiement (facultatif)",days:"jours",placeholder_timer_custom:"Jours",btn_generate:"Cr\xE9er une demande de paiement",btn_open_wallet:"Ouvrir dans le wallet",btn_copy_addr:"Copier l'adresse",btn_download_pdf:"Facture PDF",pdf_title:"Demande de paiement",pdf_address:"Adresse XMR",pdf_amount:"Montant",pdf_desc:"Description",pdf_deadline:"Date limite de paiement",pdf_deadline_days:"{d} jours",pdf_date:"Date",pdf_scan_qr:"Scanner le QR code pour payer",pdf_footer:"Cr\xE9\xE9 avec xmrpay.link",qr_hint:"Cliquez sur le QR pour enregistrer",footer:t,aria_currency:"Devise",label_share_link:"Lien partageable",btn_new_request:"Nouvelle demande de paiement",toast_copied:"Copi\xE9 !",countdown_expired:"D\xE9lai de paiement expir\xE9",countdown_remaining_days:"D\xE9lai : {d} jours, {h} h",countdown_remaining_hours:"D\xE9lai : {h}:{m} h",rates_offline:"Taux indisponibles \u2014 montant en XMR uniquement",btn_prove_payment:"Prouver le paiement",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 caract\xE8res hexad\xE9cimaux...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 caract\xE8res hexad\xE9cimaux...",btn_verify_proof:"V\xE9rifier le paiement",proof_verifying:"V\xE9rification...",proof_verified:"Paiement confirm\xE9 : {amount} XMR",proof_no_match:"Aucun output correspondant \u2014 TX Key ou adresse incorrecte",proof_tx_not_found:"Transaction introuvable",proof_error:"Erreur de v\xE9rification",status_paid:"Pay\xE9"},it:{subtitle:"Richiesta di pagamento Monero in pochi secondi",label_addr:"Indirizzo XMR",placeholder_addr:"8...",label_amount:"Importo",label_desc:"Descrizione (facoltativo)",placeholder_desc:"es. Fattura #42, lavoro freelance...",label_timer:"Scadenza pagamento (facoltativo)",days:"giorni",placeholder_timer_custom:"Giorni",btn_generate:"Crea richiesta di pagamento",btn_open_wallet:"Apri nel wallet",btn_copy_addr:"Copia indirizzo",btn_download_pdf:"Fattura PDF",pdf_title:"Richiesta di pagamento",pdf_address:"Indirizzo XMR",pdf_amount:"Importo",pdf_desc:"Descrizione",pdf_deadline:"Scadenza pagamento",pdf_deadline_days:"{d} giorni",pdf_date:"Data",pdf_scan_qr:"Scansiona il QR per pagare",pdf_footer:"Creato con xmrpay.link",qr_hint:"Clicca sul QR per salvare",footer:t,aria_currency:"Valuta",label_share_link:"Link condivisibile",btn_new_request:"Nuova richiesta di pagamento",toast_copied:"Copiato!",countdown_expired:"Scadenza pagamento superata",countdown_remaining_days:"Scadenza: {d} giorni, {h} ore",countdown_remaining_hours:"Scadenza: {h}:{m} ore",rates_offline:"Tassi non disponibili \u2014 solo importo in XMR",btn_prove_payment:"Dimostra pagamento",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 caratteri esadecimali...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 caratteri esadecimali...",btn_verify_proof:"Verifica pagamento",proof_verifying:"Verifica in corso...",proof_verified:"Pagamento confermato: {amount} XMR",proof_no_match:"Nessun output corrispondente \u2014 TX Key o indirizzo errato",proof_tx_not_found:"Transazione non trovata",proof_error:"Errore di verifica",status_paid:"Pagato"},es:{subtitle:"Solicitud de pago Monero en segundos",label_addr:"Direcci\xF3n XMR",placeholder_addr:"8...",label_amount:"Monto",label_desc:"Descripci\xF3n (opcional)",placeholder_desc:"ej. Factura #42, trabajo freelance...",label_timer:"Plazo de pago (opcional)",days:"d\xEDas",placeholder_timer_custom:"D\xEDas",btn_generate:"Crear solicitud de pago",btn_open_wallet:"Abrir en wallet",btn_copy_addr:"Copiar direcci\xF3n",btn_download_pdf:"Factura PDF",pdf_title:"Solicitud de pago",pdf_address:"Direcci\xF3n XMR",pdf_amount:"Monto",pdf_desc:"Descripci\xF3n",pdf_deadline:"Plazo de pago",pdf_deadline_days:"{d} d\xEDas",pdf_date:"Fecha",pdf_scan_qr:"Escanear QR para pagar",pdf_footer:"Creado con xmrpay.link",qr_hint:"Clic en QR para guardar",footer:t,aria_currency:"Moneda",label_share_link:"Enlace compartible",btn_new_request:"Nueva solicitud de pago",toast_copied:"\xA1Copiado!",countdown_expired:"Plazo de pago vencido",countdown_remaining_days:"Plazo: {d} d\xEDas, {h} h",countdown_remaining_hours:"Plazo: {h}:{m} h",rates_offline:"Tasas no disponibles \u2014 solo monto en XMR",btn_prove_payment:"Demostrar pago",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 caracteres hexadecimales...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 caracteres hexadecimales...",btn_verify_proof:"Verificar pago",proof_verifying:"Verificando...",proof_verified:"Pago confirmado: {amount} XMR",proof_no_match:"Ning\xFAn output coincidente \u2014 TX Key o direcci\xF3n incorrecta",proof_tx_not_found:"Transacci\xF3n no encontrada",proof_error:"Error de verificaci\xF3n",status_paid:"Pagado"},pt:{subtitle:"Pedido de pagamento Monero em segundos",label_addr:"Endere\xE7o XMR",placeholder_addr:"8...",label_amount:"Valor",label_desc:"Descri\xE7\xE3o (opcional)",placeholder_desc:"ex. Fatura #42, trabalho freelance...",label_timer:"Prazo de pagamento (opcional)",days:"dias",placeholder_timer_custom:"Dias",btn_generate:"Criar pedido de pagamento",btn_open_wallet:"Abrir na wallet",btn_copy_addr:"Copiar endere\xE7o",btn_download_pdf:"Fatura PDF",pdf_title:"Pedido de pagamento",pdf_address:"Endere\xE7o XMR",pdf_amount:"Valor",pdf_desc:"Descri\xE7\xE3o",pdf_deadline:"Prazo de pagamento",pdf_deadline_days:"{d} dias",pdf_date:"Data",pdf_scan_qr:"Digitalizar QR para pagar",pdf_footer:"Criado com xmrpay.link",qr_hint:"Clique no QR para guardar",footer:t,aria_currency:"Moeda",label_share_link:"Link partilh\xE1vel",btn_new_request:"Novo pedido de pagamento",toast_copied:"Copiado!",countdown_expired:"Prazo de pagamento expirado",countdown_remaining_days:"Prazo: {d} dias, {h} h",countdown_remaining_hours:"Prazo: {h}:{m} h",rates_offline:"Taxas indispon\xEDveis \u2014 apenas valor em XMR",btn_prove_payment:"Comprovar pagamento",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 caracteres hexadecimais...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 caracteres hexadecimais...",btn_verify_proof:"Verificar pagamento",proof_verifying:"A verificar...",proof_verified:"Pagamento confirmado: {amount} XMR",proof_no_match:"Nenhum output correspondente \u2014 TX Key ou endere\xE7o incorreto",proof_tx_not_found:"Transa\xE7\xE3o n\xE3o encontrada",proof_error:"Erro de verifica\xE7\xE3o",status_paid:"Pago"},ru:{subtitle:"\u0417\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u043E\u043F\u043B\u0430\u0442\u0443 Monero \u0437\u0430 \u0441\u0435\u043A\u0443\u043D\u0434\u044B",label_addr:"\u0410\u0434\u0440\u0435\u0441 XMR",placeholder_addr:"8...",label_amount:"\u0421\u0443\u043C\u043C\u0430",label_desc:"\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 (\u043D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E)",placeholder_desc:"\u043D\u0430\u043F\u0440. \u0421\u0447\u0451\u0442 #42, \u0444\u0440\u0438\u043B\u0430\u043D\u0441...",label_timer:"\u0421\u0440\u043E\u043A \u043E\u043F\u043B\u0430\u0442\u044B (\u043D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E)",days:"\u0434\u043D\u0435\u0439",placeholder_timer_custom:"\u0414\u043D\u0435\u0439",btn_generate:"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0437\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u043E\u043F\u043B\u0430\u0442\u0443",btn_open_wallet:"\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0432 \u043A\u043E\u0448\u0435\u043B\u044C\u043A\u0435",btn_copy_addr:"\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0430\u0434\u0440\u0435\u0441",btn_download_pdf:"PDF \u0441\u0447\u0451\u0442",pdf_title:"\u0417\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u043E\u043F\u043B\u0430\u0442\u0443",pdf_address:"\u0410\u0434\u0440\u0435\u0441 XMR",pdf_amount:"\u0421\u0443\u043C\u043C\u0430",pdf_desc:"\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435",pdf_deadline:"\u0421\u0440\u043E\u043A \u043E\u043F\u043B\u0430\u0442\u044B",pdf_deadline_days:"{d} \u0434\u043D\u0435\u0439",pdf_date:"\u0414\u0430\u0442\u0430",pdf_scan_qr:"\u0421\u043A\u0430\u043D\u0438\u0440\u0443\u0439\u0442\u0435 QR \u0434\u043B\u044F \u043E\u043F\u043B\u0430\u0442\u044B",pdf_footer:"\u0421\u043E\u0437\u0434\u0430\u043D\u043E \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E xmrpay.link",qr_hint:"\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u043D\u0430 QR \u0434\u043B\u044F \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u044F",footer:t,aria_currency:"\u0412\u0430\u043B\u044E\u0442\u0430",label_share_link:"\u0421\u0441\u044B\u043B\u043A\u0430 \u0434\u043B\u044F \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438",btn_new_request:"\u041D\u043E\u0432\u044B\u0439 \u0437\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u043E\u043F\u043B\u0430\u0442\u0443",toast_copied:"\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u043D\u043E!",countdown_expired:"\u0421\u0440\u043E\u043A \u043E\u043F\u043B\u0430\u0442\u044B \u0438\u0441\u0442\u0451\u043A",countdown_remaining_days:"\u0421\u0440\u043E\u043A: {d} \u0434\u043D\u0435\u0439, {h} \u0447",countdown_remaining_hours:"\u0421\u0440\u043E\u043A: {h}:{m} \u0447",rates_offline:"\u041A\u0443\u0440\u0441\u044B \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0441\u0443\u043C\u043C\u0430 \u0432 XMR",btn_prove_payment:"\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u043E\u043F\u043B\u0430\u0442\u0443",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 \u0448\u0435\u0441\u0442\u043D\u0430\u0434\u0446\u0430\u0442\u0435\u0440\u0438\u0447\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u0430...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 \u0448\u0435\u0441\u0442\u043D\u0430\u0434\u0446\u0430\u0442\u0435\u0440\u0438\u0447\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u0430...",btn_verify_proof:"\u041F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u043E\u043F\u043B\u0430\u0442\u0443",proof_verifying:"\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430...",proof_verified:"\u041E\u043F\u043B\u0430\u0442\u0430 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0430: {amount} XMR",proof_no_match:"\u0421\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0439 \u0432\u044B\u0445\u043E\u0434 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u2014 \u043D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 TX Key \u0438\u043B\u0438 \u0430\u0434\u0440\u0435\u0441",proof_tx_not_found:"\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430",proof_error:"\u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438",status_paid:"\u041E\u043F\u043B\u0430\u0447\u0435\u043D\u043E"}},i="en";function p(){var e=null;try{e=localStorage.getItem("xmrpay_lang")}catch{}if(e&&d[e])return e;for(var a=navigator.languages||[navigator.language||"en"],n=0;nSource · Onion',d={en:{subtitle:"Monero payment request in seconds",label_addr:"XMR Address",placeholder_addr:"8...",label_amount:"Amount",label_desc:"Description (optional)",placeholder_desc:"e.g. Invoice #42, freelance work...",label_timer:"Payment deadline (optional)",days:"days",placeholder_timer_custom:"Days",btn_generate:"Create payment request",btn_open_wallet:"Open in wallet",btn_copy_addr:"Copy address",btn_download_pdf:"PDF Invoice",pdf_title:"Payment Request",pdf_address:"XMR Address",pdf_amount:"Amount",pdf_desc:"Description",pdf_deadline:"Payment deadline",pdf_deadline_days:"{d} days",pdf_date:"Date",pdf_scan_qr:"Scan QR code to pay",pdf_footer:"Created with xmrpay.link",qr_hint:"Click QR to save",footer:r,aria_currency:"Currency",label_share_link:"Shareable link",btn_new_request:"New payment request",toast_copied:"Copied!",countdown_expired:"Payment deadline expired",countdown_remaining_days:"Deadline: {d} days, {h} hrs",countdown_remaining_hours:"Deadline: {h}:{m} hrs",rates_offline:"Rates unavailable \u2014 XMR amount only",btn_prove_payment:"Prove payment",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 hex characters...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 hex characters...",btn_verify_proof:"Verify payment",proof_verifying:"Verifying...",proof_verified:"Payment confirmed: {amount} XMR",proof_no_match:"No matching output \u2014 TX key or address mismatch",proof_tx_not_found:"Transaction not found",proof_error:"Verification error",status_paid:"Paid"},de:{subtitle:"Monero-Zahlungsanforderung in Sekunden",label_addr:"XMR-Adresse",placeholder_addr:"8...",label_amount:"Betrag",label_desc:"Beschreibung (optional)",placeholder_desc:"z.B. Rechnung #42, Freelance-Arbeit...",label_timer:"Zahlungsfrist (optional)",days:"Tage",placeholder_timer_custom:"Tage",btn_generate:"Zahlungsanforderung erstellen",btn_open_wallet:"In Wallet \xF6ffnen",btn_copy_addr:"Adresse kopieren",btn_download_pdf:"PDF Rechnung",pdf_title:"Zahlungsanforderung",pdf_address:"XMR-Adresse",pdf_amount:"Betrag",pdf_desc:"Beschreibung",pdf_deadline:"Zahlungsfrist",pdf_deadline_days:"{d} Tage",pdf_date:"Datum",pdf_scan_qr:"QR-Code scannen zum Bezahlen",pdf_footer:"Erstellt mit xmrpay.link",qr_hint:"Klick auf QR zum Speichern",footer:r,aria_currency:"W\xE4hrung",label_share_link:"Teilbarer Link",btn_new_request:"Neue Zahlungsanforderung",toast_copied:"Kopiert!",countdown_expired:"Zahlungsfrist abgelaufen",countdown_remaining_days:"Zahlungsfrist: {d} Tage, {h} Std.",countdown_remaining_hours:"Zahlungsfrist: {h}:{m} Std.",rates_offline:"Kurse nicht verf\xFCgbar \u2014 nur XMR-Betrag m\xF6glich",btn_prove_payment:"Zahlung nachweisen",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 Hex-Zeichen...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 Hex-Zeichen...",btn_verify_proof:"Zahlung verifizieren",proof_verifying:"Verifiziere...",proof_verified:"Zahlung best\xE4tigt: {amount} XMR",proof_no_match:"Kein passender Output \u2014 TX Key oder Adresse stimmt nicht",proof_tx_not_found:"Transaktion nicht gefunden",proof_error:"Fehler bei der Verifizierung",status_paid:"Bezahlt"},fr:{subtitle:"Demande de paiement Monero en quelques secondes",label_addr:"Adresse XMR",placeholder_addr:"8...",label_amount:"Montant",label_desc:"Description (facultatif)",placeholder_desc:"ex. Facture #42, travail freelance...",label_timer:"Date limite de paiement (facultatif)",days:"jours",placeholder_timer_custom:"Jours",btn_generate:"Cr\xE9er une demande de paiement",btn_open_wallet:"Ouvrir dans le wallet",btn_copy_addr:"Copier l'adresse",btn_download_pdf:"Facture PDF",pdf_title:"Demande de paiement",pdf_address:"Adresse XMR",pdf_amount:"Montant",pdf_desc:"Description",pdf_deadline:"Date limite de paiement",pdf_deadline_days:"{d} jours",pdf_date:"Date",pdf_scan_qr:"Scanner le QR code pour payer",pdf_footer:"Cr\xE9\xE9 avec xmrpay.link",qr_hint:"Cliquez sur le QR pour enregistrer",footer:r,aria_currency:"Devise",label_share_link:"Lien partageable",btn_new_request:"Nouvelle demande de paiement",toast_copied:"Copi\xE9 !",countdown_expired:"D\xE9lai de paiement expir\xE9",countdown_remaining_days:"D\xE9lai : {d} jours, {h} h",countdown_remaining_hours:"D\xE9lai : {h}:{m} h",rates_offline:"Taux indisponibles \u2014 montant en XMR uniquement",btn_prove_payment:"Prouver le paiement",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 caract\xE8res hexad\xE9cimaux...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 caract\xE8res hexad\xE9cimaux...",btn_verify_proof:"V\xE9rifier le paiement",proof_verifying:"V\xE9rification...",proof_verified:"Paiement confirm\xE9 : {amount} XMR",proof_no_match:"Aucun output correspondant \u2014 TX Key ou adresse incorrecte",proof_tx_not_found:"Transaction introuvable",proof_error:"Erreur de v\xE9rification",status_paid:"Pay\xE9"},it:{subtitle:"Richiesta di pagamento Monero in pochi secondi",label_addr:"Indirizzo XMR",placeholder_addr:"8...",label_amount:"Importo",label_desc:"Descrizione (facoltativo)",placeholder_desc:"es. Fattura #42, lavoro freelance...",label_timer:"Scadenza pagamento (facoltativo)",days:"giorni",placeholder_timer_custom:"Giorni",btn_generate:"Crea richiesta di pagamento",btn_open_wallet:"Apri nel wallet",btn_copy_addr:"Copia indirizzo",btn_download_pdf:"Fattura PDF",pdf_title:"Richiesta di pagamento",pdf_address:"Indirizzo XMR",pdf_amount:"Importo",pdf_desc:"Descrizione",pdf_deadline:"Scadenza pagamento",pdf_deadline_days:"{d} giorni",pdf_date:"Data",pdf_scan_qr:"Scansiona il QR per pagare",pdf_footer:"Creato con xmrpay.link",qr_hint:"Clicca sul QR per salvare",footer:r,aria_currency:"Valuta",label_share_link:"Link condivisibile",btn_new_request:"Nuova richiesta di pagamento",toast_copied:"Copiato!",countdown_expired:"Scadenza pagamento superata",countdown_remaining_days:"Scadenza: {d} giorni, {h} ore",countdown_remaining_hours:"Scadenza: {h}:{m} ore",rates_offline:"Tassi non disponibili \u2014 solo importo in XMR",btn_prove_payment:"Dimostra pagamento",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 caratteri esadecimali...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 caratteri esadecimali...",btn_verify_proof:"Verifica pagamento",proof_verifying:"Verifica in corso...",proof_verified:"Pagamento confermato: {amount} XMR",proof_no_match:"Nessun output corrispondente \u2014 TX Key o indirizzo errato",proof_tx_not_found:"Transazione non trovata",proof_error:"Errore di verifica",status_paid:"Pagato"},es:{subtitle:"Solicitud de pago Monero en segundos",label_addr:"Direcci\xF3n XMR",placeholder_addr:"8...",label_amount:"Monto",label_desc:"Descripci\xF3n (opcional)",placeholder_desc:"ej. Factura #42, trabajo freelance...",label_timer:"Plazo de pago (opcional)",days:"d\xEDas",placeholder_timer_custom:"D\xEDas",btn_generate:"Crear solicitud de pago",btn_open_wallet:"Abrir en wallet",btn_copy_addr:"Copiar direcci\xF3n",btn_download_pdf:"Factura PDF",pdf_title:"Solicitud de pago",pdf_address:"Direcci\xF3n XMR",pdf_amount:"Monto",pdf_desc:"Descripci\xF3n",pdf_deadline:"Plazo de pago",pdf_deadline_days:"{d} d\xEDas",pdf_date:"Fecha",pdf_scan_qr:"Escanear QR para pagar",pdf_footer:"Creado con xmrpay.link",qr_hint:"Clic en QR para guardar",footer:r,aria_currency:"Moneda",label_share_link:"Enlace compartible",btn_new_request:"Nueva solicitud de pago",toast_copied:"\xA1Copiado!",countdown_expired:"Plazo de pago vencido",countdown_remaining_days:"Plazo: {d} d\xEDas, {h} h",countdown_remaining_hours:"Plazo: {h}:{m} h",rates_offline:"Tasas no disponibles \u2014 solo monto en XMR",btn_prove_payment:"Demostrar pago",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 caracteres hexadecimales...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 caracteres hexadecimales...",btn_verify_proof:"Verificar pago",proof_verifying:"Verificando...",proof_verified:"Pago confirmado: {amount} XMR",proof_no_match:"Ning\xFAn output coincidente \u2014 TX Key o direcci\xF3n incorrecta",proof_tx_not_found:"Transacci\xF3n no encontrada",proof_error:"Error de verificaci\xF3n",status_paid:"Pagado"},pt:{subtitle:"Pedido de pagamento Monero em segundos",label_addr:"Endere\xE7o XMR",placeholder_addr:"8...",label_amount:"Valor",label_desc:"Descri\xE7\xE3o (opcional)",placeholder_desc:"ex. Fatura #42, trabalho freelance...",label_timer:"Prazo de pagamento (opcional)",days:"dias",placeholder_timer_custom:"Dias",btn_generate:"Criar pedido de pagamento",btn_open_wallet:"Abrir na wallet",btn_copy_addr:"Copiar endere\xE7o",btn_download_pdf:"Fatura PDF",pdf_title:"Pedido de pagamento",pdf_address:"Endere\xE7o XMR",pdf_amount:"Valor",pdf_desc:"Descri\xE7\xE3o",pdf_deadline:"Prazo de pagamento",pdf_deadline_days:"{d} dias",pdf_date:"Data",pdf_scan_qr:"Digitalizar QR para pagar",pdf_footer:"Criado com xmrpay.link",qr_hint:"Clique no QR para guardar",footer:r,aria_currency:"Moeda",label_share_link:"Link partilh\xE1vel",btn_new_request:"Novo pedido de pagamento",toast_copied:"Copiado!",countdown_expired:"Prazo de pagamento expirado",countdown_remaining_days:"Prazo: {d} dias, {h} h",countdown_remaining_hours:"Prazo: {h}:{m} h",rates_offline:"Taxas indispon\xEDveis \u2014 apenas valor em XMR",btn_prove_payment:"Comprovar pagamento",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 caracteres hexadecimais...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 caracteres hexadecimais...",btn_verify_proof:"Verificar pagamento",proof_verifying:"A verificar...",proof_verified:"Pagamento confirmado: {amount} XMR",proof_no_match:"Nenhum output correspondente \u2014 TX Key ou endere\xE7o incorreto",proof_tx_not_found:"Transa\xE7\xE3o n\xE3o encontrada",proof_error:"Erro de verifica\xE7\xE3o",status_paid:"Pago"},ru:{subtitle:"\u0417\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u043E\u043F\u043B\u0430\u0442\u0443 Monero \u0437\u0430 \u0441\u0435\u043A\u0443\u043D\u0434\u044B",label_addr:"\u0410\u0434\u0440\u0435\u0441 XMR",placeholder_addr:"8...",label_amount:"\u0421\u0443\u043C\u043C\u0430",label_desc:"\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 (\u043D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E)",placeholder_desc:"\u043D\u0430\u043F\u0440. \u0421\u0447\u0451\u0442 #42, \u0444\u0440\u0438\u043B\u0430\u043D\u0441...",label_timer:"\u0421\u0440\u043E\u043A \u043E\u043F\u043B\u0430\u0442\u044B (\u043D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E)",days:"\u0434\u043D\u0435\u0439",placeholder_timer_custom:"\u0414\u043D\u0435\u0439",btn_generate:"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0437\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u043E\u043F\u043B\u0430\u0442\u0443",btn_open_wallet:"\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0432 \u043A\u043E\u0448\u0435\u043B\u044C\u043A\u0435",btn_copy_addr:"\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0430\u0434\u0440\u0435\u0441",btn_download_pdf:"PDF \u0441\u0447\u0451\u0442",pdf_title:"\u0417\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u043E\u043F\u043B\u0430\u0442\u0443",pdf_address:"\u0410\u0434\u0440\u0435\u0441 XMR",pdf_amount:"\u0421\u0443\u043C\u043C\u0430",pdf_desc:"\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435",pdf_deadline:"\u0421\u0440\u043E\u043A \u043E\u043F\u043B\u0430\u0442\u044B",pdf_deadline_days:"{d} \u0434\u043D\u0435\u0439",pdf_date:"\u0414\u0430\u0442\u0430",pdf_scan_qr:"\u0421\u043A\u0430\u043D\u0438\u0440\u0443\u0439\u0442\u0435 QR \u0434\u043B\u044F \u043E\u043F\u043B\u0430\u0442\u044B",pdf_footer:"\u0421\u043E\u0437\u0434\u0430\u043D\u043E \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E xmrpay.link",qr_hint:"\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u043D\u0430 QR \u0434\u043B\u044F \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u044F",footer:r,aria_currency:"\u0412\u0430\u043B\u044E\u0442\u0430",label_share_link:"\u0421\u0441\u044B\u043B\u043A\u0430 \u0434\u043B\u044F \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438",btn_new_request:"\u041D\u043E\u0432\u044B\u0439 \u0437\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u043E\u043F\u043B\u0430\u0442\u0443",toast_copied:"\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u043D\u043E!",countdown_expired:"\u0421\u0440\u043E\u043A \u043E\u043F\u043B\u0430\u0442\u044B \u0438\u0441\u0442\u0451\u043A",countdown_remaining_days:"\u0421\u0440\u043E\u043A: {d} \u0434\u043D\u0435\u0439, {h} \u0447",countdown_remaining_hours:"\u0421\u0440\u043E\u043A: {h}:{m} \u0447",rates_offline:"\u041A\u0443\u0440\u0441\u044B \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0441\u0443\u043C\u043C\u0430 \u0432 XMR",btn_prove_payment:"\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u043E\u043F\u043B\u0430\u0442\u0443",label_tx_hash:"Transaction ID (TX Hash)",placeholder_tx_hash:"64 \u0448\u0435\u0441\u0442\u043D\u0430\u0434\u0446\u0430\u0442\u0435\u0440\u0438\u0447\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u0430...",label_tx_key:"Transaction Key (TX Key)",placeholder_tx_key:"64 \u0448\u0435\u0441\u0442\u043D\u0430\u0434\u0446\u0430\u0442\u0435\u0440\u0438\u0447\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u0430...",btn_verify_proof:"\u041F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u043E\u043F\u043B\u0430\u0442\u0443",proof_verifying:"\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430...",proof_verified:"\u041E\u043F\u043B\u0430\u0442\u0430 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0430: {amount} XMR",proof_no_match:"\u0421\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0439 \u0432\u044B\u0445\u043E\u0434 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u2014 \u043D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 TX Key \u0438\u043B\u0438 \u0430\u0434\u0440\u0435\u0441",proof_tx_not_found:"\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430",proof_error:"\u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438",status_paid:"\u041E\u043F\u043B\u0430\u0447\u0435\u043D\u043E"}},t="en";function p(){var e=null;try{e=localStorage.getItem("xmrpay_lang")}catch{}if(e&&d[e])return e;for(var a=navigator.languages||[navigator.language||"en"],n=0;n
@@ -112,7 +116,6 @@ - English