66 lines
3.2 KiB
TypeScript
66 lines
3.2 KiB
TypeScript
import { useEffect, useState } from 'react';
|
||
import QRCode from 'qrcode';
|
||
import { Check, Copy } from 'lucide-react';
|
||
import { useTranslation } from '@/contexts/language';
|
||
|
||
// BIP-353 payment name → BIP-321 URI (silent payment `sp` + BOLT 12 `lno`).
|
||
// Resolved 2026-10-05 from skatespots.user._bitcoin-payment.silentpayments.net.
|
||
// Update if the name is re-pointed (or a Cashu `creq` is added).
|
||
const SILENT_NAME = 'skatespots@silentpayments.net';
|
||
const SILENT_URI = 'bitcoin:?sp=sp1qq2xlxmvh5tpkjw460cfjf5ndz87fc45k0fm3glyalqxq4m436u8nyqa745dyh55pz4vchhjzam5tmlvvlp6whhkqmdk3e7xvfp4y80jhvq40lyl3&lno=lno1pgqppmsrse80qf0aara4slvcjxrvu6j2rp5ftmjy4yntlsmsutpkvkt6878s8y79jwe96rpahf567zyt0lhe26sxpsace8n9u5l359n254e639mqqgpas2cxvhc6ftcr6wrh6nv36mz53qhsfvwrxvgf8mnvq4tsg0z2plqqxvv8geddvc60pys4ja0ajvhhhka2zzfdsnmkvygu872fa0awyqvv8rrpg6k0kg8zpxh8hy3hm9pr35hfa73s92mk38xfqfgfz98v0w34c4z8un6ljxlfjcu69m3de0nqarvh8k8kqqey5kgfmvyfhrg3wltewtj8xn35aevy96dws40hygx7xpfu2k0ty8rm4mv262df8f9q3z2strn4cmh8svss';
|
||
|
||
export function SilentPaymentsCard({ className }: { className?: string }) {
|
||
const { t } = useTranslation();
|
||
const [qr, setQr] = useState<string | null>(null);
|
||
const [copied, setCopied] = useState(false);
|
||
|
||
useEffect(() => {
|
||
let active = true;
|
||
QRCode.toDataURL(SILENT_URI, { width: 200, margin: 1 })
|
||
.then((url) => { if (active) setQr(url); })
|
||
.catch(() => { if (active) setQr(null); });
|
||
return () => { active = false; };
|
||
}, []);
|
||
|
||
const copy = async () => {
|
||
try {
|
||
await navigator.clipboard.writeText(SILENT_NAME);
|
||
setCopied(true);
|
||
setTimeout(() => setCopied(false), 1500);
|
||
} catch { /* clipboard blocked */ }
|
||
};
|
||
|
||
return (
|
||
<div className={`rounded-2xl border-2 border-white/15 bg-black/60 p-6 ${className ?? ''}`}>
|
||
<div className="flex items-center gap-2.5">
|
||
<span className="flex h-9 w-9 items-center justify-center rounded-xl bg-white/5 text-lg">🕵️</span>
|
||
<div>
|
||
<h3 className="text-lg font-black uppercase leading-tight text-white">
|
||
{t('walletUi.supporters.silentTitle')}
|
||
</h3>
|
||
<p className="text-xs text-gray-400">{t('walletUi.supporters.silentDesc')}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mt-4 flex flex-col items-center gap-4 sm:flex-row sm:items-start">
|
||
{qr && (
|
||
<img src={qr} alt={SILENT_NAME} className="h-[200px] w-[200px] shrink-0 rounded-xl bg-white p-2" />
|
||
)}
|
||
<div className="min-w-0 text-center sm:text-left">
|
||
<p className="break-all font-mono text-sm text-white">{SILENT_NAME}</p>
|
||
<button
|
||
onClick={copy}
|
||
className="mt-2 inline-flex min-h-0 min-w-0 items-center gap-1.5 rounded-full border border-white/20 px-3 py-1.5 text-xs font-bold text-gray-200 transition-colors hover:bg-white/5"
|
||
>
|
||
{copied ? <Check className="h-3 w-3" /> : <Copy className="h-3 w-3" />}
|
||
{copied ? t('walletUi.supporters.silentCopied') : t('walletUi.supporters.silentCopyName')}
|
||
</button>
|
||
<p className="mt-3 text-[11px] leading-relaxed text-gray-500">
|
||
{t('walletUi.supporters.silentWallets')}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|