diff --git a/src/components/bitcoinConnect/BitcoinConnect.js b/src/components/bitcoinConnect/BitcoinConnect.js
index 11752a0..d2f0a01 100644
--- a/src/components/bitcoinConnect/BitcoinConnect.js
+++ b/src/components/bitcoinConnect/BitcoinConnect.js
@@ -5,14 +5,16 @@ const Button = dynamic(() => import('@getalby/bitcoin-connect-react').then(mod =
ssr: false,
});
+// Module-level state
let initialized = false;
let bitcoinConnectClient = null;
export async function initializeBitcoinConnect() {
if (!initialized) {
try {
- // Import the full module
+ // Import the required modules
const bc = await import('@getalby/bitcoin-connect-react');
+ const sdkModule = await import('@getalby/sdk');
// Initialize with the config options
bc.init({
@@ -23,6 +25,17 @@ export async function initializeBitcoinConnect() {
// Store the client for use in components
bitcoinConnectClient = bc.client;
+
+ // Export NWC functionality directly
+ if (!bitcoinConnectClient) {
+ console.log('Creating backup NWC client instance');
+ // Create fallback if client isn't available
+ bitcoinConnectClient = {
+ nwc: sdkModule.nwc,
+ webln: sdkModule.webln
+ };
+ }
+
initialized = true;
console.log('Bitcoin Connect initialized successfully, client:', bitcoinConnectClient);
} catch (error) {
@@ -35,9 +48,15 @@ export async function initializeBitcoinConnect() {
} else {
console.log('Bitcoin Connect already initialized');
}
+
return bitcoinConnectClient;
}
+// Export the SDK for direct usage
+export const getSDK = async () => {
+ return import('@getalby/sdk');
+};
+
const BitcoinConnectButton = () => {
useEffect(() => {
initializeBitcoinConnect();
diff --git a/src/components/bitcoinConnect/SubscriptionPaymentButton.js b/src/components/bitcoinConnect/SubscriptionPaymentButton.js
index f5b396f..a951b29 100644
--- a/src/components/bitcoinConnect/SubscriptionPaymentButton.js
+++ b/src/components/bitcoinConnect/SubscriptionPaymentButton.js
@@ -1,10 +1,9 @@
import React, { useState, useEffect } from 'react';
import { track } from '@vercel/analytics';
-import { initializeBitcoinConnect } from './BitcoinConnect';
+import { initializeBitcoinConnect, getSDK } from './BitcoinConnect';
import { LightningAddress } from '@getalby/lightning-tools';
import { useToast } from '@/hooks/useToast';
import { useSession } from 'next-auth/react';
-import { webln } from '@getalby/sdk';
import { useRouter } from 'next/router';
import { Divider } from 'primereact/divider';
import dynamic from 'next/dynamic';
@@ -30,7 +29,6 @@ const SubscriptionPaymentButtons = ({
const [invoice, setInvoice] = useState(null);
const [showRecurringOptions, setShowRecurringOptions] = useState(false);
const [nwcInput, setNwcInput] = useState('');
- const [bitcoinConnectClient, setBitcoinConnectClient] = useState(null);
const { showToast } = useToast();
const { data: session, status } = useSession();
const router = useRouter();
@@ -40,33 +38,27 @@ const SubscriptionPaymentButtons = ({
useEffect(() => {
// Initialize Bitcoin Connect as early as possible
- const initBC = async () => {
- try {
- const client = await initializeBitcoinConnect();
- console.log("Client in SubscriptionPaymentButton:", client);
- setBitcoinConnectClient(client);
- } catch (err) {
- console.error("Error initializing Bitcoin Connect in SubscriptionPaymentButton:", err);
- }
- };
-
- initBC();
+ initializeBitcoinConnect().catch(err => {
+ console.error("Error initializing Bitcoin Connect:", err);
+ });
}, []);
useEffect(() => {
let intervalId;
if (invoice) {
intervalId = setInterval(async () => {
- const paid = await invoice.verifyPayment();
-
- if (paid && invoice.preimage) {
+ try {
+ const paid = await invoice.verifyPayment();
+ if (paid && invoice.preimage) {
+ clearInterval(intervalId);
+ // handle success
+ onSuccess();
+ }
+ } catch (error) {
+ console.error("Error verifying payment:", error);
clearInterval(intervalId);
- // handle success
- onSuccess();
}
}, 1000);
- } else {
- console.error('no invoice');
}
return () => {
@@ -74,7 +66,7 @@ const SubscriptionPaymentButtons = ({
clearInterval(intervalId);
}
};
- }, [invoice]);
+ }, [invoice, onSuccess]);
const fetchInvoice = async () => {
try {
@@ -84,6 +76,7 @@ const SubscriptionPaymentButtons = ({
satoshi: amount,
comment: `Subscription Purchase. User: ${session?.user?.id}`,
});
+ console.log("Invoice fetched successfully:", newInvoice);
return newInvoice;
} catch (error) {
console.error('Error fetching invoice:', error);
@@ -106,32 +99,18 @@ const SubscriptionPaymentButtons = ({
};
const handleRecurringSubscription = async () => {
- setIsProcessing(true);
-
- // Re-initialize if not already initialized
- if (!bitcoinConnectClient) {
- try {
- console.log("Client not found, reinitializing");
- const client = await initializeBitcoinConnect();
- setBitcoinConnectClient(client);
-
- if (!client) {
- showToast('error', 'Connection Error', 'Failed to initialize Bitcoin Connect client');
- setIsProcessing(false);
- return;
- }
- } catch (err) {
- console.error("Error reinitializing Bitcoin Connect:", err);
- showToast('error', 'Connection Error', 'Failed to initialize Bitcoin Connect client');
- setIsProcessing(false);
- return;
- }
+ if (!setIsProcessing) {
+ console.warn("setIsProcessing is not defined");
+ } else {
+ setIsProcessing(true);
}
try {
- // Import the SDK directly to avoid client issues
- const { nwc } = await import('@getalby/sdk');
- const newNwc = nwc.NWCClient.withNewSecret();
+ // Get SDK directly to avoid client issues
+ const sdk = await getSDK();
+
+ // Create NWC client
+ const newNwc = sdk.nwc.NWCClient.withNewSecret();
const yearFromNow = new Date();
yearFromNow.setFullYear(yearFromNow.getFullYear() + 1);
@@ -145,36 +124,44 @@ const SubscriptionPaymentButtons = ({
expiresAt: yearFromNow,
};
- // Initialize NWC directly with the SDK
+ console.log("Initializing NWC with options:", initNwcOptions);
+
+ // Initialize NWC
await newNwc.initNWC(initNwcOptions);
showToast('info', 'Alby', 'Alby connection window opened.');
- // Get NWC URL directly
+ // Get NWC URL
const newNWCUrl = newNwc.getNostrWalletConnectUrl();
+ console.log("NWC URL generated:", !!newNWCUrl);
if (newNWCUrl) {
- const nwcProvider = new webln.NostrWebLNProvider({
+ const nwcProvider = new sdk.webln.NostrWebLNProvider({
nostrWalletConnectUrl: newNWCUrl,
});
await nwcProvider.enable();
+ console.log("NWC provider enabled");
const invoice = await fetchInvoice();
+ console.log("Invoice fetched for recurring payment:", !!invoice);
if (!invoice || !invoice.paymentRequest) {
showToast('error', 'NWC', `Failed to fetch invoice from ${lnAddress}`);
- setIsProcessing(false);
+ if (setIsProcessing) setIsProcessing(false);
return;
}
+ console.log("Sending payment with NWC provider");
const paymentResponse = await nwcProvider.sendPayment(invoice.paymentRequest);
+ console.log("Payment response:", paymentResponse);
if (!paymentResponse || !paymentResponse?.preimage) {
showToast('error', 'NWC', 'Payment failed');
- setIsProcessing(false);
+ if (setIsProcessing) setIsProcessing(false);
return;
}
+ console.log("Updating subscription in API");
const subscriptionResponse = await axios.put('/api/users/subscription', {
userId: session.user.id,
isSubscribed: true,
@@ -196,7 +183,7 @@ const SubscriptionPaymentButtons = ({
showToast('error', 'Subscription Setup Failed', `Error: ${error.message}`);
if (onError) onError(error);
} finally {
- setIsProcessing(false);
+ if (setIsProcessing) setIsProcessing(false);
}
};
@@ -206,29 +193,40 @@ const SubscriptionPaymentButtons = ({
return;
}
- setIsProcessing(true);
+ if (setIsProcessing) setIsProcessing(true);
+
try {
- const nwc = new webln.NostrWebLNProvider({
+ const sdk = await getSDK();
+ const nwc = new sdk.webln.NostrWebLNProvider({
nostrWalletConnectUrl: nwcInput,
});
await nwc.enable();
+ console.log("Manual NWC provider enabled");
const invoice = await fetchInvoice();
+ console.log("Invoice fetched for manual NWC:", !!invoice);
+
if (!invoice || !invoice.paymentRequest) {
showToast('error', 'NWC', `Failed to fetch invoice from ${lnAddress}`);
+ if (setIsProcessing) setIsProcessing(false);
return;
}
+ console.log("Sending payment with manual NWC");
const payResponse = await nwc.sendPayment(invoice.paymentRequest);
+ console.log("Payment response:", payResponse);
+
if (!payResponse || !payResponse.preimage) {
showToast('error', 'NWC', 'Payment failed');
+ if (setIsProcessing) setIsProcessing(false);
return;
}
showToast('success', 'NWC', 'Payment successful!');
try {
+ console.log("Updating subscription in API (manual)");
const subscriptionResponse = await axios.put('/api/users/subscription', {
userId: session.user.id,
isSubscribed: true,
@@ -252,7 +250,7 @@ const SubscriptionPaymentButtons = ({
showToast('error', 'NWC', `An error occurred: ${error.message}`);
if (onError) onError(error);
} finally {
- setIsProcessing(false);
+ if (setIsProcessing) setIsProcessing(false);
}
};
diff --git a/src/components/content/courses/details/CourseDetails.js b/src/components/content/courses/details/CourseDetails.js
index e1c3c83..53ef5e6 100644
--- a/src/components/content/courses/details/CourseDetails.js
+++ b/src/components/content/courses/details/CourseDetails.js
@@ -127,7 +127,7 @@ export default function CourseDetails({
if (session?.user && session.user?.role?.subscribed && decryptionPerformed) {
return (
);
@@ -163,7 +163,7 @@ export default function CourseDetails({
if (paidCourse && author && processedEvent?.pubkey === session?.user?.pubkey) {
return (