wallet: combine SP + on-chain into a single BIP-21 QR in the receive dialog
Mirrors CampaignWalletDonatePanel's payload format (`bitcoin:<bc1>?sp=<sp1>`) so BIP-352-aware wallets pick the `sp=` parameter and legacy wallets fall back to the on-chain address. The dialog now shows one QR and one copyable row with the full URI, the tabs and per-tab intro copy are gone, and the "Scan for payments" action lives in the wallet's overflow menu instead of inside the receive dialog.
This commit is contained in:
@@ -754,14 +754,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "استقبال البيتكوين",
|
||||
"description": "شارك عنواناً لاستقبال البيتكوين.",
|
||||
"onChain": "على السلسلة",
|
||||
"silentPayment": "دفع صامت",
|
||||
"onChainIntro": "عنوان جديد في كل مرة. انتقل إلى فهرس جديد بعد المشاركة للحفاظ على الخصوصية.",
|
||||
"addressIndex": "العنوان رقم {{index}}",
|
||||
"newAddress": "عنوان جديد",
|
||||
"silentIntro": "معرّف استقبال ثابت. شاركه مرة واحدة وأعد استخدامه إلى الأبد — يشتقّ المرسلون عنواناً فريداً على السلسلة لكل دفعة.",
|
||||
"noIndexer": "تم تعطيل المسح — لا يوجد مفهرس BIP-352 مُهيّأ. اضبط <0>bip352IndexerUrl</0> في إعدادات التطبيق لاكتشاف المدفوعات الصامتة الواردة.",
|
||||
"silentBalance": "رصيد الدفع الصامت: <0>{{amount}}</0>",
|
||||
"scanForNew": "فحص المدفوعات الجديدة",
|
||||
"scanForPayments": "فحص المدفوعات"
|
||||
},
|
||||
|
||||
@@ -1177,14 +1177,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Receive Bitcoin",
|
||||
"description": "Share an address to receive bitcoin.",
|
||||
"onChain": "On-chain",
|
||||
"silentPayment": "Silent payment",
|
||||
"onChainIntro": "Fresh address each time. Bump to a new index after sharing for privacy.",
|
||||
"addressIndex": "Address #{{index}}",
|
||||
"newAddress": "New address",
|
||||
"silentIntro": "Static receive identifier. Share once and reuse forever — senders derive a unique on-chain address per payment.",
|
||||
"noIndexer": "Scanning disabled — no BIP-352 indexer configured. Set <0>bip352IndexerUrl</0> in your app config to detect incoming silent payments.",
|
||||
"silentBalance": "Silent payment balance: <0>{{amount}}</0>",
|
||||
"scanForNew": "Scan for new payments",
|
||||
"scanForPayments": "Scan for payments"
|
||||
},
|
||||
|
||||
@@ -754,14 +754,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Recibir Bitcoin",
|
||||
"description": "Comparte una dirección para recibir bitcoin.",
|
||||
"onChain": "En cadena",
|
||||
"silentPayment": "Pago silencioso",
|
||||
"onChainIntro": "Dirección nueva cada vez. Pasa a un nuevo índice después de compartirla para preservar tu privacidad.",
|
||||
"addressIndex": "Dirección n.º {{index}}",
|
||||
"newAddress": "Nueva dirección",
|
||||
"silentIntro": "Identificador de recepción estático. Compártelo una vez y reutilízalo para siempre: los remitentes derivan una dirección única en cadena para cada pago.",
|
||||
"noIndexer": "Escaneo desactivado: no hay indexador BIP-352 configurado. Define <0>bip352IndexerUrl</0> en la configuración de tu aplicación para detectar pagos silenciosos entrantes.",
|
||||
"silentBalance": "Saldo de pago silencioso: <0>{{amount}}</0>",
|
||||
"scanForNew": "Buscar nuevos pagos",
|
||||
"scanForPayments": "Buscar pagos"
|
||||
},
|
||||
|
||||
@@ -754,14 +754,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "دریافت بیتکوین",
|
||||
"description": "برای دریافت بیتکوین، یک نشانی به اشتراک بگذارید.",
|
||||
"onChain": "روی زنجیره",
|
||||
"silentPayment": "پرداخت خاموش",
|
||||
"onChainIntro": "هر بار نشانی تازه. پس از اشتراکگذاری، برای حفظ حریم خصوصی به یک نمایه جدید بروید.",
|
||||
"addressIndex": "نشانی شمارهٔ {{index}}",
|
||||
"newAddress": "نشانی جدید",
|
||||
"silentIntro": "شناسهٔ دریافت ایستا. یکبار به اشتراک بگذارید و برای همیشه استفاده کنید — فرستندگان برای هر پرداخت یک نشانی منحصربهفرد روی زنجیره مشتق میکنند.",
|
||||
"noIndexer": "پویش غیرفعال است — هیچ ایندکسکنندهٔ BIP-352 پیکربندی نشده است. برای شناسایی پرداختهای خاموش ورودی، <0>bip352IndexerUrl</0> را در پیکربندی برنامه تنظیم کنید.",
|
||||
"silentBalance": "موجودی پرداخت خاموش: <0>{{amount}}</0>",
|
||||
"scanForNew": "پویش پرداختهای جدید",
|
||||
"scanForPayments": "پویش پرداختها"
|
||||
},
|
||||
|
||||
@@ -1177,14 +1177,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Recevoir du Bitcoin",
|
||||
"description": "Partagez une adresse pour recevoir du bitcoin.",
|
||||
"onChain": "Sur la chaîne",
|
||||
"silentPayment": "Paiement silencieux",
|
||||
"onChainIntro": "Nouvelle adresse à chaque fois. Passez à un nouvel index après partage pour la confidentialité.",
|
||||
"addressIndex": "Adresse n°{{index}}",
|
||||
"newAddress": "Nouvelle adresse",
|
||||
"silentIntro": "Identifiant de réception statique. Partagez une fois et réutilisez à vie — les expéditeurs dérivent une adresse on-chain unique par paiement.",
|
||||
"noIndexer": "Scan désactivé — aucun indexeur BIP-352 configuré. Définissez <0>bip352IndexerUrl</0> dans votre configuration d'application pour détecter les paiements silencieux entrants.",
|
||||
"silentBalance": "Solde des paiements silencieux : <0>{{amount}}</0>",
|
||||
"scanForNew": "Scanner les nouveaux paiements",
|
||||
"scanForPayments": "Scanner les paiements"
|
||||
},
|
||||
|
||||
@@ -1177,14 +1177,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Bitcoin पाएँ",
|
||||
"description": "Bitcoin पाने के लिए एक एड्रेस शेयर करें।",
|
||||
"onChain": "ऑन-चेन",
|
||||
"silentPayment": "साइलेंट पेमेंट",
|
||||
"onChainIntro": "हर बार नया एड्रेस। प्राइवेसी के लिए शेयर करने के बाद नए index पर बढ़ाएँ।",
|
||||
"addressIndex": "एड्रेस #{{index}}",
|
||||
"newAddress": "नया एड्रेस",
|
||||
"silentIntro": "स्थिर रिसीव पहचानकर्ता। एक बार शेयर करें और हमेशा के लिए दोहराते रहें — भेजने वाले हर भुगतान के लिए एक अनूठा ऑन-चेन एड्रेस derive करते हैं।",
|
||||
"noIndexer": "Scanning अक्षम है — कोई BIP-352 indexer कॉन्फ़िगर नहीं है। आने वाले साइलेंट पेमेंट का पता लगाने के लिए अपनी ऐप कॉन्फ़िग में <0>bip352IndexerUrl</0> सेट करें।",
|
||||
"silentBalance": "साइलेंट पेमेंट बैलेंस: <0>{{amount}}</0>",
|
||||
"scanForNew": "नए भुगतान के लिए scan करें",
|
||||
"scanForPayments": "भुगतान के लिए scan करें"
|
||||
},
|
||||
|
||||
@@ -1186,14 +1186,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Terima Bitcoin",
|
||||
"description": "Bagikan alamat untuk menerima bitcoin.",
|
||||
"onChain": "On-chain",
|
||||
"silentPayment": "Silent payment",
|
||||
"onChainIntro": "Alamat baru setiap saat. Naikkan ke indeks baru setelah berbagi untuk privasi.",
|
||||
"addressIndex": "Alamat #{{index}}",
|
||||
"newAddress": "Alamat baru",
|
||||
"silentIntro": "Pengenal penerima statis. Bagikan sekali dan gunakan kembali selamanya — pengirim menurunkan alamat on-chain unik per pembayaran.",
|
||||
"noIndexer": "Pemindaian dinonaktifkan — tidak ada indexer BIP-352 yang dikonfigurasi. Setel <0>bip352IndexerUrl</0> di konfigurasi aplikasi Anda untuk mendeteksi silent payment masuk.",
|
||||
"silentBalance": "Saldo silent payment: <0>{{amount}}</0>",
|
||||
"scanForNew": "Pindai pembayaran baru",
|
||||
"scanForPayments": "Pindai pembayaran"
|
||||
},
|
||||
|
||||
@@ -754,14 +754,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "ទទួល Bitcoin",
|
||||
"description": "ចែករំលែកអាសយដ្ឋានដើម្បីទទួល Bitcoin។",
|
||||
"onChain": "លើខ្សែសង្វាក់",
|
||||
"silentPayment": "ការទូទាត់ស្ងាត់",
|
||||
"onChainIntro": "អាសយដ្ឋានថ្មីរាល់ពេល។ បន្ទាប់ពីចែករំលែករួច សូមផ្លាស់ទៅសន្ទស្សន៍ថ្មីដើម្បីការពារភាពឯកជន។",
|
||||
"addressIndex": "អាសយដ្ឋាន #{{index}}",
|
||||
"newAddress": "អាសយដ្ឋានថ្មី",
|
||||
"silentIntro": "អត្តសញ្ញាណទទួលនៅស្ងៀម។ ចែករំលែកម្ដងហើយប្រើឡើងវិញជារៀងរហូត — អ្នកផ្ញើបង្កើតអាសយដ្ឋានពិសេសលើខ្សែសង្វាក់សម្រាប់ការទូទាត់នីមួយៗ។",
|
||||
"noIndexer": "ការស្កេនត្រូវបានបិទ — គ្មានអ្នកធ្វើលិបិក្រម BIP-352 បានកំណត់ទេ។ កំណត់ <0>bip352IndexerUrl</0> ក្នុងការកំណត់កម្មវិធីរបស់អ្នកដើម្បីរកការទូទាត់ស្ងាត់ដែលចូលមក។",
|
||||
"silentBalance": "សមតុល្យការទូទាត់ស្ងាត់៖ <0>{{amount}}</0>",
|
||||
"scanForNew": "ស្កេនការទូទាត់ថ្មី",
|
||||
"scanForPayments": "ស្កេនការទូទាត់"
|
||||
},
|
||||
|
||||
@@ -754,14 +754,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "د بټکوین ترلاسه کول",
|
||||
"description": "د بټکوین د ترلاسه کولو لپاره یوه پته شریکه کړئ.",
|
||||
"onChain": "په زنځیر کې",
|
||||
"silentPayment": "چوپه ورکړه",
|
||||
"onChainIntro": "هر ځل نوې پته. د شریکولو وروسته د محرمیت لپاره یوې نوې شمارلیکې ته لاړ شئ.",
|
||||
"addressIndex": "پته #{{index}}",
|
||||
"newAddress": "نوې پته",
|
||||
"silentIntro": "د ترلاسه کولو ثابته پېژند. یوځل شریکه کړئ او د تل لپاره بیا یې کاروئ — لیږونکي د هرې ورکړې لپاره په زنځیر کې یوه ځانګړې پته راپیدا کوي.",
|
||||
"noIndexer": "سکن غیرفعال دی — د BIP-352 ایندکس کوونکی نه دی تنظیم شوی. د راتلونکو چوپو ورکړو د کشف لپاره ستاسو د اپلیکیشن تنظیماتو کې <0>bip352IndexerUrl</0> وټاکئ.",
|
||||
"silentBalance": "د چوپې ورکړې بیلانس: <0>{{amount}}</0>",
|
||||
"scanForNew": "د نوو ورکړو لپاره سکن",
|
||||
"scanForPayments": "د ورکړو لپاره سکن"
|
||||
},
|
||||
|
||||
@@ -1177,14 +1177,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Receber Bitcoin",
|
||||
"description": "Compartilhe um endereço para receber bitcoin.",
|
||||
"onChain": "On-chain",
|
||||
"silentPayment": "Pagamento silencioso",
|
||||
"onChainIntro": "Endereço novo a cada vez. Avance para um novo índice após compartilhar para privacidade.",
|
||||
"addressIndex": "Endereço n.º {{index}}",
|
||||
"newAddress": "Novo endereço",
|
||||
"silentIntro": "Identificador de recebimento estático. Compartilhe uma vez e reutilize para sempre — remetentes derivam um endereço on-chain único por pagamento.",
|
||||
"noIndexer": "Escaneamento desativado — nenhum indexador BIP-352 configurado. Defina <0>bip352IndexerUrl</0> na sua configuração do app para detectar pagamentos silenciosos recebidos.",
|
||||
"silentBalance": "Saldo de pagamentos silenciosos: <0>{{amount}}</0>",
|
||||
"scanForNew": "Escanear novos pagamentos",
|
||||
"scanForPayments": "Escanear pagamentos"
|
||||
},
|
||||
|
||||
@@ -1177,14 +1177,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Получить Bitcoin",
|
||||
"description": "Поделитесь адресом для получения bitcoin.",
|
||||
"onChain": "В блокчейне",
|
||||
"silentPayment": "Тихий платёж",
|
||||
"onChainIntro": "Свежий адрес каждый раз. Переходите на новый индекс после публикации для конфиденциальности.",
|
||||
"addressIndex": "Адрес №{{index}}",
|
||||
"newAddress": "Новый адрес",
|
||||
"silentIntro": "Статический идентификатор получения. Поделитесь один раз и используйте навсегда — отправители получают уникальный адрес в блокчейне на каждый платёж.",
|
||||
"noIndexer": "Сканирование отключено — индексер BIP-352 не настроен. Установите <0>bip352IndexerUrl</0> в конфигурации вашего приложения, чтобы обнаруживать входящие тихие платежи.",
|
||||
"silentBalance": "Баланс тихих платежей: <0>{{amount}}</0>",
|
||||
"scanForNew": "Сканировать новые платежи",
|
||||
"scanForPayments": "Сканировать платежи"
|
||||
},
|
||||
|
||||
@@ -754,14 +754,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Gamuchira Bitcoin",
|
||||
"description": "Govera kero yokugamuchira bitcoin.",
|
||||
"onChain": "PaCheni",
|
||||
"silentPayment": "Mubhadharo wakanyararira",
|
||||
"onChainIntro": "Kero itsva nguva dzese. Chinjira kune index itsva mushure mokugovera kuti uchengetedze privacy.",
|
||||
"addressIndex": "Kero #{{index}}",
|
||||
"newAddress": "Kero itsva",
|
||||
"silentIntro": "Chiratidzo chokugamuchira chakamira. Govera kamwe woshandisazve nokusingaperi — vatumiri vanobvisa kero yakasiyana pacheni pamubhadharo woga woga.",
|
||||
"noIndexer": "Kuongorora kwadzimwa — hapana muongorori weBIP-352 wakaiswa. Isa <0>bip352IndexerUrl</0> mukurongedzwa kweapp yako kuti uone mibhadharo yakanyararira inopinda.",
|
||||
"silentBalance": "Bharanzi remubhadharo wakanyararira: <0>{{amount}}</0>",
|
||||
"scanForNew": "Tsvaga mibhadharo mitsva",
|
||||
"scanForPayments": "Tsvaga mibhadharo"
|
||||
},
|
||||
|
||||
@@ -1186,14 +1186,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "Bitcoin Al",
|
||||
"description": "Bitcoin almak için bir adres paylaşın.",
|
||||
"onChain": "Zincir üstü",
|
||||
"silentPayment": "Sessiz ödeme",
|
||||
"onChainIntro": "Her seferinde yeni adres. Gizlilik için paylaşımdan sonra yeni bir dizine geçin.",
|
||||
"addressIndex": "Adres #{{index}}",
|
||||
"newAddress": "Yeni adres",
|
||||
"silentIntro": "Sabit alım tanımlayıcısı. Bir kez paylaşın ve sonsuza dek tekrar kullanın — göndericiler her ödeme için benzersiz bir zincir üstü adres türetir.",
|
||||
"noIndexer": "Tarama devre dışı — BIP-352 indeksleyici yapılandırılmamış. Gelen sessiz ödemeleri algılamak için uygulama yapılandırmanızda <0>bip352IndexerUrl</0> ayarını yapın.",
|
||||
"silentBalance": "Sessiz ödeme bakiyesi: <0>{{amount}}</0>",
|
||||
"scanForNew": "Yeni ödemeler için tara",
|
||||
"scanForPayments": "Ödemeler için tara"
|
||||
},
|
||||
|
||||
@@ -754,14 +754,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "接收比特幣",
|
||||
"description": "分享一個地址以接收比特幣。",
|
||||
"onChain": "鏈上",
|
||||
"silentPayment": "靜默支付",
|
||||
"onChainIntro": "每次都生成新地址。分享後請切換到新索引以保護隱私。",
|
||||
"addressIndex": "地址 #{{index}}",
|
||||
"newAddress": "新地址",
|
||||
"silentIntro": "靜態接收識別符號。一次分享,永久複用——傳送方為每筆支付派生唯一的鏈上地址。",
|
||||
"noIndexer": "掃描已停用——未配置 BIP-352 索引器。在應用配置中設定 <0>bip352IndexerUrl</0> 以檢測傳入的靜默支付。",
|
||||
"silentBalance": "靜默支付餘額:<0>{{amount}}</0>",
|
||||
"scanForNew": "掃描新支付",
|
||||
"scanForPayments": "掃描支付"
|
||||
},
|
||||
|
||||
@@ -754,14 +754,8 @@
|
||||
"receiveDialog": {
|
||||
"title": "接收比特币",
|
||||
"description": "分享一个地址以接收比特币。",
|
||||
"onChain": "链上",
|
||||
"silentPayment": "静默支付",
|
||||
"onChainIntro": "每次都生成新地址。分享后请切换到新索引以保护隐私。",
|
||||
"addressIndex": "地址 #{{index}}",
|
||||
"newAddress": "新地址",
|
||||
"silentIntro": "静态接收标识符。一次分享,永久复用——发送方为每笔支付派生唯一的链上地址。",
|
||||
"noIndexer": "扫描已禁用——未配置 BIP-352 索引器。在应用配置中设置 <0>bip352IndexerUrl</0> 以检测传入的静默支付。",
|
||||
"silentBalance": "静默支付余额:<0>{{amount}}</0>",
|
||||
"scanForNew": "扫描新支付",
|
||||
"scanForPayments": "扫描支付"
|
||||
},
|
||||
|
||||
+60
-130
@@ -1,7 +1,7 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useSeoMeta } from '@unhead/react';
|
||||
import { useTranslation, Trans } from 'react-i18next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Copy,
|
||||
Check,
|
||||
@@ -34,7 +34,6 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { HDSendBitcoinDialog } from '@/components/HDSendBitcoinDialog';
|
||||
import { HDSilentPaymentScanDialog } from '@/components/HDSilentPaymentScanDialog';
|
||||
import { WalletBackupMnemonicDialog } from '@/components/WalletBackupMnemonic';
|
||||
@@ -64,8 +63,7 @@ export function WalletPage() {
|
||||
const sp = useHdWalletSp();
|
||||
const { data: btcPrice } = useHdBtcPrice();
|
||||
|
||||
const [copiedAddress, setCopiedAddress] = useState(false);
|
||||
const [copiedSp, setCopiedSp] = useState(false);
|
||||
const [copiedPayload, setCopiedPayload] = useState(false);
|
||||
const [txOpen, setTxOpen] = useState(false);
|
||||
const [sendOpen, setSendOpen] = useState(false);
|
||||
const [receiveOpen, setReceiveOpen] = useState(false);
|
||||
@@ -80,36 +78,30 @@ export function WalletPage() {
|
||||
const address = currentReceiveAddress?.address ?? '';
|
||||
const spAddress = silentPaymentAddress?.address ?? '';
|
||||
|
||||
const copyAddress = async () => {
|
||||
if (!address) return;
|
||||
// Combined BIP-21 payload: `bitcoin:<bc1>?sp=<sp1>` when both are
|
||||
// available, falling back to the single endpoint that exists.
|
||||
// Mirrors the campaign donate panel's QR payload so BIP-352-aware
|
||||
// wallets pick the `sp=` parameter and legacy wallets fall back to
|
||||
// the on-chain address.
|
||||
const qrPayload = address && spAddress
|
||||
? `bitcoin:${address}?sp=${spAddress}`
|
||||
: address
|
||||
? `bitcoin:${address}`
|
||||
: spAddress
|
||||
? `bitcoin:?sp=${spAddress}`
|
||||
: '';
|
||||
|
||||
const copyPayload = async () => {
|
||||
if (!qrPayload) return;
|
||||
try {
|
||||
await navigator.clipboard.writeText(address);
|
||||
setCopiedAddress(true);
|
||||
setTimeout(() => setCopiedAddress(false), 2000);
|
||||
await navigator.clipboard.writeText(qrPayload);
|
||||
setCopiedPayload(true);
|
||||
setTimeout(() => setCopiedPayload(false), 2000);
|
||||
} catch {
|
||||
// clipboard unavailable
|
||||
}
|
||||
};
|
||||
|
||||
const copySpAddress = async () => {
|
||||
if (!spAddress) return;
|
||||
try {
|
||||
await navigator.clipboard.writeText(spAddress);
|
||||
setCopiedSp(true);
|
||||
setTimeout(() => setCopiedSp(false), 2000);
|
||||
} catch {
|
||||
// clipboard unavailable
|
||||
}
|
||||
};
|
||||
|
||||
const truncatedAddress = address
|
||||
? `${address.slice(0, 12)}...${address.slice(-8)}`
|
||||
: '';
|
||||
|
||||
const truncatedSpAddress = spAddress
|
||||
? `${spAddress.slice(0, 12)}...${spAddress.slice(-8)}`
|
||||
: '';
|
||||
|
||||
// ── Logged out ────────────────────────────────────────────────
|
||||
if (availability.status === 'logged-out') {
|
||||
return (
|
||||
@@ -185,6 +177,14 @@ export function WalletPage() {
|
||||
<KeyRound className="size-4 mr-2" />
|
||||
{t('walletSettings.backup.label')}
|
||||
</DropdownMenuItem>
|
||||
{sp.enabled && spAddress && (
|
||||
<DropdownMenuItem onSelect={() => setSpScanOpen(true)} className="cursor-pointer">
|
||||
<Radar className="size-4 mr-2" />
|
||||
{sp.storage?.scanHeight && sp.storage.scanHeight > 0
|
||||
? t('wallet.receiveDialog.scanForNew')
|
||||
: t('wallet.receiveDialog.scanForPayments')}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem asChild>
|
||||
<Link to="/wallet/legacy" className="cursor-pointer">
|
||||
<History className="size-4 mr-2" />
|
||||
@@ -291,115 +291,45 @@ export function WalletPage() {
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Tabs defaultValue="onchain" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-2">
|
||||
<TabsTrigger value="onchain">{t('wallet.receiveDialog.onChain')}</TabsTrigger>
|
||||
<TabsTrigger value="silent" disabled={!spAddress}>
|
||||
{t('wallet.receiveDialog.silentPayment')}
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
{qrPayload && (
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
{/* Combined BIP-21 QR. BIP-352-aware wallets pick the
|
||||
`sp=` parameter; legacy wallets fall back to the
|
||||
on-chain address. Mirrors CampaignWalletDonatePanel. */}
|
||||
<div className="rounded-2xl bg-white p-4 shadow-sm">
|
||||
<QRCodeCanvas value={qrPayload} size={220} level="M" />
|
||||
</div>
|
||||
|
||||
{/* Copyable row showing the full payment URI. */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={copyPayload}
|
||||
className="w-full flex items-center gap-2 rounded-lg border bg-muted/40 px-3 py-2.5 text-left hover:bg-muted/60 motion-safe:transition-colors cursor-pointer"
|
||||
>
|
||||
<span className="flex-1 min-w-0 truncate font-mono text-xs" title={qrPayload}>
|
||||
{qrPayload}
|
||||
</span>
|
||||
{copiedPayload ? (
|
||||
<Check className="size-4 text-green-500 shrink-0" />
|
||||
) : (
|
||||
<Copy className="size-4 text-muted-foreground shrink-0" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* ── On-chain (BIP86 single-use) ──────────────── */}
|
||||
<TabsContent value="onchain" className="mt-4">
|
||||
{address && (
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<p className="text-xs text-muted-foreground text-center max-w-xs">
|
||||
{t('wallet.receiveDialog.onChainIntro')}
|
||||
</p>
|
||||
|
||||
<div className="rounded-2xl bg-white p-4 shadow-sm">
|
||||
<QRCodeCanvas value={address} size={200} level="M" />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3 text-xs text-muted-foreground">
|
||||
<span>{t('wallet.receiveDialog.addressIndex', { index: currentReceiveAddress?.index ?? 0 })}</span>
|
||||
<span aria-hidden>·</span>
|
||||
<button
|
||||
onClick={copyAddress}
|
||||
className="flex items-center gap-2 rounded-full border px-4 py-2 text-sm font-mono text-muted-foreground hover:bg-muted/50 transition-colors cursor-pointer"
|
||||
onClick={() => nextReceiveAddress()}
|
||||
className="hover:text-foreground underline-offset-4 hover:underline transition-colors cursor-pointer"
|
||||
>
|
||||
{truncatedAddress}
|
||||
{copiedAddress ? (
|
||||
<Check className="size-3.5 text-green-500" />
|
||||
) : (
|
||||
<Copy className="size-3.5" />
|
||||
)}
|
||||
{t('wallet.receiveDialog.newAddress')}
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-3 text-xs text-muted-foreground">
|
||||
<span>{t('wallet.receiveDialog.addressIndex', { index: currentReceiveAddress?.index ?? 0 })}</span>
|
||||
<span aria-hidden>·</span>
|
||||
<button
|
||||
onClick={() => nextReceiveAddress()}
|
||||
className="hover:text-foreground underline-offset-4 hover:underline transition-colors cursor-pointer"
|
||||
>
|
||||
{t('wallet.receiveDialog.newAddress')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</TabsContent>
|
||||
|
||||
{/* ── Silent payment (BIP-352 static) ──────────── */}
|
||||
<TabsContent value="silent" className="mt-4">
|
||||
{spAddress && (
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<p className="text-xs text-muted-foreground text-center max-w-xs">
|
||||
{t('wallet.receiveDialog.silentIntro')}
|
||||
</p>
|
||||
|
||||
<div className="rounded-2xl bg-white p-4 shadow-sm">
|
||||
<QRCodeCanvas value={spAddress} size={220} level="L" />
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={copySpAddress}
|
||||
className="flex items-center gap-2 rounded-full border px-4 py-2 text-sm font-mono text-muted-foreground hover:bg-muted/50 transition-colors cursor-pointer"
|
||||
>
|
||||
{truncatedSpAddress}
|
||||
{copiedSp ? (
|
||||
<Check className="size-3.5 text-green-500" />
|
||||
) : (
|
||||
<Copy className="size-3.5" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
{sp.unavailableReason === 'no-indexer' ? (
|
||||
<p className="text-xs text-orange-500 dark:text-orange-400 text-center max-w-xs">
|
||||
<Trans
|
||||
i18nKey="wallet.receiveDialog.noIndexer"
|
||||
components={{ 0: <span className="font-mono" /> }}
|
||||
/>
|
||||
</p>
|
||||
) : sp.enabled ? (
|
||||
<div className="flex flex-col items-center gap-2 w-full">
|
||||
{sp.balance > 0 && (
|
||||
<p className="text-xs text-muted-foreground text-center">
|
||||
<Trans
|
||||
i18nKey="wallet.receiveDialog.silentBalance"
|
||||
values={{
|
||||
amount: btcPrice
|
||||
? satsToUSD(sp.balance, btcPrice)
|
||||
: `${formatBTC(sp.balance)} BTC`,
|
||||
}}
|
||||
components={{ 0: <span className="text-foreground font-medium" /> }}
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setSpScanOpen(true)}
|
||||
className="rounded-full"
|
||||
>
|
||||
<Radar className="size-3.5 mr-1.5" />
|
||||
{sp.storage?.scanHeight && sp.storage.scanHeight > 0
|
||||
? t('wallet.receiveDialog.scanForNew')
|
||||
: t('wallet.receiveDialog.scanForPayments')}
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user