# Central Relay Hub Architecture ## Overview The Ario application uses a centralized relay hub architecture to manage all Nostr relay connections. This design provides a single point of connection management, efficient resource sharing, and consistent relay behavior across all components. ## Architecture Components ### 1. Core Relay Hub (`relayHub.ts`) The `RelayHub` class is the foundation of the relay management system, built on top of `nostr-tools` SimplePool. **Key Features:** - **Singleton Pattern**: Single instance manages all relay connections - **Connection Pooling**: Efficiently manages multiple relay connections - **Automatic Reconnection**: Handles connection failures and reconnection logic - **Health Monitoring**: Regular health checks and status reporting - **Mobile Optimization**: Handles mobile app visibility changes - **Event Emission**: Provides event-driven architecture for status updates **Location:** `src/lib/nostr/relayHub.ts` ### 2. Relay Hub Composable (`useRelayHub.ts`) A Vue 3 composable that provides a reactive interface to the relay hub. **Key Features:** - **Reactive State**: `isConnected`, `connectionStatus`, `relayStatuses` - **Connection Management**: `initialize()`, `connect()`, `disconnect()` - **Subscription Management**: `subscribe()`, `unsubscribe()` - **Event Publishing**: `publishEvent()`, `queryEvents()` - **Health Monitoring**: Connection health percentages and status **Location:** `src/composables/useRelayHub.ts` ### 3. Application Integration (`App.vue`) The main application component initializes the relay hub at startup. **Key Integration Points:** ```typescript // Initialize relay hub const relayHub = useRelayHub() onMounted(async () => { // Initialize relay hub try { await relayHub.initialize() console.log('Relay hub initialized successfully') } catch (error) { console.error('Failed to initialize relay hub:', error) } }) ``` ## How Components Plug Into the Relay Hub ### 1. Direct Integration via `useRelayHub()` Components can directly use the relay hub composable: ```typescript import { useRelayHub } from '@/composables/useRelayHub' export default { setup() { const relayHub = useRelayHub() // Access reactive state const isConnected = relayHub.isConnected const connectionStatus = relayHub.connectionStatus // Use connection methods const connect = async () => { await relayHub.connect() } // Subscribe to events const unsubscribe = relayHub.subscribe({ id: 'my-subscription', filters: [{ kinds: [1] }], // Text notes onEvent: (event) => { console.log('Received event:', event) } }) // Clean up on unmount onUnmounted(() => { unsubscribe() }) return { isConnected, connectionStatus, connect } } } ``` ### 2. Indirect Integration via Specialized Composables Components can use specialized composables that internally use the relay hub: #### Chat Integration (`useNostrChat.ts`) The chat system integrates with the relay hub for message handling: ```typescript // Inside useNostrChat.ts const subscribeToPeer = async (peerPubkey: string) => { // Check connection status if (!relayHub.isConnected.value) { await relayHub.connect() } // Subscribe to peer messages const unsubscribe = relayHub.subscribe({ id: `peer-${peerPubkey}`, filters: [ { kinds: [4], // Direct messages '#p': [currentUser.value.pubkey], authors: [peerPubkey] } ], onEvent: (event) => handleIncomingMessage(event, peerPubkey) }) return unsubscribe } ``` #### Market Integration (`useMarket.ts`) The market system can integrate similarly: ```typescript // Example market integration const subscribeToMarketEvents = async () => { if (!relayHub.isConnected.value) { await relayHub.connect() } return relayHub.subscribe({ id: 'market-events', filters: [ { kinds: [30000], // Custom market events '#t': ['market'] } ], onEvent: (event) => handleMarketEvent(event) }) } ``` ### 3. Configuration and Setup #### Relay Configuration Relays are configured in the application config: ```typescript // src/lib/config.ts export const config = { nostr: { relays: [ 'wss://relay.ariege.io', 'wss://lnbits.ariege.io/nostrrelay/benac' ] } } ``` #### Initialization Order 1. **App.vue** initializes the relay hub 2. **Components** can use the relay hub immediately after initialization 3. **Specialized composables** handle their own relay hub integration ## Benefits of the Central Relay Hub Architecture ### 1. **Resource Efficiency** - Single connection pool for all relay connections - Shared connection management across components - Reduced memory usage and connection overhead ### 2. **Consistent Behavior** - Unified connection status across the application - Consistent error handling and reconnection logic - Standardized relay health monitoring ### 3. **Scalability** - Easy to add new relay endpoints - Centralized configuration management - Simple to extend with new relay features ### 4. **Maintainability** - Single point of truth for relay logic - Easier debugging and monitoring - Centralized relay-related bug fixes ## Best Practices for Component Integration ### 1. **Always Check Connection Status** ```typescript const myFunction = async () => { if (!relayHub.isConnected.value) { await relayHub.connect() } // Proceed with relay operations } ``` ### 2. **Use Subscription IDs** ```typescript const subscriptionId = `my-component-${Date.now()}` const unsubscribe = relayHub.subscribe({ id: subscriptionId, filters: [...], onEvent: handleEvent }) ``` ### 3. **Clean Up Subscriptions** ```typescript onUnmounted(() => { if (unsubscribe) { unsubscribe() } }) ``` ### 4. **Handle Connection Errors** ```typescript const connect = async () => { try { await relayHub.connect() } catch (error) { console.error('Failed to connect:', error) // Handle error appropriately } } ``` ### 5. **Monitor Connection Health** ```typescript const connectionHealth = computed(() => relayHub.connectionHealth) const isHealthy = computed(() => connectionHealth.value > 50) ``` ## Example: Creating a New Relay-Enabled Component Here's a complete example of a new component that uses the relay hub: ```vue ``` ## Troubleshooting ### Common Issues 1. **Connection Not Established** - Check if relay hub is initialized in App.vue - Verify relay URLs in configuration - Check browser console for connection errors 2. **Subscriptions Not Working** - Ensure connection is established before subscribing - Verify subscription filters are correct - Check if unsubscribe function is called prematurely 3. **Performance Issues** - Monitor number of active subscriptions - Use appropriate filter limits - Clean up unused subscriptions ### Debug Tools The relay hub provides several debugging capabilities: ```typescript // Check connection status console.log('Connected:', relayHub.isConnected.value) console.log('Relay count:', relayHub.totalRelayCount) // Monitor relay health console.log('Health:', relayHub.connectionHealth.value) // Check specific relay status const status = relayHub.getRelayStatus('wss://relay.example.com') console.log('Relay status:', status) ``` ## Conclusion The central relay hub architecture provides a robust, efficient, and maintainable way to manage Nostr relay connections across the Ario application. By following the integration patterns outlined in this document, components can easily leverage the relay hub's capabilities while maintaining clean separation of concerns and optimal performance. For questions or issues with relay hub integration, refer to the existing implementations in `useNostrChat.ts` and `useMarket.ts` as reference examples.