- Introduce a comprehensive roadmap for integrating nostr-market-app purchasing functionality into the web-app. - Outline key components of the shopping cart system, checkout process, and order management. - Detail phased implementation strategy, including enhanced user experience and advanced features. - Include security, performance, and testing considerations to ensure robust integration. feat: Enhance market store with new order and cart management features - Introduce new interfaces for Order, OrderItem, ContactInfo, and ShippingZone to support enhanced order management. - Update Stall and Product interfaces to include currency and shipping details. - Implement a comprehensive shopping cart system with stall-specific carts, including methods for adding, removing, and updating items. - Add payment-related interfaces and methods for managing payment requests and statuses. - Enhance filter options to include in-stock status and payment methods, improving product filtering capabilities. - Refactor computed properties and methods for better cart management and checkout processes. feat: Implement shopping cart functionality with new components and routing - Add ShoppingCart, CartItem, and CartSummary components to manage cart items and display summaries. - Introduce Cart.vue page to serve as the main shopping cart interface, integrating cart and summary components. - Update Navbar.vue to include a cart icon with item count, enhancing user navigation. - Implement cart management features in the market store, including item addition, quantity updates, and removal. - Establish routing for the cart page, ensuring seamless navigation for users. - Enhance ProductCard.vue to support adding items to the cart directly from the product listing. feat: Update cart and checkout functionality with improved navigation and button labels - Change "Proceed to Checkout" button text to dynamic "Place Order" based on context in CartSummary.vue. - Update "Continue Shopping" button to "Back to Cart" in CartSummary.vue for clearer navigation. - Modify routing for checkout to include stall ID in ShoppingCart.vue, enhancing checkout process. - Simplify Cart.vue by removing CartSummary component and focusing on ShoppingCart display. - Add new route for checkout with stall ID in router configuration for better handling of checkout flows. feat: Enhance cart and checkout components with improved shipping address handling - Update CartSummary.vue to use readonly types for cart items and shipping zones, ensuring immutability. - Modify Checkout.vue to conditionally display the shipping address field based on the selected shipping zone's requirements for physical shipping. - Add a digital delivery note for products that do not require a shipping address. - Introduce a computed property to determine if a shipping address is required, improving validation logic during checkout. - Update market store to include a new property for shipping zones indicating if physical shipping is required. feat: Implement order placement functionality in checkout process - Add a "Place Order" button in Checkout.vue that triggers the order placement process. - Introduce loading state during order placement to enhance user experience. - Implement createAndPlaceOrder method in market store to handle order creation and status updates. - Include error handling for order placement failures, providing user feedback on errors. - Update checkout logic to validate shipping zone and contact information before proceeding. feat: Add Order History page and update Navbar for order tracking - Introduce a new OrderHistory.vue page to display users' past orders with filtering and sorting options. - Update Navbar.vue to include an "Order History" option with a badge showing the count of orders. - Implement computed properties for order count and enhance user navigation experience. feat: Integrate Nostr functionality for order management and user notifications - Add NostrExtensionGuide component to inform users about the required Nostr extension for order transmission. - Implement useNostrOrders composable to manage Nostr connection, event creation, and order sending. - Update Checkout.vue to display Nostr connection status and provide feedback on order transmission. - Enhance OrderHistory.vue to show Nostr transmission status and details for each order. - Modify market store to handle Nostr event details and errors during order placement, ensuring local fallback. - Introduce types for Nostr events to improve type safety and integration with the existing order management system. refactor: Update Nostr relay configuration to use environment variable - Change DEFAULT_RELAYS to dynamically retrieve relay URLs from the VITE_MARKET_RELAYS environment variable. - Add error handling to ensure relays are configured before establishing a connection. - Modify createBlankEvent function to return a more precise type. - Update event signing process to ensure the event ID is generated correctly before signing. refactor: useAuth switch Enhance Nostr order management with authentication checks - Integrate user authentication checks to ensure Nostr features are only accessible to authenticated users. - Replace direct window.nostr calls with auth store methods for retrieving public and private keys. - Implement a helper function for signing events and mock encryption for order content. - Remove obsolete Nostr type definitions to streamline the codebase. feat: Enhance Checkout.vue with Nostr processing feedback and cleanup - Update the checkout button to disable based on order placement state. - Simplify order placement feedback by removing unnecessary Nostr processing checks. - Introduce a new visual indicator for Nostr order processing status. - Refactor computed properties for better clarity and efficiency in shipping zone handling. refactor: Streamline Nostr order handling and integrate buyer public key retrieval - Remove redundant Nostr relay tag from order event creation in useNostrOrders. - Update Checkout.vue to retrieve the buyer's public key from the auth store, enhancing order placement logic. - Modify createAndPlaceOrder method in market store to accept an optional Nostr orders instance for improved flexibility in order processing. refactor: Remove Nostr-related components and streamline order processing - Delete NostrExtensionGuide.vue and associated type definitions to simplify the codebase. - Remove unused useNostr.ts file and related logic from useNostrOrders.ts. - Update order handling in market store to directly integrate Nostr publishing without relying on external components. - Enhance Checkout.vue and Cart.vue to reflect changes in Nostr integration and provide clearer order status feedback. feat: Enhance Nostr chat functionality with malformed message handling - Introduce tracking for malformed message IDs to prevent repeated processing attempts. - Implement functions to mark messages as malformed, clean up old entries, and retrieve statistics on malformed messages. - Add periodic cleanup of malformed messages to manage memory usage. - Enhance message processing logic to skip previously identified malformed messages and provide detailed error handling for decryption failures. - Update the return object to include new functions for managing malformed messages. ZZ feat: Implement Lightning invoice management in market store - Add functionality to create and manage Lightning invoices for orders. - Introduce payment monitoring and status updates for invoices. - Implement payment confirmation messaging via Nostr upon successful payment. - Enhance order interface to include new fields for Lightning invoice details and payment status. ZZ feat: Enhance OrderHistory.vue with payment status indicators and invoice management - Add visual indicators for payment status, including 'Paid' and 'Payment Pending' badges. - Implement expandable payment display for orders with Lightning invoices. - Introduce functionality to toggle payment display and generate Lightning invoices. - Update order status messaging to reflect payment requirements and invoice generation status. ZZ feat: Enhance OrderHistory.vue with payment status indicators and invoice management - Add visual indicators for payment status, including 'Paid' and 'Payment Pending' badges. - Implement expandable payment display for orders with Lightning invoices. - Introduce functionality to toggle payment display and generate Lightning invoices. - Update order status messaging to reflect payment requirements and invoice generation status. feat: Implement order event handling in useOrderEvents composable - Introduce useOrderEvents composable to manage subscription and processing of order-related events. - Define order event types and interfaces for better type safety and clarity. - Implement methods to handle payment requests, order status updates, and invoice generation. - Enhance OrderHistory.vue to display order event subscription status and last update timestamp. - Update market store to include order update functionality for better integration with order events. FIX: Build errors refactor: Update component styles and improve UI consistency across market pages - Replace various color classes with updated design tokens for better consistency. - Change background colors of components to align with the new design system. - Update text colors to enhance readability and maintain a cohesive look. - Refactor class names in CartItem.vue, CartSummary.vue, DashboardOverview.vue, and other components to use the new color scheme. - Ensure all components reflect the updated design guidelines for a unified user experience. refactor: Remove Order History references from Navbar component - Eliminate order count computation and related UI elements from the Navbar. - Streamline the Navbar by removing the Order History button and badge. - Maintain existing functionality for other menu items, ensuring a cleaner user interface. feat: Implement QR code generation and download functionality in PaymentDisplay component - Add QR code generation for payment requests using the qrcode library. - Enhance UI to display loading states and error messages during QR code generation. - Introduce a download button for users to save the generated QR code. - Implement logic to regenerate QR code when the invoice changes. refactor: Replace useRelayHub with relayHubComposable across components - Update imports in multiple components and composables to use the new relayHubComposable for better consistency and maintainability. - Enhance OrderHistory.vue with debug information for development, displaying key states related to orders, authentication, and relay hub connectivity. - Remove unnecessary reconnect button from RelayHubStatus.vue to streamline user interactions. - Improve logging in useOrderEvents for better debugging and monitoring of order event subscriptions. refactor: Update OrderHistory.vue styles for improved UI consistency - Replace color classes with updated design tokens for better alignment with the new design system. - Enhance readability by adjusting text colors and background styles for payment status indicators. - Ensure a cohesive look across the component by standardizing class names and styles. refactor: Update component styles for improved UI consistency across checkout pages - Replace color classes with updated design tokens for better alignment with the new design system. - Enhance readability by adjusting text colors and background styles in CartSummary.vue, PaymentDisplay.vue, Checkout.vue, and OrderHistory.vue. - Standardize class names and styles to ensure a cohesive look across all components. feat: Implement invoice generation and Nostr integration in MerchantStore component - Add functionality to generate Lightning invoices for orders and send them to customers via Nostr. - Introduce a new sendInvoiceToCustomer method to update order details and publish invoice information. - Enhance order event handling in useOrderEvents to update existing orders with new invoice data. - Improve error handling and logging for invoice generation and sending processes. feat: Enhance MerchantStore and PaymentDisplay components for improved invoice handling - Add wallet indicator in MerchantStore to display the selected wallet name during pending orders. - Implement temporary fixes for missing buyer and seller public keys when generating invoices. - Update invoice generation logic to utilize the first available wallet and improve error handling. - Modify PaymentDisplay to use the new bolt11 field for payment requests and enhance date formatting. - Refactor order event handling to ensure accurate updates and invoice management across components. feat: Enhance order event processing in useOrderEvents composable - Refactor processOrderEvent to handle incoming Nostr market order events with improved validation and logging. - Implement logic to update existing orders or create new ones based on event data, ensuring accurate order management. - Add detailed console logging for better debugging and tracking of order events and their statuses. - Ensure compatibility with market order structure and invoice details for seamless integration with payment processing. feat: Enhance order management with localStorage persistence - Update createOrder method to optionally accept an order ID from events, improving order tracking. - Convert items from readonly to mutable for better manipulation. - Implement localStorage persistence for orders, ensuring data is saved and loaded across sessions. - Add methods to save and load orders from localStorage, enhancing user experience and data reliability. feat: Update invoice creation to support additional metadata and nostrmarket compatibility - Modify createInvoice method to accept an optional extra parameter for additional metadata. - Change invoice tag to 'nostrmarket' for improved compatibility with Nostr market. - Include merchant and buyer public keys in the invoice data for better integration. - Update invoice creation in market store to utilize new parameters for enhanced functionality. feat: Enhance order and invoice handling for Nostr market compatibility - Add originalOrderId to order events for tracking Nostr order IDs. - Update invoice creation to utilize original Nostr order ID when generating invoices. - Improve logging for invoice requests to LNBits, providing better visibility into the data being sent. - Ensure compatibility with nostrmarket by adjusting order ID handling in the market store. fix: Refine invoice creation logic for Nostr market compatibility - Adjust order ID handling in invoice creation to prioritize originalOrderId for better compatibility with nostrmarket. - Enhance logging to provide clearer insights into the order ID being used during invoice generation. feat: Integrate nostrmarket service for order publishing and merchant catalog management - Implement functionality to publish orders via the nostrmarket protocol, replacing the previous Nostr integration. - Add methods to publish merchant catalogs, including stalls and products, to nostrmarket with event ID tracking. - Enhance order interface to include nostrEventId for better integration with nostrmarket. - Improve error handling and logging for nostrmarket publishing processes. refactor: Simplify order creation logic in useOrderEvents and update contact structure in nostrmarketService - Streamline order creation by using event.id and defaulting to 'unknown' for stallId. - Update contact structure to include address and message, removing optional email and phone fields for clarity. - Ensure compatibility with new order data structure for improved integration with nostrmarket. feat: Add bech32 to hex conversion utility and integrate into nostrmarketService - Implement a new utility function to convert bech32 keys to hex format, enhancing key handling. - Update nostrmarketService to utilize the new conversion function for user public and private keys. - Modify contact structure to include additional fields for improved order information management. feat: Add nostrclient configuration to AppConfig for enhanced Nostr integration - Introduce a new nostrclient property in AppConfig to manage Nostr client settings. - Include url and enabled fields to configure the Nostr client connection dynamically. - Ensure compatibility with environment variables for flexible deployment configurations. feat: Introduce comprehensive order management and fulfillment documentation - Add ORDER_MANAGEMENT_FULFILLMENT.md to detail the complete order lifecycle, including order states, data models, and merchant/customer interfaces. - Implement test scripts for verifying order and payment request formats in test-nostrmarket-format.js. - Create PaymentRequestDialog.vue for handling payment requests with dynamic options and QR code generation. - Enhance useOrderEvents.ts to process nostrmarket protocol messages for order management. - Update nostrmarketService.ts to handle payment requests and order status updates, ensuring seamless integration with the marketplace. - Integrate payment request dialog in Market.vue and manage its state in the market store. refactor: Remove obsolete test script for nostrmarket order format - Delete test-nostrmarket-format.js as it is no longer needed for verifying order and payment request formats. - Update PaymentRequestDialog.vue to enhance UI components and integrate QR code generation for payment requests. - Refactor payment handling and notification logic to utilize toast notifications instead of Quasar's notify system. feat: Enhance OrderHistory component with payment request handling and QR code generation - Add UI elements to display payment request status and options in OrderHistory.vue. - Implement functions to copy payment requests, open Lightning wallets, and download QR codes. - Update nostrmarketService to generate QR codes for payment requests and manage order statuses effectively. - Remove obsolete PaymentRequestDialog integration from Market.vue for a cleaner UI. feat: Add debug information and toast notifications in OrderHistory component - Introduce debug info display for payment requests and hashes in OrderHistory.vue. - Implement toast notifications for actions like copying payment requests, opening wallets, and downloading QR codes. - Enhance error handling with user feedback for various order-related actions. - Remove obsolete payment request dialog methods from market store for cleaner code. feat: Revamp CartItem and ShoppingCart components for improved layout and functionality - Enhance CartItem.vue with responsive design for desktop and mobile views, including better organization of product details, price, quantity controls, and remove button. - Update ShoppingCart.vue to separate desktop and mobile layouts, improving the user experience with clearer action buttons and cart summary display. - Implement consistent styling and layout adjustments for better visual coherence across different screen sizes.
32 KiB
Ario Web App Architecture
Overview
The Ario web app uses a singleton-based architecture to manage shared state and resources across components. This document explains how the core singletons work and how different components (chat, market, feed) plug into the system.
Core Singleton Architecture
1. Authentication Singleton (useAuth)
Location: src/composables/useAuth.ts
Purpose: Manages user authentication state using LNBits integration.
Singleton Pattern:
export function useAuth() {
// ... implementation
}
// Export singleton instance for global state
export const auth = useAuth()
Usage: Imported throughout the app for authentication state:
import { auth } from '@/composables/useAuth'
// All components see the same authentication state
console.log(auth.isAuthenticated.value)
2. Relay Hub Singleton (relayHub)
Location: src/lib/nostr/relayHub.ts
Purpose: Centralized management of Nostr relay connections, providing a single WebSocket connection pool for the entire application.
Singleton Pattern:
export class RelayHub extends EventEmitter {
// ... implementation
}
// Export singleton instance
export const relayHub = new RelayHub()
Key Features:
- Single WebSocket connection pool
- Automatic reconnection and health checks
- Event broadcasting for connection state changes
- Mobile visibility handling for WebSocket management
3. Relay Hub Composable Singleton (useRelayHub)
Location: src/composables/useRelayHub.ts
Purpose: Vue-reactive wrapper around the core relayHub instance, providing reactive state and Vue-specific functionality.
Singleton Pattern:
export function useRelayHub() {
// Uses the same relayHub instance
const initialize = async () => {
await relayHub.initialize(relayUrls)
}
return { initialize, connect, disconnect, ... }
}
// Export singleton instance
export const relayHubComposable = useRelayHub()
Relationship: This composable wraps the core relayHub instance, making it Vue-reactive while maintaining the singleton connection pool.
4. Chat Singleton (useNostrChat)
Location: src/composables/useNostrChat.ts
Purpose: Manages Nostr chat functionality including message encryption/decryption, peer management, and real-time messaging.
Singleton Pattern:
export function useNostrChat() {
// ... implementation
}
// Export singleton instance for global state
export const nostrChat = useNostrChat()
Relay Hub Integration: Uses useRelayHub() to connect to relays and manage subscriptions.
5. Market Singleton (useMarket)
Location: src/composables/useMarket.ts
Purpose: Manages market functionality including stalls, products, and market data.
Singleton Pattern:
export function useMarket() {
// ... implementation
}
// Export singleton instance
export const market = useMarket()
Relay Hub Integration: Uses useRelayHub() to fetch market data from Nostr relays.
6. Nostr Store Singleton (useNostrStore)
Location: src/stores/nostr.ts
Purpose: Pinia store for Nostr-related state including push notifications and relay connection status.
Singleton Pattern:
export const useNostrStore = defineStore('nostr', () => {
// ... implementation
})
Relay Hub Integration: Imports the relayHub singleton directly for connection management.
Component Integration Architecture
How Components Plug Into the System
┌─────────────────────────────────────────────────────────────┐
│ Component Layer │
├─────────────────────────────────────────────────────────────┤
│ ChatComponent │ NostrFeed │ Market.vue │ Navbar.vue │
│ ↓ │ ↓ │ ↓ │ ↓ │
├─────────────────────────────────────────────────────────────┤
│ Composable Layer │
├─────────────────────────────────────────────────────────────┤
│ useNostrChat │ useRelayHub │ useMarket │ useAuth │
│ ↓ │ ↓ │ ↓ │ ↓ │
├─────────────────────────────────────────────────────────────┤
│ Singleton Instance Layer │
├─────────────────────────────────────────────────────────────┤
│ nostrChat │ relayHub │ market │ auth │
│ ↓ │ ↓ │ ↓ │ ↓ │
├─────────────────────────────────────────────────────────────┤
│ Core Implementation Layer │
├─────────────────────────────────────────────────────────────┤
│ RelayHub │ LNBits API │ Market API │ Chat API │
└─────────────────────────────────────────────────────────────┘
1. Chat Component Integration
Component: src/components/nostr/ChatComponent.vue
Integration Path:
// 1. Component imports the chat singleton
import { nostrChat } from '@/composables/useNostrChat'
// 2. Chat singleton uses relay hub composable
import { useRelayHub } from './useRelayHub'
// 3. Relay hub composable uses core relay hub singleton
import { relayHub } from '../lib/nostr/relayHub'
Data Flow:
ChatComponent → nostrChat → useRelayHub → relayHub → Nostr Relays
↓ ↓ ↓ ↓
UI Updates Chat State Vue State WebSocket
Key Benefits:
- Single chat state across all components
- Shared relay connections
- Centralized message encryption/decryption
- Unified peer management
2. Feed Component Integration
Component: src/components/nostr/NostrFeed.vue
Integration Path:
// 1. Component imports relay hub composable
import { useRelayHub } from '@/composables/useRelayHub'
// 2. Relay hub composable uses core relay hub singleton
import { relayHub } from '../lib/nostr/relayHub'
Data Flow:
NostrFeed → useRelayHub → relayHub → Nostr Relays
↓ ↓ ↓
Feed UI Vue State WebSocket
Key Benefits:
- Real-time feed updates
- Shared relay connections
- Centralized admin filtering
- Efficient event subscription management
3. Market Component Integration
Component: src/pages/Market.vue
Integration Path:
// 1. Component uses market composable
import { useMarket } from '@/composables/useMarket'
// 2. Market composable uses relay hub composable
import { useRelayHub } from './useRelayHub'
// 3. Relay hub composable uses core relay hub singleton
import { relayHub } from '../lib/nostr/relayHub'
Data Flow:
Market.vue → useMarket → useRelayHub → relayHub → Nostr Relays
↓ ↓ ↓ ↓
Market UI Market Vue State WebSocket
State
Key Benefits:
- Centralized market data
- Shared relay connections
- Efficient product/stall fetching
- Real-time market updates
Singleton Benefits in Practice
1. Shared Connection State
// Component A
const { isConnected } = useRelayHub()
console.log(isConnected.value) // true
// Component B (different part of app)
const { isConnected } = useRelayHub()
console.log(isConnected.value) // true (same state!)
2. Centralized Resource Management
// All components share the same WebSocket connections
relayHub.connectedRelayCount // Same value everywhere
relayHub.totalSubscriptionCount // Same value everywhere
3. Event Broadcasting
// Component A listens to connection events
relayHub.on('connected', () => console.log('Connected!'))
// Component B triggers connection
await relayHub.connect() // Component A gets notified!
4. Efficient Resource Usage
- Before: Each component creates its own relay connections
- After: Single connection pool shared across all components
- Result: Reduced memory usage, better performance, consistent state
Configuration and Environment Variables
Required Environment Variables
# Nostr relay configuration
VITE_NOSTR_RELAYS=["wss://relay1.example.com", "wss://relay2.example.com"]
# Admin pubkeys for feed filtering
VITE_ADMIN_PUBKEYS=["npub1admin1...", "npub1admin2..."]
# LNBits API configuration
VITE_LNBITS_BASE_URL=https://your-lnbits-instance.com
VITE_API_KEY=your-api-key
Configuration Structure
// src/lib/config/index.ts
export const config: AppConfig = {
nostr: {
relays: parseJsonEnv(import.meta.env.VITE_NOSTR_RELAYS, []),
adminPubkeys: parseJsonEnv(import.meta.env.VITE_ADMIN_PUBKEYS, [])
},
api: {
baseUrl: import.meta.env.VITE_LNBITS_BASE_URL || '',
key: import.meta.env.VITE_API_KEY || ''
}
}
Testing and Development
Mocking Singletons for Testing
// In test files, you can mock the singleton instances
import { auth } from '@/composables/useAuth'
import { nostrChat } from '@/composables/useNostrChat'
// Mock the singletons
vi.mock('@/composables/useAuth', () => ({
auth: {
isAuthenticated: ref(false),
currentUser: ref(null)
}
}))
Development Benefits
- Hot Reload: Singleton state persists across component reloads
- Debugging: Single point of inspection for shared state
- Performance: No unnecessary re-initialization of expensive resources
Best Practices
1. Always Use the Singleton Instance
// ✅ Good: Use the exported singleton
import { auth } from '@/composables/useAuth'
import { nostrChat } from '@/composables/useNostrChat'
// ❌ Bad: Don't create new instances
const { currentUser } = useAuth() // This creates a new instance!
2. Access State Through Composables
// ✅ Good: Use the composable wrapper for reactive state
const { isConnected, connectionStatus } = useRelayHub()
// ❌ Bad: Don't access relayHub directly in components
import { relayHub } from '@/lib/nostr/relayHub'
console.log(relayHub.isConnected) // Not reactive!
3. Listen to Events for State Changes
// ✅ Good: Listen to relay hub events
relayHub.on('connected', () => {
console.log('Relay connected!')
})
// ❌ Bad: Don't poll for state changes
setInterval(() => {
console.log(relayHub.isConnected) // Inefficient!
}, 1000)
Conclusion
The singleton architecture in Ario provides:
- Efficient Resource Management: Single connection pools and shared state
- Consistent User Experience: All components see the same data
- Simplified Development: Clear patterns for state management
- Better Performance: No duplicate connections or state
- Easier Testing: Centralized mocking of shared resources
This architecture makes the app more maintainable, performant, and user-friendly while providing a solid foundation for future features.
Shared Nostr Function Execution
Event Building and Publishing Pattern
All components that need to create and publish Nostr events follow a consistent pattern through the relay hub singleton:
1. Event Creation Utilities
Direct Event Template Creation (used in useNostrChat):
import { nip04, finalizeEvent, type EventTemplate } from 'nostr-tools'
// Create event template
const eventTemplate: EventTemplate = {
kind: 4, // Encrypted DM
created_at: Math.floor(Date.now() / 1000),
tags: [['p', peerPubkey]]
content: encryptedContent
}
// Finalize and sign the event
const event = finalizeEvent(eventTemplate, hexToBytes(privateKey))
Market Event Creation (used in useMarket):
// Market events use specific kinds and tags
const MARKET_EVENT_KINDS = {
STALL: 30017,
PRODUCT: 30018,
MARKET: 30019
}
// Extract data from event tags
const stallId = event.tags.find((tag: any) => tag[0] === 'd')?.[1]
const productId = event.tags.find((tag: any) => tag[0] === 'd')?.[1]
2. Centralized Publishing Through Relay Hub
All components publish through the same singleton:
// In useNostrChat.ts
await relayHub.publishEvent(event)
// In useMarket.ts (if publishing)
await relayHub.publishEvent(event)
// In any other component
await relayHub.publishEvent(event)
Relay Hub Publishing Logic:
async publishEvent(event: Event): Promise<{ success: number; total: number }> {
if (!this._isConnected) {
throw new Error('Not connected to any relays')
}
const relayUrls = Array.from(this.connectedRelays.keys())
const results = await Promise.allSettled(
relayUrls.map(relay => this.pool.publish([relay], event))
)
const successful = results.filter(result => result.status === 'fulfilled').length
const total = results.length
this.emit('eventPublished', { eventId: event.id, success: successful, total })
return { success: successful, total }
}
3. Event Querying and Subscription
Consistent Query Interface:
// One-time event queries
const events = await relayHub.queryEvents(filters)
// Real-time subscriptions
const unsubscribe = relayHub.subscribe({
id: 'subscription-id',
filters: [{ kinds: [1], limit: 50 }],
onEvent: (event) => {
// Handle incoming event
}
})
Shared Dependencies
nostr-tools Package:
finalizeEvent- Event signing and finalizationnip04- Encrypted message handlingSimplePool- Relay connection managementEventTemplate- Event structure typing
Common Event Patterns:
- Text Notes (kind 1): Community posts and announcements
- Encrypted DMs (kind 4): Private chat messages
- Market Events (kinds 30017-30019): Stall, product, and market data
- Reactions (kind 7): Emoji reactions to posts
Configuration Management
Environment Variables and Configuration
Centralized Config (src/lib/config/index.ts):
interface NostrConfig {
relays: string[]
adminPubkeys: string[]
}
interface MarketConfig {
defaultNaddr: string
supportedRelays: string[]
lightningEnabled: boolean
defaultCurrency: string
}
// Environment variables
VITE_NOSTR_RELAYS: JSON array of relay URLs
VITE_ADMIN_PUBKEYS: JSON array of admin public keys
VITE_MARKET_RELAYS: JSON array of market-specific relays
VITE_LIGHTNING_ENABLED: Boolean for Lightning integration
Default Relay Configuration:
// Fallback relay configuration
supportedRelays: [
'ws://127.0.0.1:7777',
'wss://relay.damus.io',
'wss://relay.snort.social',
'wss://nostr-pub.wellorder.net',
'wss://nostr.zebedee.cloud',
'wss://nostr.walletofsatoshi.com'
]
Configuration Utilities
Admin Pubkey Validation:
export const configUtils = {
isAdminPubkey(pubkey: string): boolean {
return config.nostr.adminPubkeys.includes(pubkey)
}
}
Error Handling and Resilience
Connection Management
Automatic Reconnection:
// Relay hub automatically handles reconnection
private scheduleReconnect(): void {
if (this.reconnectInterval) {
clearTimeout(this.reconnectInterval)
}
this.reconnectInterval = setTimeout(async () => {
await this.connect()
}, this.reconnectDelay)
}
Health Monitoring:
// Continuous health checks
private startHealthCheck(): void {
this.healthCheckInterval = setInterval(() => {
this.performHealthCheck()
}, this.healthCheckIntervalMs)
}
Error Handling Patterns
Graceful Degradation:
// Components handle connection failures gracefully
async function loadNotes() {
try {
if (!relayHub.isConnected.value) {
await relayHub.connect()
}
// ... load notes
} catch (err) {
error.value = err instanceof Error ? err : new Error('Failed to load notes')
console.error('Failed to load notes:', err)
}
}
Retry Logic:
// Market app retry pattern
async def wait_for_nostr_events(nostr_client: NostrClient):
while True:
try:
await subscribe_to_all_merchants()
# ... process events
except Exception as e:
logger.warning(f"Subscription failed. Will retry in one minute: {e}")
await asyncio.sleep(10)
Event Processing and Filtering
Filter Management
Dynamic Filter Creation:
// Feed component creates filters based on type
const filters: any[] = [{
kinds: [1], // TEXT_NOTE
limit: 50
}]
// Filter by authors for announcements
if (props.feedType === 'announcements' && hasAdminPubkeys.value) {
filters[0].authors = adminPubkeys
}
Market Event Filtering:
// Market-specific filters
const _filters_for_stall_events = (public_keys: List[str], since: int) -> List:
stall_filter = {"kinds": [30017], "authors": public_keys}
if since and since != 0:
stall_filter["since"] = since
return [stall_filter]
Event Processing Pipeline
Event Processing Flow:
// 1. Receive event from relay
onEvent: (event) => {
// 2. Process and transform
const newNote = {
id: event.id,
pubkey: event.pubkey,
content: event.content,
created_at: event.created_at,
tags: event.tags || [],
mentions: event.tags?.filter(tag => tag[0] === 'p').map(tag => tag[1]) || [],
isReply: event.tags?.some(tag => tag[0] === 'e' && tag[3] === 'reply'),
replyTo: event.tags?.find(tag => tag[0] === 'e' && tag[3] === 'reply')?.[1]
}
// 3. Apply business logic filters
let shouldInclude = true
if (props.feedType === 'announcements' && !isAdminPost(event.pubkey)) {
shouldInclude = false
}
// 4. Add to state if approved
if (shouldInclude) {
notes.value.unshift(newNote)
// 5. Limit array size for memory management
if (notes.value.length > 100) {
notes.value = notes.value.slice(0, 100)
}
}
}
Performance Optimizations
Memory Management
Array Size Limits:
// Prevent memory issues with large feeds
if (notes.value.length > 100) {
notes.value = notes.value.slice(0, 100)
}
Subscription Cleanup:
// Proper cleanup prevents memory leaks
onUnmounted(() => {
if (unsubscribe) {
unsubscribe()
unsubscribe = null
}
})
Connection Pooling
Shared WebSocket Connections:
// Single pool shared across all components
private pool: SimplePool
// Components don't create individual connections
// They all use the centralized relay hub
Efficient Relay Usage:
// Query multiple relays simultaneously
const events = await this.pool.querySync(availableRelays, filter)
// Publish to all relays in parallel
const results = await Promise.allSettled(
relayUrls.map(relay => this.pool.publish([relay], event))
)
Security Considerations
Encryption and Privacy
End-to-End Encryption:
// All chat messages are encrypted using nip04
const encryptedContent = await nip04.encrypt(
privateKey,
publicKey,
content
)
Private Key Management:
// Keys never leave the browser
// Validation of key format and length
if (privateKey.length !== 64) {
throw new Error(`Invalid private key length: ${privateKey.length} (expected 64)`)
}
// Hex format validation
const hexRegex = /^[0-9a-fA-F]+$/
if (!hexRegex.test(privateKey)) {
throw new Error(`Invalid private key format: contains non-hex characters`)
}
Access Control
Admin Pubkey Validation:
// Only admin pubkeys can post announcements
function isAdminPost(pubkey: string): boolean {
return configUtils.isAdminPubkey(pubkey)
}
// Filter content based on user permissions
if (props.feedType === 'announcements' && !isAdminPost(event.pubkey)) {
shouldInclude = false
}
Benefits of This Architecture
1. Consistent Event Handling
- All components use the same event creation and publishing patterns
- Centralized relay management ensures consistent behavior
- Shared error handling and retry logic
2. Efficient Resource Usage
- Single WebSocket connection pool shared across all components
- No duplicate relay connections
- Centralized connection health monitoring
3. Simplified Component Logic
- Components focus on business logic, not relay management
- Consistent API for all Nostr operations
- Easy to add new event types and functionality
4. Maintainable Codebase
- Single source of truth for relay connections
- Centralized event publishing logic
- Easy to debug and monitor Nostr operations
5. Robust Error Handling
- Automatic reconnection and health monitoring
- Graceful degradation when relays are unavailable
- Comprehensive error logging and user feedback
6. Performance Optimized
- Memory management with array size limits
- Efficient connection pooling
- Parallel relay operations
Future Extensibility
This architecture makes it easy to add new Nostr functionality:
- New Event Types: Add new event creation utilities following the existing pattern
- Additional Relays: Configure new relays in the centralized relay hub
- New Components: Import the existing singletons and use the established patterns
- Enhanced Features: Extend the relay hub with new capabilities (e.g., event caching, filtering)
- Advanced Filtering: Implement more sophisticated event filtering and processing
- Caching Layer: Add event caching for improved performance
- Rate Limiting: Implement rate limiting for relay operations
- Metrics and Monitoring: Add comprehensive metrics for relay performance
This architecture makes the app more maintainable, performant, and user-friendly while providing a solid foundation for future features.
Market Integration Roadmap
Overview
This document outlines the roadmap for integrating the nostr-market-app purchasing functionality into the web-app, creating a seamless e-commerce experience while maintaining the decentralized, Nostr-based architecture.
Analysis of nostr-market-app Purchasing Flow
The nostr-market-app has a sophisticated purchasing system with the following key components:
1. Shopping Cart System
- Cart Management: Products are added to stall-specific carts
- Cart State: Each stall has its own cart with products and quantities
- Cart Persistence: Cart data is stored locally and synced across sessions
2. Checkout Process
- Order Confirmation: Users provide contact information (address, email, message)
- Shipping Selection: Multiple shipping zones with different costs
- Payment Options: Lightning Network, BTC Onchain, and Cashu support
3. Order Placement
- Encrypted Communication: Orders are encrypted using NIP-04 and sent as direct messages
- Order Structure: Includes product details, quantities, shipping, and contact info
- Payment Integration: Lightning invoice generation and QR code display
4. Key Components
ShoppingCartCheckout.vue- Main checkout interfaceuseShoppingCart.js- Cart management logicuseOrders.js- Order placement and managementmarketStore.js- Central state management
Implementation Roadmap
Phase 1: Enhanced Shopping Cart System (High Priority)
1.1 Extend Market Store
- Add cart management with stall-specific carts
- Implement cart persistence and synchronization
- Add shipping zone support
- Extend existing
useMarketStorewith cart functionality
1.2 Create Cart Components
ShoppingCart.vue- Cart overview and managementCartItem.vue- Individual cart item with quantity controlsCartSummary.vue- Cart totals and checkout button- Integrate cart icon in header with item count
1.3 Cart State Management
- Implement stall-specific cart structure
- Add cart persistence to local storage
- Sync cart state across components
- Handle cart updates and real-time synchronization
Phase 2: Checkout System (High Priority)
2.1 Checkout Flow
CheckoutPage.vue- Main checkout interface- Contact information form (address, email, message)
- Shipping zone selection with cost calculation
- Order summary and confirmation
2.2 Payment Integration
- Lightning Network invoice generation
- QR code display for payments
- Payment status tracking
- Integration with existing payment infrastructure
2.3 Checkout State Management
- Form validation and error handling
- Multi-step checkout process
- Order confirmation and review
Phase 3: Order Management (Medium Priority)
3.1 Order Processing
- Encrypted order creation using NIP-04
- Direct message sending to merchants
- Order status tracking and updates
- Integration with existing Nostr messaging system
3.2 Order History
OrdersPage.vue- User's order history- Order status updates and notifications
- Communication with merchants
- Order filtering and search
3.3 Order Communication
- Encrypted messaging between buyers and sellers
- Order status notifications
- Shipping updates and tracking
Phase 4: Enhanced User Experience (Medium Priority)
4.1 Streamlined Navigation
- Integrated cart icon in header
- Quick checkout from product cards
- Seamless flow between browsing and purchasing
- Breadcrumb navigation for checkout process
4.2 Real-time Updates
- Live inventory updates
- Order status notifications
- Chat integration with merchants
- WebSocket connections for live updates
Phase 5: Advanced Features (Low Priority)
5.1 Multiple Payment Methods
- BTC Onchain payments
- Cashu integration
- Payment method selection
- Payment preference storage
5.2 Advanced Filtering and Search
- Enhanced product search
- Advanced filtering options
- Saved search preferences
- Product recommendations
5.3 Merchant Tools
- Merchant dashboard
- Inventory management
- Order fulfillment tools
- Analytics and reporting
Technical Implementation Details
State Management Architecture
Extended Market Store Structure
interface CartItem {
product: Product
quantity: number
stallId: string
}
interface StallCart {
id: string
merchant: string
products: CartItem[]
subtotal: number
shippingZone?: ShippingZone
}
interface Order {
id: string
cartId: string
status: OrderStatus
contactInfo: ContactInfo
shippingZone: ShippingZone
paymentRequest?: string
createdAt: number
updatedAt: number
}
Component Architecture
New Components to Create
ShoppingCart.vue- Main cart interfaceCartItem.vue- Individual cart itemCartSummary.vue- Cart totals and checkoutCheckoutPage.vue- Complete checkout flowOrderSummary.vue- Order review and confirmationPaymentModal.vue- Payment processing interfaceOrdersPage.vue- Order history and management
Enhanced Existing Components
ProductCard.vue- Add quick add to cartMarket.vue- Integrate cart functionality- Header navigation - Add cart icon and count
Data Flow
Cart Management Flow
- User adds product to cart
- Cart state updated in store
- Cart persisted to local storage
- Cart UI components updated
- Real-time sync across components
Checkout Flow
- User initiates checkout from cart
- Contact information collected
- Shipping zone selected
- Order summary displayed
- Payment method selected
- Order encrypted and sent
- Payment processed
- Order confirmed
Integration Points
Existing Systems
- Authentication: Integrate with existing auth system
- Nostr Store: Extend existing Nostr functionality
- Relay Hub: Use existing relay connections
- Notifications: Leverage existing notification system
- Storage: Extend existing storage mechanisms
New Systems
- Payment Gateway: Lightning Network integration
- Order Management: Encrypted order processing
- Cart Persistence: Local storage with sync
- Real-time Updates: WebSocket connections
Security Considerations
Data Encryption
- All order data encrypted using NIP-04
- Private keys never stored in plain text
- Secure communication channels
- Payment information protection
Privacy Protection
- Minimal data collection
- User consent for data sharing
- Anonymity options for users
- Secure storage practices
Payment Security
- Lightning Network security
- Payment verification
- Fraud prevention measures
- Secure key management
Performance Considerations
Optimization Strategies
- Lazy loading of cart components
- Efficient state management
- Minimal re-renders
- Optimized storage operations
Scalability
- Modular component architecture
- Efficient data structures
- Caching strategies
- Performance monitoring
Testing Strategy
Unit Testing
- Component functionality
- Store actions and mutations
- Utility functions
- Integration points
Integration Testing
- End-to-end checkout flow
- Payment processing
- Order management
- Real-time updates
User Testing
- Usability testing
- Performance testing
- Security testing
- Accessibility testing
Deployment and Rollout
Phase 1 Deployment
- Enhanced shopping cart
- Basic checkout functionality
- Order placement system
Phase 2 Deployment
- Payment integration
- Order tracking
- Enhanced user experience
Phase 3 Deployment
- Advanced features
- Performance optimizations
- Full feature set
Success Metrics
User Experience Metrics
- Cart abandonment rate
- Checkout completion rate
- Time to complete purchase
- User satisfaction scores
Technical Metrics
- Page load times
- Cart sync performance
- Order processing speed
- Error rates
Business Metrics
- Conversion rates
- Average order value
- Repeat purchase rate
- Customer retention
Future Enhancements
Long-term Vision
- Multi-currency support
- Advanced analytics
- AI-powered recommendations
- Mobile app development
- API for third-party integrations
Scalability Plans
- Microservices architecture
- Distributed storage
- Global relay network
- Cross-platform support
Conclusion
This roadmap provides a comprehensive plan for integrating the nostr-market-app purchasing functionality into the web-app. The phased approach ensures core functionality is delivered first while building toward a full-featured e-commerce platform.
The integration will maintain the decentralized, Nostr-based architecture while providing a professional, user-friendly shopping experience. Each phase builds upon the previous one, ensuring a smooth development process and consistent user experience.
Key success factors include:
- Maintaining the existing architecture and design patterns
- Ensuring seamless integration with current systems
- Prioritizing user experience and performance
- Implementing robust security measures
- Creating a scalable and maintainable codebase
This roadmap serves as a living document that should be updated as development progresses and new requirements emerge.