import { webln } from '@getalby/sdk'; import { SendPaymentResponse } from '@getalby/sdk/dist/types'; import { NDKEvent } from '@nostr-dev-kit/ndk'; import * as Dialog from '@radix-ui/react-dialog'; import { invoke } from '@tauri-apps/api/primitives'; import { message } from '@tauri-apps/plugin-dialog'; import { QRCodeSVG } from 'qrcode.react'; import { useEffect, useRef, useState } from 'react'; import CurrencyInput from 'react-currency-input-field'; import { useNavigate } from 'react-router-dom'; import { useNDK } from '@libs/ndk/provider'; import { useStorage } from '@libs/storage/provider'; import { CancelIcon, ZapIcon } from '@shared/icons'; import { useProfile } from '@utils/hooks/useProfile'; import { sendNativeNotification } from '@utils/notification'; import { compactNumber } from '@utils/number'; export function NoteZap({ event }: { event: NDKEvent }) { const nwc = useRef(null); const navigate = useNavigate(); const { db } = useStorage(); const { ndk } = useNDK(); const { user } = useProfile(event.pubkey); const [walletConnectURL, setWalletConnectURL] = useState(null); const [amount, setAmount] = useState('21'); const [zapMessage, setZapMessage] = useState(''); const [invoice, setInvoice] = useState(null); const [isOpen, setIsOpen] = useState(false); const [isCompleted, setIsCompleted] = useState(false); const [isLoading, setIsLoading] = useState(false); const createZapRequest = async () => { try { if (!ndk.signer) return navigate('/new/privkey'); const zapAmount = parseInt(amount) * 1000; const res = await event.zap(zapAmount, zapMessage); if (!res) return await message('Cannot create zap request', { title: 'Zap', type: 'error', }); // user don't connect nwc, create QR Code for invoice if (!walletConnectURL) return setInvoice(res); // user connect nwc nwc.current = new webln.NostrWebLNProvider({ nostrWalletConnectUrl: walletConnectURL, }); await nwc.current.enable(); // start loading setIsLoading(true); // send payment via nwc const send: SendPaymentResponse = await nwc.current.sendPayment(res); if (send) { await sendNativeNotification( `You've tipped ${compactNumber.format(send.amount)} sats to ${ user?.name || user?.display_name || user?.displayName }` ); // eose nwc.current.close(); setIsCompleted(true); setIsLoading(false); // reset after 3 secs const timeout = setTimeout(() => setIsCompleted(false), 3000); clearTimeout(timeout); } } catch (e) { nwc.current.close(); setIsLoading(false); await message(JSON.stringify(e), { title: 'Zap', type: 'error' }); } }; useEffect(() => { async function getWalletConnectURL() { const uri: string = await invoke('secure_load', { key: `${db.account.pubkey}-nwc`, }); if (uri) setWalletConnectURL(uri); } if (isOpen) getWalletConnectURL(); return () => { setAmount('21'); setZapMessage(''); setIsCompleted(false); setIsLoading(false); }; }, [isOpen]); return (
Send tip to {user?.name || user?.display_name || user?.displayName}
{!invoice ? ( <>
setAmount(value)} className="w-full flex-1 border-none bg-transparent text-right text-4xl font-semibold placeholder:text-neutral-600 focus:outline-none focus:ring-0 dark:text-neutral-400" /> sats
setZapMessage(e.target.value)} spellCheck={false} autoComplete="off" autoCorrect="off" autoCapitalize="off" placeholder="Enter message (optional)" className="w-full resize-none rounded-lg border-transparent bg-neutral-100 px-3 py-3 !outline-none placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-400" />
{walletConnectURL ? ( ) : ( )}
) : (

Scan to zap

You must use Bitcoin wallet which support Lightning
such as: Blue Wallet, Bitkit, Phoenix,...
)}
); }