From 727064aafb62d169123950b68cf3b8377077f88a Mon Sep 17 00:00:00 2001 From: n <n> Date: Sat, 12 Apr 2025 21:45:22 +0100 Subject: [PATCH] fix: stuff --- client/package-lock.json | 7 + client/src/auth-manager.ts | 6 +- client/src/billboard.ts | 22 +- client/src/client-event-handler.ts | 37 ++++ client/src/client.ts | 93 +++++++- client/src/components/Nostr21121Creator.ts | 2 +- client/src/converter.ts | 20 +- client/src/services/AuthenticationService.ts | 219 +++++++++++++++++-- client/src/services/Nostr21121Service.ts | 2 +- client/src/services/Nostr31120Service.ts | 81 +++++-- package-lock.json | 46 +--- 11 files changed, 430 insertions(+), 105 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 1ed4e53..f1ae0bc 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "jsqr": "^1.4.0", "nostr-login": "^1.7.11", "nostr-tools": "^2.12.0", "qrcode": "^1.5.4", @@ -5311,6 +5312,12 @@ "json5": "lib/cli.js" } }, + "node_modules/jsqr": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz", + "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==", + "license": "Apache-2.0" + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/client/src/auth-manager.ts b/client/src/auth-manager.ts index 4c45377..a0d0afa 100644 --- a/client/src/auth-manager.ts +++ b/client/src/auth-manager.ts @@ -93,12 +93,16 @@ export async function loginWithNostrLogin(): Promise<string | null> { executePostAuthQueue(); return result.pubkey; + } else if (result.error) { + // If we have a specific error message from the authentication service + console.error("Authentication failed with message:", result.error); + throw new Error(result.error); } return null; } catch (error) { console.error("Error using Nostr login:", error); - return null; + throw error; // Rethrow to allow the caller to handle specific error messages } } diff --git a/client/src/billboard.ts b/client/src/billboard.ts index 9f39e61..6089b69 100644 --- a/client/src/billboard.ts +++ b/client/src/billboard.ts @@ -52,11 +52,27 @@ document.addEventListener('DOMContentLoaded', () => { updateUIBasedOnAuth(); } else { console.log('Login attempt failed, showing error'); - alert('Login failed. Please make sure you have a Nostr extension installed (like Alby or nos2x).'); + alert('Login failed. Authentication with nostr-login was unsuccessful. Please check the console for error details.'); } } catch (error) { console.error('Authentication error:', error); - alert(`Authentication error: ${error instanceof Error ? error.message : 'Unknown error'}`); + + let errorMessage = 'Authentication error'; + + if (error instanceof Error) { + if (error.message.includes('Rejected') || error.message.includes('Cancelled')) { + errorMessage = 'Login was cancelled. Please try again when you are ready to authenticate.'; + } else { + errorMessage = error.message; + } + } else if (error && typeof error === 'object' && 'error' in error) { + const errorValue = error.error; + errorMessage = typeof errorValue === 'string' ? errorValue : errorMessage; + } else { + errorMessage = String(error || 'Unknown error'); + } + + alert(errorMessage); } }); } @@ -271,7 +287,7 @@ async function handleConnectRelay(): Promise<void> { updateUIBasedOnAuth(); updateRelayStatus('Authentication successful. Connecting...', 'connecting'); } else { - updateRelayStatus('Authentication failed. Please try again or install a Nostr extension like Alby or nos2x.', 'error'); + updateRelayStatus('Authentication failed. Please try again. nostr-login authentication was unsuccessful.', 'error'); return; } } catch (error) { diff --git a/client/src/client-event-handler.ts b/client/src/client-event-handler.ts index 6911b76..1b5a691 100644 --- a/client/src/client-event-handler.ts +++ b/client/src/client-event-handler.ts @@ -17,6 +17,9 @@ import type { NostrRelayService } from './services/NostrRelayService'; // Create a singleton instance of the client event store const clientEventStore = new ClientEventStore(); +// Track events that have been published to avoid duplicates +const publishedEvents = new Set<string>(); + // The table UI component (initialized in setup) let clientEventsTable: ClientEventsTable | null = null; @@ -216,12 +219,46 @@ export function trackOutgoingEvent(event: NostrEvent): string | null { console.warn(`Expected KIND 21120 event, got ${event.kind}`); } + // Check if this event is already tracked + const existingEvent = clientEventStore.getEvent(event.id); + if (existingEvent) { + console.log(`Event ${event.id} is already being tracked, not adding again`); + return event.id; + } + + // Check if this event has already been published + if (publishedEvents.has(event.id)) { + console.log(`Event ${event.id} has already been published, not adding again`); + return event.id; + } + // Add to the store const eventId = clientEventStore.addOutgoingEvent(event); console.log(`Tracked outgoing event: ${eventId}`); return eventId; } +/** + * Mark an event as published to prevent duplicate publishing + * @param eventId The ID of the event that was published + */ +export function markEventAsPublished(eventId: string): void { + if (!eventId) return; + + // Add to the set of published events + publishedEvents.add(eventId); + console.log(`Marked event ${eventId} as published`); +} + +/** + * Check if an event has already been published + * @param eventId The ID of the event to check + * @returns True if the event has been published, false otherwise + */ +export function isEventPublished(eventId: string): boolean { + return publishedEvents.has(eventId); +} + /** * Handle a pending 21120 event before it's published * @param event The event being prepared diff --git a/client/src/client.ts b/client/src/client.ts index 5a88b2f..f7dd135 100644 --- a/client/src/client.ts +++ b/client/src/client.ts @@ -41,7 +41,9 @@ import { initClientEventHandler, trackOutgoingEvent, handleIncomingResponse, - reconnectRelayService + reconnectRelayService, + markEventAsPublished, + isEventPublished } from './client-event-handler'; import type { NostrEvent } from './converter'; // Import functions from internal modules @@ -609,10 +611,35 @@ function initNostrLogin(): void { authManager.setAuthenticated(true, pubkey); } }).catch(err => { - console.warn("Not currently connected to Nostr extension:", err); + console.warn("Not currently connected to Nostr provider:", err); }); } else { - console.warn("Nostr extension not available"); + console.warn("Nostr provider not available. Using nostr-login if available."); + + // Try to use nostr-login library if available + if (NostrLogin) { + try { + console.log("Using nostr-login in initNostrLogin"); + const nostrLogin = new NostrLogin(); + + nostrLogin.getPublicKey().then((pubkey: string) => { + if (pubkey) { + console.log(`Found pubkey from nostr-login: ${pubkey.slice(0, 8)}...`); + // Update UI to show pubkey + updateClientPubkeyDisplay(pubkey); + + // Update auth state in the service + authManager.setAuthenticated(true, pubkey); + } + }).catch((err: Error) => { + console.warn("Not currently connected to nostr-login:", err); + }); + } catch (nostrLoginError) { + console.error('nostr-login error:', nostrLoginError); + } + } else { + console.warn("No Nostr provider available"); + } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); @@ -651,11 +678,9 @@ async function ensureAuthenticated(): Promise<boolean> { return true; } - // Not authenticated, check if extension is available - if (!window.nostr) { - console.warn("Nostr extension not available"); - return false; - } + // Not authenticated, try to use nostr-login or extension + // We no longer need to check window.nostr because loginWithNostrLogin handles that + console.log("No active authentication, attempting to authenticate with nostr-login..."); try { // Try to get the user's public key @@ -698,6 +723,12 @@ async function handlePublishEvent(): Promise<void> { showLoading(publishResultDiv, 'Publishing to relay...'); try { + // Check if this event has already been published + if (event.id && isEventPublished(event.id)) { + showSuccess(publishResultDiv, "Event was already published, not sending duplicate"); + return; + } + // Track the event before publishing console.log('Tracking outgoing event:', event.id); trackOutgoingEvent(event); @@ -705,6 +736,12 @@ async function handlePublishEvent(): Promise<void> { // Publish the event console.log('Publishing event to relay:', relayUrl); const result = await publishToRelay(event, relayUrl); + + // Mark the event as published to prevent duplicates + if (event.id) { + markEventAsPublished(event.id); + } + showSuccess(publishResultDiv, result); // Force reconnect to ensure we're subscribed for the response @@ -782,6 +819,12 @@ async function handlePublishEvent(): Promise<void> { publishResultDiv.innerHTML += '<br><span>Attempting to publish...</span>'; try { + // Check if this event has already been published + if (event.id && isEventPublished(event.id)) { + showSuccess(publishResultDiv, "Event was already published, not sending duplicate"); + return; + } + // Track the event in our client store console.log('Tracking outgoing event:', event.id); trackOutgoingEvent(event); @@ -789,6 +832,12 @@ async function handlePublishEvent(): Promise<void> { // Publish the event console.log('Publishing event to relay:', relayUrl); const result = await publishToRelay(event, relayUrl); + + // Mark the event as published to prevent duplicates + if (event.id) { + markEventAsPublished(event.id); + } + showSuccess(publishResultDiv, result); // Force reconnect to ensure we're subscribed for the response @@ -1595,12 +1644,32 @@ document.addEventListener('DOMContentLoaded', function(): void { // Try to get pubkey again after DOM is ready if (window.nostr) { - window.nostr.getPublicKey().then(pubkey => { - console.log(`DOM ready: Retrieved pubkey: ${pubkey.slice(0, 8)}...`); + window.nostr.getPublicKey().then((pubkey: string) => { + console.log(`DOM ready: Retrieved pubkey from extension: ${pubkey.slice(0, 8)}...`); localStorage.setItem('userPublicKey', pubkey); - }).catch(err => { - console.warn("DOM ready: Failed to get pubkey:", err); + }).catch((err: Error) => { + console.warn("DOM ready: Failed to get pubkey from extension:", err); }); + } else if (NostrLogin) { + // Try to use nostr-login if window.nostr is not available + try { + console.log("DOM ready: Using nostr-login to get pubkey"); + const nostrLogin = new NostrLogin(); + + nostrLogin.getPublicKey().then((pubkey: string) => { + if (pubkey) { + console.log(`DOM ready: Retrieved pubkey from nostr-login: ${pubkey.slice(0, 8)}...`); + localStorage.setItem('userPublicKey', pubkey); + updateClientPubkeyDisplay(pubkey); + } + }).catch((err: Error) => { + console.warn("DOM ready: Failed to get pubkey from nostr-login:", err); + }); + } catch (nostrLoginError) { + console.error('DOM ready: nostr-login error:', nostrLoginError); + } + } else { + console.warn("DOM ready: No Nostr provider available"); } // Set default HTTP request diff --git a/client/src/components/Nostr21121Creator.ts b/client/src/components/Nostr21121Creator.ts index ad3a36c..d02e80b 100644 --- a/client/src/components/Nostr21121Creator.ts +++ b/client/src/components/Nostr21121Creator.ts @@ -190,7 +190,7 @@ export class Nostr21121Creator { // Always add reference to the request event if (requestEvent.id) { - tags.push(['e', requestEvent.id, '', 'reply']); + tags.push(['e', requestEvent.id]); } // Add kind reference diff --git a/client/src/converter.ts b/client/src/converter.ts index 9427a5c..0ccfda9 100644 --- a/client/src/converter.ts +++ b/client/src/converter.ts @@ -438,6 +438,12 @@ if (publishRelayInput) { // Import the tracking function from client-event-handler import('./client-event-handler').then(module => { + // Check if this event is already published + if (signedEvent.id && module.isEventPublished(signedEvent.id)) { + showSuccess(publishResult, "Event was already published, not sending duplicate"); + return; + } + // Track the event before publishing try { module.trackOutgoingEvent(signedEvent); @@ -449,6 +455,10 @@ if (publishRelayInput) { // Publish the event using the publishToRelay function publishToRelay(signedEvent, relayUrl) .then((result: string) => { + // Mark the event as published to prevent duplicates + if (signedEvent.id) { + module.markEventAsPublished(signedEvent.id); + } showSuccess(publishResult, result); }) .catch((error: Error) => { @@ -685,16 +695,10 @@ if (publishRelayInput) { // Initialize event listeners when the DOM is fully loaded document.addEventListener('DOMContentLoaded', () => { - // Set up the click event handler without any automatic encryption - const convertButton = document.getElementById('convertButton'); + // The Convert button event listener is already set in client.ts + // so we don't set it here to avoid duplicate calls and double events const publishButton = document.getElementById('publishButton'); - if (convertButton) { - convertButton.addEventListener('click', (): void => { - void displayConvertedEvent(); - }); - } - // Add a handler for the publish button to check if an event is available if (publishButton) { publishButton.addEventListener('click', (): void => { diff --git a/client/src/services/AuthenticationService.ts b/client/src/services/AuthenticationService.ts index 2250311..527d928 100644 --- a/client/src/services/AuthenticationService.ts +++ b/client/src/services/AuthenticationService.ts @@ -4,9 +4,9 @@ * Stateless authentication service that directly uses the Nostr extension. * Removed all localStorage and session dependencies. */ - import type * as nostrTools from 'nostr-tools'; + /** * Interface for authentication operation results */ @@ -64,32 +64,122 @@ export class AuthenticationService { */ public async authenticate(): Promise<AuthResult> { try { - // Check if a Nostr extension is available - if (!window.nostr) { - return { - success: false, - error: 'Nostr extension not found. Please install Alby or nos2x.' - }; + console.log("AuthenticationService: Using nostr-login for authentication"); + + // Try to use nostr-login library if available + const nostrLoginModule = typeof require !== 'undefined' ? require('nostr-login') : null; + + if (nostrLoginModule && nostrLoginModule.init) { + try { + console.log("nostr-login loaded, initializing..."); + + // Initialize nostr-login which sets up window.nostr + await nostrLoginModule.init({ + // Options for nostr-login + darkMode: document.body.getAttribute('data-theme') === 'dark', + noBanner: true, // Don't show the banner + }); + + console.log("nostr-login initialized, window.nostr should be available"); + + // Check if window.nostr was successfully set up + if (window.nostr) { + console.log("Attempting to get pubkey through window.nostr..."); + // Get pubkey through window.nostr + const pubkey = await window.nostr.getPublicKey(); + console.log("window.nostr.getPublicKey returned:", pubkey); + + if (pubkey) { + console.log(`Authentication successful with pubkey: ${pubkey.substring(0, 8)}...`); + // Cache the pubkey in memory + this.cachedPubkey = pubkey; + + // Notify listeners of authentication change + this.notifyAuthStateChanged(true, pubkey); + + // Set the global nostrPubkey for backwards compatibility with existing code + if (window) { + window.nostrPubkey = pubkey; + } + + return { + success: true, + pubkey + }; + } + } else { + console.error('nostr-login initialized but window.nostr is not available'); + } + } catch (nostrLoginError) { + console.error('nostr-login error:', nostrLoginError); + console.error('nostr-login stack:', nostrLoginError instanceof Error ? nostrLoginError.stack : 'No stack available'); + console.error('nostr-login error details:', JSON.stringify(nostrLoginError)); + + // Check for specific error types + const errorMessage = nostrLoginError instanceof Error ? nostrLoginError.message : String(nostrLoginError); + + if (errorMessage.includes('Already started')) { + console.warn('nostr-login was already initialized, this is usually not a problem'); + // Continue with window.nostr if it's available despite the "Already started" error + if (window.nostr) { + try { + console.log("nostr-login already initialized, using window.nostr directly"); + const pubkey = await window.nostr.getPublicKey(); + if (pubkey) { + console.log(`Authentication successful with pubkey: ${pubkey.substring(0, 8)}...`); + this.cachedPubkey = pubkey; + this.notifyAuthStateChanged(true, pubkey); + if (window) { + window.nostrPubkey = pubkey; + } + return { + success: true, + pubkey + }; + } + } catch (directNostrError) { + console.error('Direct window.nostr error:', directNostrError); + } + } + } else if (errorMessage.includes('Rejected by user') || errorMessage.includes('Cancelled')) { + console.warn('User rejected or cancelled the nostr-login authentication'); + return { + success: false, + error: 'Authentication was cancelled by the user. Please try again.' + }; + } + // Fall back to window.nostr if NostrLogin fails for other reasons + } } - // Directly request the public key from the Nostr extension - const pubkey = await window.nostr.getPublicKey(); - - if (pubkey) { - // Cache the pubkey in memory - this.cachedPubkey = pubkey; + // Fall back to window.nostr if NostrLogin is not available + if (window.nostr) { + console.log("Falling back to window.nostr"); - // Notify listeners of authentication change - this.notifyAuthStateChanged(true, pubkey); + // Directly request the public key from the Nostr extension + const pubkey = await window.nostr.getPublicKey(); - // Set the global nostrPubkey for backwards compatibility with existing code - if (window) { - window.nostrPubkey = pubkey; + if (pubkey) { + // Cache the pubkey in memory + this.cachedPubkey = pubkey; + + // Notify listeners of authentication change + this.notifyAuthStateChanged(true, pubkey); + + // Set the global nostrPubkey for backwards compatibility with existing code + if (window) { + window.nostrPubkey = pubkey; + } + + return { + success: true, + pubkey + }; } - + } else { return { - success: true, - pubkey + success: false, + error: 'Authentication failed. No Nostr provider found.' }; } @@ -119,9 +209,52 @@ export class AuthenticationService { return true; } - // No cached pubkey, try to get it from the extension + // Try to use nostr-login library if available + const nostrLoginModule = typeof require !== 'undefined' ? require('nostr-login') : null; + + if (nostrLoginModule && nostrLoginModule.init) { + try { + console.log("Using nostr-login to check authentication"); + + // Initialize nostr-login which sets up window.nostr + await nostrLoginModule.init({ + darkMode: document.body.getAttribute('data-theme') === 'dark', + noBanner: true, // Don't show the banner + }); + + console.log("nostr-login initialized for auth check, window.nostr should be available"); + + // Check if window.nostr was successfully set up + if (window.nostr) { + console.log("Attempting to get pubkey through window.nostr for auth check..."); + // Get pubkey through window.nostr + const pubkey = await window.nostr.getPublicKey(); + console.log("window.nostr.getPublicKey returned for auth check:", pubkey); + + if (pubkey) { + console.log(`Authentication check successful with pubkey: ${pubkey.substring(0, 8)}...`); + this.cachedPubkey = pubkey; + // Set the global nostrPubkey for backwards compatibility + if (window) { + window.nostrPubkey = pubkey; + } + return true; + } + } else { + console.error('nostr-login initialized but window.nostr is not available for auth check'); + } + } catch (nostrLoginError) { + console.error('Failed to get pubkey from nostr-login:', nostrLoginError); + console.error('nostr-login stack:', nostrLoginError instanceof Error ? nostrLoginError.stack : 'No stack available'); + console.error('nostr-login error details:', JSON.stringify(nostrLoginError)); + // Fall back to window.nostr if NostrLogin fails + } + } + + // Fall back to window.nostr if NostrLogin is not available if (window.nostr) { try { + console.log("Falling back to window.nostr to check authentication"); const pubkey = await window.nostr.getPublicKey(); if (pubkey) { this.cachedPubkey = pubkey; @@ -163,12 +296,52 @@ export class AuthenticationService { public async getPubkey(): Promise<string | null> { // If we have a cached pubkey, return it if (this.cachedPubkey) { + console.log(`Using cached pubkey: ${this.cachedPubkey.substring(0, 8)}...`); return this.cachedPubkey; } - // Try to get pubkey from extension + // Try to use nostr-login library if available + const nostrLoginModule = typeof require !== 'undefined' ? require('nostr-login') : null; + + if (nostrLoginModule && nostrLoginModule.init) { + try { + console.log("Using nostr-login to get pubkey"); + + // Initialize nostr-login which sets up window.nostr + await nostrLoginModule.init({ + darkMode: document.body.getAttribute('data-theme') === 'dark', + noBanner: true, // Don't show the banner + }); + + console.log("nostr-login initialized in getPubkey, window.nostr should be available"); + + // Check if window.nostr was successfully set up + if (window.nostr) { + console.log("Attempting to get pubkey through window.nostr in getPubkey..."); + // Get pubkey through window.nostr + const pubkey = await window.nostr.getPublicKey(); + console.log("window.nostr.getPublicKey returned in getPubkey:", pubkey); + + if (pubkey) { + console.log(`getPubkey successful with: ${pubkey.substring(0, 8)}...`); + this.cachedPubkey = pubkey; + return pubkey; + } + } else { + console.error('nostr-login initialized but window.nostr is not available in getPubkey'); + } + } catch (nostrLoginError) { + console.error('Failed to get pubkey from nostr-login:', nostrLoginError); + console.error('NostrLogin stack:', nostrLoginError instanceof Error ? nostrLoginError.stack : 'No stack available'); + console.error('NostrLogin error details:', JSON.stringify(nostrLoginError)); + // Fall back to window.nostr if NostrLogin fails + } + } + + // Fall back to window.nostr if NostrLogin is not available try { if (window.nostr) { + console.log("Falling back to window.nostr to get pubkey"); const pubkey = await window.nostr.getPublicKey(); if (pubkey) { this.cachedPubkey = pubkey; diff --git a/client/src/services/Nostr21121Service.ts b/client/src/services/Nostr21121Service.ts index d6ed409..3fa0898 100644 --- a/client/src/services/Nostr21121Service.ts +++ b/client/src/services/Nostr21121Service.ts @@ -96,7 +96,7 @@ export class Nostr21121Service { // Always add reference to the request event if (requestEvent.id) { - tags.push(['e', requestEvent.id, '']); + tags.push(['e', requestEvent.id]); } // Get the pubkey of the request creator (client) for encryption diff --git a/client/src/services/Nostr31120Service.ts b/client/src/services/Nostr31120Service.ts index 6627b6b..1ba499e 100644 --- a/client/src/services/Nostr31120Service.ts +++ b/client/src/services/Nostr31120Service.ts @@ -192,21 +192,41 @@ export class Nostr31120Service { } } - // Check if window.nostr (Nostr browser extension) is available - if (!window.nostr) { - throw new Error('No Nostr browser extension found. Please install a NIP-07 compatible extension.'); + // Try to use nostr-login library if available + const NostrLogin = typeof require !== 'undefined' ? require('nostr-login') : null; + let nostrProvider = null; + + // Try nostr-login first + if (NostrLogin) { + try { + console.log("Using nostr-login in Nostr31120Service"); + nostrProvider = new NostrLogin(); + } catch (nostrLoginError) { + console.error('NostrLogin error:', nostrLoginError); + // Fall back to window.nostr + } } - // Get user's public key using the extension + // Fall back to window.nostr if nostr-login is not available + if (!nostrProvider && window.nostr) { + nostrProvider = window.nostr; + } + + // Check if we have a Nostr provider + if (!nostrProvider) { + throw new Error('No Nostr provider found. Authentication with nostr-login was unsuccessful.'); + } + + // Get user's public key using the Nostr provider let userPubkey: string; try { - userPubkey = await window.nostr!.getPublicKey(); + userPubkey = await nostrProvider.getPublicKey(); if (!userPubkey) { - throw new Error('Failed to get public key from Nostr extension'); + throw new Error('Failed to get public key from Nostr provider'); } } catch (error) { - console.error('Error getting public key from Nostr extension:', error); - throw new Error('Failed to get your public key. Please make sure your Nostr extension is working.'); + console.error('Error getting public key from Nostr provider:', error); + throw new Error('Failed to get your public key. Authentication with nostr-login was unsuccessful.'); } // Generate or use a provided server pubkey @@ -269,14 +289,14 @@ export class Nostr31120Service { content: content || 'HTTP-over-Nostr server', }; - // Sign the event using the browser extension + // Sign the event using the Nostr provider let signedEvent: NostrEvent; try { - signedEvent = await window.nostr!.signEvent(unsignedEvent); - console.log('Event signed successfully with Nostr extension'); + signedEvent = await nostrProvider.signEvent(unsignedEvent); + console.log('Event signed successfully with Nostr provider'); } catch (error) { - console.error('Error signing event with Nostr extension:', error); - throw new Error('Failed to sign the event with your Nostr extension'); + console.error('Error signing event with Nostr provider:', error); + throw new Error('Failed to sign the event. Authentication with nostr-login was unsuccessful.'); } // Publish to relay @@ -362,14 +382,39 @@ export class Nostr31120Service { content: content || 'HTTP-over-Nostr server', }; - // Sign the event using the browser extension + // Sign the event using the Nostr provider let signedEvent: NostrEvent; try { - signedEvent = await window.nostr!.signEvent(unsignedEvent); - console.log('Event signed successfully with Nostr extension'); + // Try to use nostr-login library if available + const NostrLogin = typeof require !== 'undefined' ? require('nostr-login') : null; + let nostrProvider = null; + + // Try nostr-login first + if (NostrLogin) { + try { + console.log("Using nostr-login in processEventWithServerKey"); + nostrProvider = new NostrLogin(); + } catch (nostrLoginError) { + console.error('NostrLogin error:', nostrLoginError); + // Fall back to window.nostr + } + } + + // Fall back to window.nostr if nostr-login is not available + if (!nostrProvider && window.nostr) { + nostrProvider = window.nostr; + } + + // Check if we have a Nostr provider + if (!nostrProvider) { + throw new Error('No Nostr provider found. Authentication with nostr-login was unsuccessful.'); + } + + signedEvent = await nostrProvider.signEvent(unsignedEvent); + console.log('Event signed successfully with Nostr provider'); } catch (error) { - console.error('Error signing event with Nostr extension:', error); - throw new Error('Failed to sign the event with your Nostr extension'); + console.error('Error signing event with Nostr provider:', error); + throw new Error('Failed to sign the event. Authentication with nostr-login was unsuccessful.'); } // Publish to relay diff --git a/package-lock.json b/package-lock.json index 1941a34..6d2095e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", "engines": { "node": ">=8" } @@ -26,7 +25,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -41,7 +39,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "license": "MIT", "engines": { "node": ">=6" } @@ -50,7 +47,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -61,7 +57,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -72,14 +67,12 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -87,20 +80,17 @@ "node_modules/dijkstrajs": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", - "license": "MIT" + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -113,7 +103,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -122,7 +111,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", "engines": { "node": ">=8" } @@ -130,14 +118,12 @@ "node_modules/jsqr": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz", - "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==", - "license": "Apache-2.0" + "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==" }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -149,7 +135,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -164,7 +149,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -176,7 +160,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "license": "MIT", "engines": { "node": ">=6" } @@ -185,7 +168,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "license": "MIT", "engines": { "node": ">=8" } @@ -194,7 +176,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "license": "MIT", "engines": { "node": ">=10.13.0" } @@ -203,7 +184,6 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", - "license": "MIT", "dependencies": { "dijkstrajs": "^1.0.1", "pngjs": "^5.0.0", @@ -220,7 +200,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -228,20 +207,17 @@ "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "license": "ISC" + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -255,7 +231,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -266,14 +241,12 @@ "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "license": "ISC" + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" }, "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -286,14 +259,12 @@ "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "license": "ISC" + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -315,7 +286,6 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0"