From e6607509c5224d9271752283e7db3da223c84a2f Mon Sep 17 00:00:00 2001 From: padreug Date: Sat, 2 Aug 2025 17:11:23 +0200 Subject: [PATCH] refactor: Update useMarket composable to utilize fetchEvents method and improve subscription handling - Replace direct calls to fetchNotes with the new fetchEvents method in useMarket.ts for better event retrieval. - Simplify event fetching logic by removing unnecessary filters and enhancing clarity. - Implement individual relay subscriptions for market updates, allowing for more efficient event handling and cleanup. --- src/composables/useMarket.ts | 43 ++++++++++++++---------- src/lib/nostr/client.ts | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 18 deletions(-) diff --git a/src/composables/useMarket.ts b/src/composables/useMarket.ts index d357f75..5cfb48d 100644 --- a/src/composables/useMarket.ts +++ b/src/composables/useMarket.ts @@ -2,6 +2,7 @@ import { ref, computed, readonly } from 'vue' import { useNostrStore } from '@/stores/nostr' import { useMarketStore, type Market, type Stall, type Product } from '@/stores/market' import { config } from '@/lib/config' +import { nip19 } from 'nostr-tools' // Nostr event kinds for market functionality const MARKET_EVENT_KINDS = { @@ -26,7 +27,7 @@ export function useMarket() { error.value = null // Decode naddr - const { type, data } = window.NostrTools.nip19.decode(naddr) + const { type, data } = nip19.decode(naddr) if (type !== 'naddr' || data.kind !== MARKET_EVENT_KINDS.MARKET) { throw new Error('Invalid market naddr') } @@ -70,13 +71,11 @@ export function useMarket() { const client = nostrStore.getClient() // Fetch market configuration event - const filters = [{ + const events = await client.fetchEvents({ kinds: [MARKET_EVENT_KINDS.MARKET], authors: [marketData.pubkey], '#d': [marketData.d] - }] - - const events = await client.fetchNotes({ filters }) + }) if (events.length > 0) { const marketEvent = events[0] @@ -103,12 +102,10 @@ export function useMarket() { const client = nostrStore.getClient() // Fetch stall events for this market - const filters = [{ + const events = await client.fetchEvents({ kinds: [MARKET_EVENT_KINDS.STALL], authors: [marketPubkey] - }] - - const events = await client.fetchNotes({ filters }) + }) events.forEach(event => { try { @@ -145,12 +142,10 @@ export function useMarket() { if (stallPubkeys.length === 0) return // Fetch product events from all stalls - const filters = [{ + const events = await client.fetchEvents({ kinds: [MARKET_EVENT_KINDS.PRODUCT], authors: stallPubkeys - }] - - const events = await client.fetchNotes({ filters }) + }) events.forEach(event => { try { @@ -198,12 +193,24 @@ export function useMarket() { } ] - const unsubscribe = client.subscribeToNotes((event) => { - handleMarketEvent(event) - }, filters) + // Subscribe to each relay individually + const unsubscribes = config.market.supportedRelays.map(relay => { + const sub = client.poolInstance.subscribeMany( + [relay], + filters, + { + onevent: (event: any) => { + handleMarketEvent(event) + } + } + ) + return () => sub.close() + }) - // Store unsubscribe function for cleanup - return unsubscribe + // Return a function that unsubscribes from all relays + return () => { + unsubscribes.forEach(unsub => unsub()) + } } catch (err) { console.error('Error subscribing to market updates:', err) diff --git a/src/lib/nostr/client.ts b/src/lib/nostr/client.ts index c38e3e5..4369407 100644 --- a/src/lib/nostr/client.ts +++ b/src/lib/nostr/client.ts @@ -29,6 +29,10 @@ export class NostrClient { return this._isConnected } + get poolInstance(): SimplePool { + return this.pool + } + async connect(): Promise { try { // Try to connect to at least one relay @@ -205,6 +209,67 @@ export class NostrClient { } } + /** + * Fetch events by kind + */ + async fetchEvents(options: { + kinds: number[] + authors?: string[] + limit?: number + since?: number + until?: number + '#d'?: string[] + } = {}): Promise { + const { + kinds, + authors, + limit = 100, + since, + until, + '#d': dTags + } = options + + const filters: Filter[] = [{ + kinds, + limit, + ...(authors && { authors }), + ...(since && { since }), + ...(until && { until }), + ...(dTags && { '#d': dTags }) + }] + + try { + const allEvents: Event[] = [] + + const subscription = this.pool.subscribeMany(this.relays, filters, { + onevent(event: Event) { + allEvents.push(event) + }, + oneose() { + // End of stored events - subscription is complete for initial fetch + } + }) + + // Wait for events to be collected + await new Promise(resolve => setTimeout(resolve, 2000)) + + // Close the subscription + subscription.close() + + // Deduplicate events by ID + const uniqueEvents = Array.from( + new Map(allEvents.map(event => [event.id, event])).values() + ) + + return uniqueEvents + .sort((a, b) => b.created_at - a.created_at) + .slice(0, limit) + } catch (error) { + console.error('Failed to fetch events:', error) + throw error + } + } + /** * Fetch user profiles */