mirror of
https://gitlab.com/soapbox-pub/mkstack.git
synced 2025-08-26 20:49:22 +00:00
tidying
This commit is contained in:
parent
8c34dbc8d5
commit
7eecec7506
@ -10,7 +10,6 @@ interface ZapButtonProps {
|
||||
target: Event;
|
||||
className?: string;
|
||||
showCount?: boolean;
|
||||
// New: option to pass pre-fetched zap data (for batch mode)
|
||||
zapData?: { count: number; totalSats: number; isLoading?: boolean };
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { Zap, Copy, Sparkle, Sparkles, Star, Rocket, Wallet, Globe } from 'lucide-react';
|
||||
import { Zap, Copy, Sparkle, Sparkles, Star, Rocket } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
@ -40,24 +40,7 @@ export function ZapDialog({ target, children, className }: ZapDialogProps) {
|
||||
const { user } = useCurrentUser();
|
||||
const { data: author } = useAuthor(target.pubkey);
|
||||
const { toast } = useToast();
|
||||
const { webln, activeNWC, hasWebLN, hasNWC, detectWebLN } = useWallet();
|
||||
|
||||
// Debug logging
|
||||
useEffect(() => {
|
||||
console.debug('ZapDialog wallet status:', { hasWebLN, hasNWC, activeNWC: !!activeNWC });
|
||||
}, [hasWebLN, hasNWC, activeNWC]);
|
||||
|
||||
// Additional debug logging when dialog opens
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
console.debug('ZapDialog opened with wallet status:', {
|
||||
hasWebLN,
|
||||
hasNWC,
|
||||
activeNWC: activeNWC ? { alias: activeNWC.alias, isConnected: activeNWC.isConnected } : null
|
||||
});
|
||||
}
|
||||
}, [open, hasWebLN, hasNWC, activeNWC]);
|
||||
|
||||
const { webln, activeNWC, hasWebLN, detectWebLN } = useWallet();
|
||||
const { zap, isZapping, invoice, setInvoice } = useZaps(target, webln, activeNWC, () => setOpen(false));
|
||||
const [amount, setAmount] = useState<number | string>(100);
|
||||
const [comment, setComment] = useState<string>('');
|
||||
@ -104,7 +87,7 @@ export function ZapDialog({ target, children, className }: ZapDialogProps) {
|
||||
zap(finalAmount, comment);
|
||||
};
|
||||
|
||||
if (!user || user.pubkey === target.pubkey || !author?.metadata?.lud16) {
|
||||
if (!user || user.pubkey === target.pubkey || !author?.metadata?.lud06 && !author?.metadata?.lud16) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -141,28 +124,6 @@ export function ZapDialog({ target, children, className }: ZapDialogProps) {
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{/* Payment Method Indicator */}
|
||||
<div className="flex items-center justify-center py-2 px-1">
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
{hasNWC ? (
|
||||
<>
|
||||
<Wallet className="h-4 w-4 text-green-600" />
|
||||
<span>Wallet Connected</span>
|
||||
</>
|
||||
) : hasWebLN ? (
|
||||
<>
|
||||
<Globe className="h-4 w-4 text-blue-600" />
|
||||
<span>WebLN Available</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Copy className="h-4 w-4" />
|
||||
<span>Manual Payment</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 py-4">
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
|
@ -25,8 +25,6 @@ export function useNWCInternal() {
|
||||
const [activeConnection, setActiveConnection] = useLocalStorage<string | null>('nwc-active-connection', null);
|
||||
const [connectionInfo, setConnectionInfo] = useState<Record<string, NWCInfo>>({});
|
||||
|
||||
// Use connections directly - no filtering needed
|
||||
|
||||
// Parse and validate NWC URI
|
||||
const parseNWCUri = (uri: string): { connectionString: string } | null => {
|
||||
try {
|
||||
@ -70,8 +68,6 @@ export function useNWCInternal() {
|
||||
}
|
||||
|
||||
try {
|
||||
console.debug('Testing NWC connection:', { uri: uri.substring(0, 50) + '...' });
|
||||
|
||||
// Test the connection by creating an LN client with timeout
|
||||
const testPromise = new Promise((resolve, reject) => {
|
||||
try {
|
||||
@ -81,18 +77,15 @@ export function useNWCInternal() {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
setTimeout(() => reject(new Error('Connection test timeout')), 10000);
|
||||
});
|
||||
|
||||
const _client = await Promise.race([testPromise, timeoutPromise]) as LN;
|
||||
await Promise.race([testPromise, timeoutPromise]) as LN;
|
||||
|
||||
const connection: NWCConnection = {
|
||||
connectionString: parsed.connectionString,
|
||||
alias: alias || 'NWC Wallet',
|
||||
isConnected: true,
|
||||
// Don't store the client, create fresh ones for each payment
|
||||
};
|
||||
|
||||
// Store basic connection info
|
||||
@ -107,33 +100,9 @@ export function useNWCInternal() {
|
||||
const newConnections = [...connections, connection];
|
||||
setConnections(newConnections);
|
||||
|
||||
console.debug('NWC connection added:', {
|
||||
alias: connection.alias,
|
||||
totalConnections: newConnections.length,
|
||||
connectionString: parsed.connectionString.substring(0, 50) + '...',
|
||||
isConnected: connection.isConnected
|
||||
});
|
||||
|
||||
// Set as active if it's the first connection or no active connection is set
|
||||
if (connections.length === 0 || !activeConnection) {
|
||||
console.debug('Setting as active connection:', {
|
||||
alias: connection.alias,
|
||||
connectionString: parsed.connectionString.substring(0, 50) + '...',
|
||||
previousActiveConnection: activeConnection
|
||||
});
|
||||
if (connections.length === 0 || !activeConnection)
|
||||
setActiveConnection(parsed.connectionString);
|
||||
console.debug('Active connection set to:', parsed.connectionString.substring(0, 50) + '...');
|
||||
}
|
||||
|
||||
console.debug('NWC connection successful');
|
||||
|
||||
// Force a small delay to ensure state updates are processed
|
||||
setTimeout(() => {
|
||||
console.debug('Post-connection state check:', {
|
||||
connectionsLength: connections.length + 1, // +1 because we just added one
|
||||
newConnectionAlias: connection.alias
|
||||
});
|
||||
}, 100);
|
||||
|
||||
toast({
|
||||
title: 'Wallet connected',
|
||||
@ -159,14 +128,9 @@ export function useNWCInternal() {
|
||||
const filtered = connections.filter(c => c.connectionString !== connectionString);
|
||||
setConnections(filtered);
|
||||
|
||||
console.debug('NWC connection removed:', {
|
||||
remainingConnections: filtered.length
|
||||
});
|
||||
|
||||
if (activeConnection === connectionString) {
|
||||
const newActive = filtered.length > 0 ? filtered[0].connectionString : null;
|
||||
setActiveConnection(newActive);
|
||||
console.debug('Active connection changed:', { newActive });
|
||||
}
|
||||
|
||||
setConnectionInfo(prev => {
|
||||
@ -183,15 +147,8 @@ export function useNWCInternal() {
|
||||
|
||||
// Get active connection
|
||||
const getActiveConnection = useCallback((): NWCConnection | null => {
|
||||
console.debug('getActiveConnection called:', {
|
||||
activeConnection,
|
||||
connectionsLength: connections.length,
|
||||
connections: connections.map(c => ({ alias: c.alias, connectionString: c.connectionString.substring(0, 50) + '...' }))
|
||||
});
|
||||
|
||||
// If no active connection is set but we have connections, set the first one as active
|
||||
if (!activeConnection && connections.length > 0) {
|
||||
console.debug('Setting first connection as active:', connections[0].alias);
|
||||
setActiveConnection(connections[0].connectionString);
|
||||
return connections[0];
|
||||
}
|
||||
@ -202,7 +159,6 @@ export function useNWCInternal() {
|
||||
}
|
||||
|
||||
const found = connections.find(c => c.connectionString === activeConnection);
|
||||
console.debug('Found active connection:', found ? found.alias : 'null');
|
||||
return found || null;
|
||||
}, [activeConnection, connections, setActiveConnection]);
|
||||
|
||||
@ -218,7 +174,6 @@ export function useNWCInternal() {
|
||||
// Always create a fresh client for each payment to avoid stale connections
|
||||
let client: LN;
|
||||
try {
|
||||
console.debug('Creating fresh NWC client for payment...');
|
||||
client = new LN(connection.connectionString);
|
||||
} catch (error) {
|
||||
console.error('Failed to create NWC client:', error);
|
||||
@ -226,20 +181,13 @@ export function useNWCInternal() {
|
||||
}
|
||||
|
||||
try {
|
||||
console.debug('Sending payment via NWC SDK:', {
|
||||
invoice: invoice.substring(0, 50) + '...',
|
||||
connectionAlias: connection.alias
|
||||
});
|
||||
|
||||
// Add timeout to prevent hanging
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
setTimeout(() => reject(new Error('Payment timeout after 30 seconds')), 30000);
|
||||
setTimeout(() => reject(new Error('Payment timeout after 15 seconds')), 15);
|
||||
});
|
||||
|
||||
const paymentPromise = client.pay(invoice);
|
||||
const response = await Promise.race([paymentPromise, timeoutPromise]) as { preimage: string };
|
||||
|
||||
console.debug('Payment successful:', { preimage: response.preimage });
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('NWC payment failed:', error);
|
||||
@ -279,8 +227,6 @@ export function useNWCInternal() {
|
||||
}
|
||||
|
||||
try {
|
||||
console.debug('Testing NWC connection...', { alias: connection.alias });
|
||||
|
||||
// Create a fresh client for testing
|
||||
const testPromise = new Promise((resolve, reject) => {
|
||||
try {
|
||||
@ -294,10 +240,8 @@ export function useNWCInternal() {
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
setTimeout(() => reject(new Error('Connection test timeout')), 5000);
|
||||
});
|
||||
|
||||
await Promise.race([testPromise, timeoutPromise]);
|
||||
|
||||
console.debug('NWC connection test successful');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('NWC connection test failed:', error);
|
||||
@ -305,8 +249,6 @@ export function useNWCInternal() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
return {
|
||||
connections,
|
||||
activeConnection,
|
||||
|
@ -44,7 +44,7 @@ export function useWallet() {
|
||||
}
|
||||
}, [webln, isDetecting]);
|
||||
|
||||
// Only auto-detect once on mount, don't spam detection
|
||||
// Only auto-detect once on mount
|
||||
useEffect(() => {
|
||||
if (!hasAttemptedDetection) {
|
||||
detectWebLN();
|
||||
|
@ -24,7 +24,6 @@ function parseNWCUri(uri: string): NWCConnection | null {
|
||||
const walletPubkey = url.pathname.replace('//', '');
|
||||
const secret = url.searchParams.get('secret');
|
||||
const relayParam = url.searchParams.getAll('relay');
|
||||
const _lud16 = url.searchParams.get('lud16') || undefined;
|
||||
|
||||
if (!walletPubkey || !secret || relayParam.length === 0) {
|
||||
return null;
|
||||
@ -194,7 +193,7 @@ export function useZaps(
|
||||
}
|
||||
|
||||
try {
|
||||
if (!author.data || !author.data?.metadata) {
|
||||
if (!author.data || !author.data?.metadata || !author.data?.event ) {
|
||||
toast({
|
||||
title: 'Author not found',
|
||||
description: 'Could not find the author of this item.',
|
||||
@ -204,8 +203,8 @@ export function useZaps(
|
||||
return;
|
||||
}
|
||||
|
||||
const { lud16 } = author.data.metadata;
|
||||
if (!lud16) {
|
||||
const { lud06, lud16 } = author.data.metadata;
|
||||
if (!lud06 && !lud16) {
|
||||
toast({
|
||||
title: 'Lightning address not found',
|
||||
description: 'The author does not have a lightning address configured.',
|
||||
@ -216,7 +215,7 @@ export function useZaps(
|
||||
}
|
||||
|
||||
// Get zap endpoint using the old reliable method
|
||||
const zapEndpoint = await nip57.getZapEndpoint(author.data.event as Event);
|
||||
const zapEndpoint = await nip57.getZapEndpoint(author.data.event);
|
||||
if (!zapEndpoint) {
|
||||
toast({
|
||||
title: 'Zap endpoint not found',
|
||||
@ -227,30 +226,20 @@ export function useZaps(
|
||||
return;
|
||||
}
|
||||
|
||||
// Create zap request
|
||||
const zapAmount = amount * 1000; // convert to millisats
|
||||
const relays = [config.relayUrl];
|
||||
|
||||
// Create zap request (unsigned, like the old implementation)
|
||||
const zapRequest = nip57.makeZapRequest({
|
||||
profile: primaryTarget.pubkey,
|
||||
event: primaryTarget.id,
|
||||
event: primaryTarget,
|
||||
amount: zapAmount,
|
||||
relays,
|
||||
comment: comment,
|
||||
relays: [config.relayUrl],
|
||||
comment
|
||||
});
|
||||
|
||||
// Handle addressable events
|
||||
if (primaryTarget.kind >= 30000 && primaryTarget.kind < 40000) {
|
||||
const identifier = primaryTarget.tags.find((t) => t[0] === 'd')?.[1] || '';
|
||||
zapRequest.tags.push(["a", `${primaryTarget.kind}:${primaryTarget.pubkey}:${identifier}`]);
|
||||
zapRequest.tags = zapRequest.tags.filter(t => t[0] !== 'e');
|
||||
}
|
||||
|
||||
// Sign and publish the zap request
|
||||
publishEvent(zapRequest, {
|
||||
onSuccess: async (event) => {
|
||||
try {
|
||||
// Use the old fetch method - more reliable than LNURL validation
|
||||
const res = await fetch(`${zapEndpoint}?amount=${zapAmount}&nostr=${encodeURI(JSON.stringify(event))}`);
|
||||
const responseData = await res.json();
|
||||
|
||||
@ -266,38 +255,10 @@ export function useZaps(
|
||||
// Get the current active NWC connection dynamically
|
||||
const currentNWCConnection = getActiveConnection();
|
||||
|
||||
console.debug('Zap payment - detailed state check:', {
|
||||
// Raw state
|
||||
connectionsLength: connections.length,
|
||||
activeConnectionString: activeConnection ? activeConnection.substring(0, 50) + '...' : null,
|
||||
|
||||
// Connection details
|
||||
connections: connections.map(c => ({
|
||||
alias: c.alias,
|
||||
isConnected: c.isConnected,
|
||||
connectionString: c.connectionString.substring(0, 50) + '...'
|
||||
})),
|
||||
|
||||
// getActiveConnection result
|
||||
currentNWCConnection: currentNWCConnection ? {
|
||||
alias: currentNWCConnection.alias,
|
||||
isConnected: currentNWCConnection.isConnected,
|
||||
connectionString: currentNWCConnection.connectionString.substring(0, 50) + '...'
|
||||
} : null
|
||||
});
|
||||
|
||||
// Try NWC first if available and properly connected
|
||||
if (currentNWCConnection && currentNWCConnection.connectionString && currentNWCConnection.isConnected) {
|
||||
try {
|
||||
console.debug('Attempting NWC payment...', {
|
||||
amount,
|
||||
alias: currentNWCConnection.alias,
|
||||
invoiceLength: newInvoice.length
|
||||
});
|
||||
|
||||
const response = await sendPayment(currentNWCConnection, newInvoice);
|
||||
|
||||
console.debug('NWC payment successful:', { preimage: response.preimage });
|
||||
await sendPayment(currentNWCConnection, newInvoice);
|
||||
|
||||
// Clear states immediately on success
|
||||
setIsZapping(false);
|
||||
@ -322,10 +283,7 @@ export function useZaps(
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to WebLN or manual payment
|
||||
if (webln) {
|
||||
} else if (webln) { // Try WebLN next
|
||||
await webln.sendPayment(newInvoice);
|
||||
|
||||
// Clear states immediately on success
|
||||
@ -339,7 +297,7 @@ export function useZaps(
|
||||
|
||||
// Close dialog last to ensure clean state
|
||||
onZapSuccess?.();
|
||||
} else {
|
||||
} else { // Default - show QR code and manual Lightning URI
|
||||
setInvoice(newInvoice);
|
||||
setIsZapping(false);
|
||||
}
|
||||
@ -376,7 +334,6 @@ export function useZaps(
|
||||
};
|
||||
|
||||
return {
|
||||
// Legacy single-target API (for backward compatibility)
|
||||
zaps,
|
||||
...query,
|
||||
zap,
|
||||
@ -384,8 +341,6 @@ export function useZaps(
|
||||
invoice,
|
||||
setInvoice,
|
||||
parseNWCUri,
|
||||
|
||||
// New batch API
|
||||
zapData,
|
||||
isBatchMode,
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user