diff --git a/src/modules/base/auth/auth-service.ts b/src/modules/base/auth/auth-service.ts index 6a3d257..45b97c3 100644 --- a/src/modules/base/auth/auth-service.ts +++ b/src/modules/base/auth/auth-service.ts @@ -1,8 +1,7 @@ // Auth service for LNbits integration import { ref } from 'vue' import { eventBus } from '@/core/event-bus' -import { getAuthToken } from '@/lib/config/lnbits' -import { config } from '@/lib/config' +import { lnbitsAPI, type LoginCredentials, type RegisterData } from '@/lib/api/lnbits' export class AuthService { public isAuthenticated = ref(false) @@ -21,39 +20,16 @@ export class AuthService { } async checkAuth(): Promise { - const authToken = getAuthToken() - - if (!authToken) { + if (!lnbitsAPI.isAuthenticated()) { console.log('πŸ”‘ No auth token found - user needs to login') this.isAuthenticated.value = false this.user.value = null return false } - // Fetch current user data from API try { this.isLoading.value = true - const API_BASE_URL = config.api.baseUrl || 'http://localhost:5006' - const response = await fetch(`${API_BASE_URL}/api/v1/auth/nostr/me`, { - headers: { - 'Authorization': `Bearer ${authToken}`, - 'Content-Type': 'application/json' - } - }) - - if (!response.ok) { - if (response.status === 401) { - console.log('πŸ”‘ Auth token invalid - user needs to login') - this.logout() - return false - } - console.warn(`πŸ”‘ Failed to fetch user data: ${response.status} - authentication may not be properly configured`) - this.isAuthenticated.value = false - this.user.value = null - return false - } - - const userData = await response.json() + const userData = await lnbitsAPI.getCurrentUser() this.user.value = userData this.isAuthenticated.value = true @@ -66,25 +42,25 @@ export class AuthService { console.warn('πŸ”‘ Authentication check failed:', error) this.isAuthenticated.value = false this.user.value = null + // Clear invalid token + lnbitsAPI.logout() return false } finally { this.isLoading.value = false } } - async login(credentials: any): Promise { + async login(credentials: LoginCredentials): Promise { this.isLoading.value = true try { - // Implement your login logic here - // For demo purposes, we'll accept any credentials - this.user.value = credentials + await lnbitsAPI.login(credentials) + const userData = await lnbitsAPI.getCurrentUser() + + this.user.value = userData this.isAuthenticated.value = true - // Store auth state - localStorage.setItem('auth', JSON.stringify(credentials)) - - eventBus.emit('auth:login', { user: credentials }, 'auth-service') + eventBus.emit('auth:login', { user: userData }, 'auth-service') } catch (error) { console.error('Login failed:', error) @@ -95,10 +71,31 @@ export class AuthService { } } + async register(data: RegisterData): Promise { + this.isLoading.value = true + + try { + await lnbitsAPI.register(data) + const userData = await lnbitsAPI.getCurrentUser() + + this.user.value = userData + this.isAuthenticated.value = true + + eventBus.emit('auth:login', { user: userData }, 'auth-service') + + } catch (error) { + console.error('Registration failed:', error) + eventBus.emit('auth:login-failed', { error }, 'auth-service') + throw error + } finally { + this.isLoading.value = false + } + } + logout(): void { + lnbitsAPI.logout() this.user.value = null this.isAuthenticated.value = false - localStorage.removeItem('auth') eventBus.emit('auth:logout', {}, 'auth-service') } diff --git a/src/modules/chat/services/chat-service.ts b/src/modules/chat/services/chat-service.ts index faf51a7..84b6374 100644 --- a/src/modules/chat/services/chat-service.ts +++ b/src/modules/chat/services/chat-service.ts @@ -404,16 +404,29 @@ export class ChatService { console.log('Loading message history for', peerPubkeys.length, 'peers') // Query historical messages (kind 4) to/from known peers - const events = await relayHub.queryEvents([ + // We need separate queries for sent vs received messages due to different tagging + const receivedEvents = await relayHub.queryEvents([ { kinds: [4], - authors: [userPubkey, ...peerPubkeys], // Messages from us or peers - '#p': [userPubkey], // Messages tagged with our pubkey - limit: 100 // Limit to last 100 messages per conversation + authors: peerPubkeys, // Messages from peers + '#p': [userPubkey], // Messages tagged to us + limit: 100 } ]) - console.log('Found', events.length, 'historical messages') + const sentEvents = await relayHub.queryEvents([ + { + kinds: [4], + authors: [userPubkey], // Messages from us + '#p': peerPubkeys, // Messages tagged to peers + limit: 100 + } + ]) + + const events = [...receivedEvents, ...sentEvents] + .sort((a, b) => a.created_at - b.created_at) // Sort by timestamp + + console.log('Found', events.length, 'historical messages:', receivedEvents.length, 'received,', sentEvents.length, 'sent') // Process historical messages for (const event of events) { diff --git a/src/modules/market/composables/useMarket.ts b/src/modules/market/composables/useMarket.ts index a26ffa8..6bd99a6 100644 --- a/src/modules/market/composables/useMarket.ts +++ b/src/modules/market/composables/useMarket.ts @@ -70,8 +70,31 @@ export function useMarket() { // Load market data from Nostr events const loadMarketData = async (marketData: any) => { try { + console.log('πŸ›’ Loading market data for:', { identifier: marketData.identifier, pubkey: marketData.pubkey?.slice(0, 8) }) + + // Check if we can query events (relays are connected) + if (!isConnected.value) { + console.log('πŸ›’ Not connected to relays, creating default market') + // Create default market without trying to fetch from Nostr + const market = { + d: marketData.identifier, + pubkey: marketData.pubkey, + relays: config.nostr.relays, + selected: true, + opts: { + name: 'Demo Market (Offline)', + description: 'Demo market running in offline mode', + merchants: [], + ui: {} + } + } + + marketStore.addMarket(market) + marketStore.setActiveMarket(market) + return + } + // Load market data from Nostr events - // Fetch market configuration event const events = await relayHub.queryEvents([ { @@ -80,6 +103,8 @@ export function useMarket() { '#d': [marketData.identifier] } ]) + + console.log('πŸ›’ Found', events.length, 'market events') // Process market events @@ -90,7 +115,7 @@ export function useMarket() { const market = { d: marketData.identifier, pubkey: marketData.pubkey, - relays: config.market.supportedRelays, + relays: config.nostr.relays, selected: true, opts: JSON.parse(marketEvent.content) } @@ -103,7 +128,7 @@ export function useMarket() { const market = { d: marketData.identifier, pubkey: marketData.pubkey, - relays: config.market.supportedRelays, + relays: config.nostr.relays, selected: true, opts: { name: 'AriΓ¨ge Market', @@ -122,7 +147,7 @@ export function useMarket() { const market = { d: marketData.identifier, pubkey: marketData.pubkey, - relays: config.market.supportedRelays, + relays: config.nostr.relays, selected: true, opts: { name: 'Default Market', @@ -159,6 +184,8 @@ export function useMarket() { authors: merchants } ]) + + console.log('πŸ›’ Found', events.length, 'stall events for', merchants.length, 'merchants') // Process stall events @@ -221,6 +248,8 @@ export function useMarket() { authors: merchants } ]) + + console.log('πŸ›’ Found', events.length, 'product events for', merchants.length, 'merchants') // Process product events @@ -463,35 +492,46 @@ export function useMarket() { // Connect to market const connectToMarket = async () => { try { + console.log('πŸ›’ Checking RelayHub connection...') // Use existing relay hub connection (should already be connected by base module) isConnected.value = relayHub.isConnected.value + console.log('πŸ›’ RelayHub connected:', isConnected.value) if (!isConnected.value) { - console.warn('RelayHub not connected, attempting to connect...') - await relayHub.connect() - isConnected.value = relayHub.isConnected.value - - if (!isConnected.value) { - throw new Error('Failed to connect to Nostr relays') - } + console.warn('πŸ›’ RelayHub not connected - this is expected if authentication is not complete') + // Don't try to connect here - let the base module handle connections + // Just proceed with offline/demo mode + console.log('πŸ›’ Proceeding in offline mode') } - // Market connected successfully + console.log('πŸ›’ Market connected successfully') // Load market data + console.log('πŸ›’ Loading basic market data...') await loadMarketData({ identifier: 'default', pubkey: nostrStore.account?.pubkey || '' }) - // Load stalls and products - await loadStalls() - await loadProducts() + // Load stalls and products only if connected + if (isConnected.value) { + console.log('πŸ›’ Loading stalls...') + await loadStalls() + console.log('πŸ›’ Loading products...') + await loadProducts() + } else { + console.log('πŸ›’ Skipping stalls/products loading - not connected to relays') + // Add sample products for demo mode + console.log('πŸ›’ Adding sample products for offline demo...') + addSampleProducts() + } // Subscribe to updates + console.log('πŸ›’ Subscribing to market updates...') subscribeToMarketUpdates() } catch (err) { + console.error('πŸ›’ Failed to connect to market:', err) error.value = err instanceof Error ? err : new Error('Failed to connect to market') throw err } diff --git a/src/modules/market/composables/useMarketPreloader.ts b/src/modules/market/composables/useMarketPreloader.ts index a09ba9f..a269a94 100644 --- a/src/modules/market/composables/useMarketPreloader.ts +++ b/src/modules/market/composables/useMarketPreloader.ts @@ -14,32 +14,97 @@ export function useMarketPreloader() { const preloadMarket = async () => { // Don't preload if already done or currently preloading if (isPreloaded.value || isPreloading.value) { + console.log('πŸ›’ Market preload skipped - already loaded or in progress') return } + console.log('πŸ›’ Starting market preload...') + try { isPreloading.value = true preloadError.value = null const naddr = config.market.defaultNaddr if (!naddr) { + console.warn('πŸ›’ No market naddr configured, skipping preload') return } - // Connect to market - await market.connectToMarket() + console.log('πŸ›’ Using market naddr:', naddr.slice(0, 20) + '...') - // Load market data - await market.loadMarket(naddr) + // Add timeout protection to prevent hanging + const timeoutMs = 30000 // 30 seconds + + const connectWithTimeout = async () => { + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error('Market connection timeout after 30 seconds')), timeoutMs) + }) + + return Promise.race([ + market.connectToMarket(), + timeoutPromise + ]) + } + + const loadWithTimeout = async () => { + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error('Market loading timeout after 30 seconds')), timeoutMs) + }) + + return Promise.race([ + market.loadMarket(naddr), + timeoutPromise + ]) + } + + // Connect to market + console.log('πŸ›’ Connecting to market...') + await connectWithTimeout() + + // Load market data + console.log('πŸ›’ Loading market data...') + await loadWithTimeout() // Clear any error state since preloading succeeded marketStore.setError(null) isPreloaded.value = true + console.log('πŸ›’ Market preload completed successfully') } catch (error) { - preloadError.value = error instanceof Error ? error.message : 'Failed to preload market' - // Don't throw error, let the UI handle it gracefully + console.error('πŸ›’ Market preload failed:', error) + console.log('πŸ›’ Attempting fallback with sample data...') + + try { + // Create a basic market with sample data as fallback + const fallbackMarket = { + d: 'demo-market', + pubkey: 'demo', + relays: ['ws://localhost:5006/nostrrelay/test1'], + selected: true, + opts: { + name: 'Demo Market', + description: 'Demo market with sample products', + merchants: [], + ui: {} + } + } + + marketStore.addMarket(fallbackMarket) + marketStore.setActiveMarket(fallbackMarket) + + // Add some sample products if the useMarket composable supports it + if (market.addSampleProducts && typeof market.addSampleProducts === 'function') { + market.addSampleProducts() + } + + isPreloaded.value = true + console.log('πŸ›’ Market preload completed with fallback data') + + } catch (fallbackError) { + console.error('πŸ›’ Fallback also failed:', fallbackError) + preloadError.value = error instanceof Error ? error.message : 'Failed to preload market' + } } finally { isPreloading.value = false } diff --git a/src/modules/market/views/MarketPage.vue b/src/modules/market/views/MarketPage.vue index f61c9ad..d257c85 100644 --- a/src/modules/market/views/MarketPage.vue +++ b/src/modules/market/views/MarketPage.vue @@ -184,4 +184,4 @@ onUnmounted(() => { } market.disconnectFromMarket() }) - \ No newline at end of file +