diff --git a/src/App.tsx b/src/App.tsx index d286f0f5..71276c2b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,7 @@ import { createAddressLoader } from 'applesauce-loaders/loaders' import Bookmarks from './components/Bookmarks' import Toast from './components/Toast' import { useToast } from './hooks/useToast' +import { ALL_RELAYS, PROFILE_RELAYS } from './config/relays' const DEFAULT_ARTICLE = import.meta.env.VITE_DEFAULT_ARTICLE_NADDR || 'naddr1qvzqqqr4gupzqmjxss3dld622uu8q25gywum9qtg4w4cv4064jmg20xsac2aam5nqqxnzd3cxqmrzv3exgmr2wfesgsmew' @@ -94,33 +95,16 @@ function App() { const pool = new RelayPool() - // Define relay URLs for bookmark fetching - const relayUrls = [ - 'wss://relay.damus.io', - 'wss://nos.lol', - 'wss://relay.nostr.band', - 'wss://relay.dergigi.com', - 'wss://wot.dergigi.com', - 'wss://relay.snort.social', - 'wss://relay.current.fyi', - 'wss://nostr-pub.wellorder.net' - ] - // Create a relay group for better event deduplication and management // This follows the applesauce-relay documentation pattern - // Note: We could use pool.group(relayUrls) for direct requests in the future - pool.group(relayUrls) - console.log('Created relay group with', relayUrls.length, 'relays') - console.log('Relay URLs:', relayUrls) + pool.group(ALL_RELAYS) + console.log('Created relay group with', ALL_RELAYS.length, 'relays (including local)') + console.log('Relay URLs:', ALL_RELAYS) // Attach address/replaceable loaders so ProfileModel can fetch profiles const addressLoader = createAddressLoader(pool, { eventStore: store, - lookupRelays: [ - 'wss://purplepag.es', - 'wss://relay.primal.net', - 'wss://relay.nostr.band' - ] + lookupRelays: PROFILE_RELAYS }) store.addressableLoader = addressLoader store.replaceableLoader = addressLoader diff --git a/src/config/relays.ts b/src/config/relays.ts new file mode 100644 index 00000000..b15672fb --- /dev/null +++ b/src/config/relays.ts @@ -0,0 +1,70 @@ +/** + * Centralized relay configuration + * All relay URLs used throughout the application + */ + +// Local relay URL (hardcoded for development) +export const LOCAL_RELAY = 'ws://localhost:7777' + +// Public relays for general use +export const PUBLIC_RELAYS = [ + 'wss://relay.damus.io', + 'wss://nos.lol', + 'wss://relay.nostr.band', + 'wss://relay.dergigi.com', + 'wss://wot.dergigi.com', + 'wss://relay.snort.social', + 'wss://relay.current.fyi', + 'wss://nostr-pub.wellorder.net' +] + +// Relays for profile lookups +export const PROFILE_RELAYS = [ + 'wss://purplepag.es', + 'wss://relay.primal.net', + 'wss://relay.nostr.band' +] + +// Relays for highlights (read and write) +export const HIGHLIGHT_RELAYS = [ + LOCAL_RELAY, + 'wss://relay.damus.io', + 'wss://nos.lol', + 'wss://relay.nostr.band', + 'wss://relay.snort.social', + 'wss://purplepag.es' +] + +// Relays for articles +export const ARTICLE_RELAYS = [ + LOCAL_RELAY, + 'wss://relay.damus.io', + 'wss://nos.lol', + 'wss://relay.nostr.band', + 'wss://relay.primal.net' +] + +// Relays for settings (read and write) +export const SETTINGS_RELAYS = [ + LOCAL_RELAY, + 'wss://relay.damus.io', + 'wss://nos.lol', + 'wss://relay.nostr.band', + 'wss://relay.dergigi.com', + 'wss://wot.dergigi.com' +] + +// All relays including local (for general operations and relay pool initialization) +export const ALL_RELAYS = [LOCAL_RELAY, ...PUBLIC_RELAYS] + +// All write relays (where we publish events) +export const WRITE_RELAYS = [ + LOCAL_RELAY, + 'wss://relay.damus.io', + 'wss://nos.lol', + 'wss://relay.nostr.band', + 'wss://relay.snort.social', + 'wss://purplepag.es', + 'wss://relay.dergigi.com' +] + diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts index d4f49c80..3c84b7bc 100644 --- a/src/hooks/useSettings.ts +++ b/src/hooks/useSettings.ts @@ -5,11 +5,7 @@ import { EventFactory } from 'applesauce-factory' import { AccountManager } from 'applesauce-accounts' import { UserSettings, loadSettings, saveSettings, watchSettings } from '../services/settingsService' import { loadFont, getFontFamily } from '../utils/fontLoader' - -const RELAY_URLS = [ - 'wss://relay.damus.io', 'wss://nos.lol', 'wss://relay.nostr.band', - 'wss://relay.dergigi.com', 'wss://wot.dergigi.com' -] +import { SETTINGS_RELAYS } from '../config/relays' interface UseSettingsParams { relayPool: RelayPool | null @@ -29,7 +25,7 @@ export function useSettings({ relayPool, eventStore, pubkey, accountManager }: U const loadAndWatch = async () => { try { - const loadedSettings = await loadSettings(relayPool, eventStore, pubkey, RELAY_URLS) + const loadedSettings = await loadSettings(relayPool, eventStore, pubkey, SETTINGS_RELAYS) if (loadedSettings) setSettings(loadedSettings) } catch (err) { console.error('Failed to load settings:', err) @@ -65,7 +61,7 @@ export function useSettings({ relayPool, eventStore, pubkey, accountManager }: U const fullAccount = accountManager.getActive() if (!fullAccount) throw new Error('No active account') const factory = new EventFactory({ signer: fullAccount }) - await saveSettings(relayPool, eventStore, factory, newSettings, RELAY_URLS) + await saveSettings(relayPool, eventStore, factory, newSettings, SETTINGS_RELAYS) setSettings(newSettings) setToastType('success') setToastMessage('Settings saved') diff --git a/src/services/articleService.ts b/src/services/articleService.ts index 7e8b95ee..a555f767 100644 --- a/src/services/articleService.ts +++ b/src/services/articleService.ts @@ -9,6 +9,7 @@ import { getArticlePublished, getArticleSummary } from 'applesauce-core/helpers' +import { ARTICLE_RELAYS } from '../config/relays' export interface ArticleContent { title: string @@ -95,15 +96,10 @@ export async function fetchArticleByNaddr( const pointer = decoded.data as AddressPointer - // Define relays to query + // Define relays to query - prefer relays from naddr, fallback to configured relays (including local) const relays = pointer.relays && pointer.relays.length > 0 ? pointer.relays - : [ - 'wss://relay.damus.io', - 'wss://nos.lol', - 'wss://relay.nostr.band', - 'wss://relay.primal.net' - ] + : ARTICLE_RELAYS // Fetch the article event const filter = { diff --git a/src/services/highlightCreationService.ts b/src/services/highlightCreationService.ts index 452e8fba..dde97cfb 100644 --- a/src/services/highlightCreationService.ts +++ b/src/services/highlightCreationService.ts @@ -4,6 +4,7 @@ import { RelayPool } from 'applesauce-relay' import { IAccount } from 'applesauce-accounts' import { AddressPointer } from 'nostr-tools/nip19' import { NostrEvent } from 'nostr-tools' +import { WRITE_RELAYS } from '../config/relays' /** * Creates and publishes a highlight event (NIP-84) @@ -36,18 +37,10 @@ export async function createHighlight( // Sign the event const signedEvent = await factory.sign(highlightEvent) - // Publish to relays - const relayUrls = [ - 'wss://relay.damus.io', - 'wss://nos.lol', - 'wss://relay.nostr.band', - 'wss://relay.snort.social', - 'wss://purplepag.es' - ] - - await relayPool.publish(relayUrls, signedEvent) + // Publish to relays (including local relay) + await relayPool.publish(WRITE_RELAYS, signedEvent) - console.log('✅ Highlight published:', signedEvent) + console.log('✅ Highlight published to', WRITE_RELAYS.length, 'relays (including local):', signedEvent) } /** diff --git a/src/services/highlightService.ts b/src/services/highlightService.ts index 878660a3..f65f34ed 100644 --- a/src/services/highlightService.ts +++ b/src/services/highlightService.ts @@ -11,6 +11,7 @@ import { getHighlightAttributions } from 'applesauce-core/helpers' import { Highlight } from '../types/highlights' +import { HIGHLIGHT_RELAYS } from '../config/relays' /** * Deduplicate highlight events by ID @@ -42,18 +43,9 @@ export const fetchHighlightsForArticle = async ( onHighlight?: (highlight: Highlight) => void ): Promise => { try { - // Use well-known relays for highlights even if user isn't logged in - const highlightRelays = [ - 'wss://relay.damus.io', - 'wss://nos.lol', - 'wss://relay.nostr.band', - 'wss://relay.snort.social', - 'wss://purplepag.es' - ] - console.log('🔍 Fetching highlights (kind 9802) for article:', articleCoordinate) console.log('🔍 Event ID:', eventId || 'none') - console.log('🔍 From relays:', highlightRelays) + console.log('🔍 From relays (including local):', HIGHLIGHT_RELAYS) const seenIds = new Set() const processEvent = (event: NostrEvent): Highlight | null => { @@ -89,7 +81,7 @@ export const fetchHighlightsForArticle = async ( // Query for highlights that reference this article via the 'a' tag const aTagEvents = await lastValueFrom( relayPool - .req(highlightRelays, { kinds: [9802], '#a': [articleCoordinate] }) + .req(HIGHLIGHT_RELAYS, { kinds: [9802], '#a': [articleCoordinate] }) .pipe( onlyEvents(), tap((event: NostrEvent) => { @@ -111,7 +103,7 @@ export const fetchHighlightsForArticle = async ( if (eventId) { eTagEvents = await lastValueFrom( relayPool - .req(highlightRelays, { kinds: [9802], '#e': [eventId] }) + .req(HIGHLIGHT_RELAYS, { kinds: [9802], '#e': [eventId] }) .pipe( onlyEvents(), tap((event: NostrEvent) => {