import React, { useState, useEffect } from 'react'; import { Button } from 'primereact/button'; import { ProgressSpinner } from 'primereact/progressspinner'; import { initializeBitcoinConnect } from './BitcoinConnect'; import { LightningAddress } from '@getalby/lightning-tools'; import { useToast } from '@/hooks/useToast'; import { useSession } from 'next-auth/react'; import { webln, nwc } from '@getalby/sdk'; import { useRouter } from 'next/router'; import { Divider } from 'primereact/divider'; import dynamic from 'next/dynamic'; import AlbyButton from '@/components/buttons/AlbyButton'; import axios from 'axios'; import Image from 'next/image'; const PaymentModal = dynamic( () => import('@getalby/bitcoin-connect-react').then((mod) => mod.Payment), { ssr: false } ); const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptionSuccess, setIsProcessing }) => { const [invoice, setInvoice] = useState(null); const [showRecurringOptions, setShowRecurringOptions] = useState(false); const [nwcInput, setNwcInput] = useState(''); const { showToast } = useToast(); const { data: session } = useSession(); const lnAddress = process.env.NEXT_PUBLIC_LIGHTNING_ADDRESS; const amount = 25; useEffect(() => { initializeBitcoinConnect(); }, []); useEffect(() => { let intervalId; if (invoice) { intervalId = setInterval(async () => { const paid = await invoice.verifyPayment(); if (paid && invoice.preimage) { clearInterval(intervalId); // handle success onSuccess(); } }, 1000); } else { console.log('no invoice'); } return () => { if (intervalId) { clearInterval(intervalId); } }; }, [invoice]); const fetchInvoice = async () => { try { const ln = new LightningAddress(lnAddress); await ln.fetch(); const newInvoice = await ln.requestInvoice({ satoshi: amount }); console.log('newInvoice', newInvoice); return newInvoice; } catch (error) { console.error('Error fetching invoice:', error); showToast('error', 'Invoice Error', `Failed to fetch the invoice: ${error.message}`); if (onError) onError(error); return null; } }; const handlePaymentSuccess = async (response) => { console.log('Payment successful', response); clearInterval(checkPaymentInterval); showToast('success', 'Payment Successful', 'Your payment has been processed successfully.'); if (onSuccess) onSuccess(response); }; const handlePaymentError = async (error) => { console.error('Payment error', error); clearInterval(checkPaymentInterval); showToast('error', 'Payment Failed', `An error occurred during payment: ${error.message}`); if (onError) onError(error); }; const handleRecurringSubscription = async () => { setIsProcessing(true); const newNwc = nwc.NWCClient.withNewSecret(); const yearFromNow = new Date(); yearFromNow.setFullYear(yearFromNow.getFullYear() + 1); try { const initNwcOptions = { name: "plebdevs.com", requestMethods: ['pay_invoice'], maxAmount: 25, editable: false, budgetRenewal: 'monthly', expiresAt: yearFromNow, }; await newNwc.initNWC(initNwcOptions); showToast('info', 'Alby', 'Alby connection window opened.'); const newNWCUrl = newNwc.getNostrWalletConnectUrl(); if (newNWCUrl) { const subscriptionResponse = await axios.put('/api/users/subscription', { userId: session.user.id, isSubscribed: true, nwc: newNWCUrl, }); if (subscriptionResponse.status === 200) { showToast('success', 'Subscription Setup', 'Recurring subscription setup successful!'); if (onRecurringSubscriptionSuccess) onRecurringSubscriptionSuccess(); } else { throw new Error(`Unexpected response status: ${subscriptionResponse.status}`); } } else { throw new Error('Failed to generate NWC URL'); } } catch (error) { console.error('Error initializing NWC:', error); showToast('error', 'Subscription Setup Failed', `Error: ${error.message}`); if (onError) onError(error); } finally { setIsProcessing(false); } }; const handleManualNwcSubmit = async () => { if (!nwcInput) { showToast('error', 'NWC', 'Please enter a valid NWC URL'); return; } setIsProcessing(true); try { const nwc = new webln.NostrWebLNProvider({ nostrWalletConnectUrl: nwcInput, }); await nwc.enable(); const invoice = await fetchInvoice(); if (!invoice || !invoice.paymentRequest) { showToast('error', 'NWC', `Failed to fetch invoice from ${lnAddress}`); return; } const payResponse = await nwc.sendPayment(invoice.paymentRequest); if (!payResponse || !payResponse.preimage) { showToast('error', 'NWC', 'Payment failed'); return; } showToast('success', 'NWC', 'Payment successful!'); try { const subscriptionResponse = await axios.put('/api/users/subscription', { userId: session.user.id, isSubscribed: true, nwc: nwcInput, }); if (subscriptionResponse.status === 200) { showToast('success', 'NWC', 'Subscription setup successful!'); if (onRecurringSubscriptionSuccess) onRecurringSubscriptionSuccess(); } else { throw new Error('Unexpected response status'); } } catch (error) { console.error('Subscription setup error:', error); showToast('error', 'NWC', 'Subscription setup failed. Please contact support.'); if (onError) onError(error); } } catch (error) { console.error('NWC error:', error); showToast('error', 'NWC', `An error occurred: ${error.message}`); if (onError) onError(error); } finally { setIsProcessing(false); } }; return ( <> {!invoice && (
)} {showRecurringOptions && ( <>
or

Manually enter NWC URL

*make sure you set a budget of at least 25000 sats and set budget renewal to monthly setNwcInput(e.target.value)} placeholder="Enter NWC URL" className="w-full p-2 mb-4 border rounded" />
)} {invoice && invoice.paymentRequest && (
)} ); }; export default SubscriptionPaymentButtons;