diff --git a/docs/02-modules/index.md b/docs/02-modules/index.md index 5b2a3c5..8b0fda2 100644 --- a/docs/02-modules/index.md +++ b/docs/02-modules/index.md @@ -74,6 +74,34 @@ interface ModulePlugin { **See:** [[base-module/index|πŸ“– Base Module Documentation]] +### **Wallet Module** πŸ’° +**Purpose:** Lightning Network wallet management with real-time updates +**Location:** `src/modules/wallet/` +**Dependencies:** `['base']` + +**Features:** +- **Real-time Balance Updates** - WebSocket connection to LNbits for instant balance sync +- **Payment Processing** - Send to Lightning invoices, addresses, and LNURL endpoints +- **Transaction Management** - Comprehensive history with real-time transaction updates +- **Payment Links** - Create LNURL payment links and Lightning addresses for receiving +- **Multi-wallet Support** - Manage multiple wallets with automatic selection +- **Battery Optimization** - Pauses WebSocket when app not visible to save battery + +**Key Components:** +- SendDialog for payment sending interface +- ReceiveDialog for payment link creation +- TransactionList with real-time updates +- BalanceDisplay with WebSocket synchronization +- PayLinkManager for LNURL link management + +**WebSocket Integration:** +- Real-time balance updates via LNbits WebSocket API +- Smart unit conversion handling (sats/millisats) +- Automatic reconnection with exponential backoff +- VisibilityService integration for mobile battery optimization + +**See:** [[wallet-module/index|πŸ“– Wallet Module Documentation]] + ### **Nostr Feed Module** πŸ“° **Purpose:** Social feed and content discovery **Location:** `src/modules/nostr-feed/` @@ -369,7 +397,8 @@ async dispose(): Promise { ### Module Documentation - **[[base-module/index|πŸ—οΈ Base Module]]** - Core infrastructure services -- **[[chat-module/index|πŸ’¬ Chat Module]]** - Encrypted messaging system +- **[[wallet-module/index|πŸ’° Wallet Module]]** - Lightning wallet with real-time updates +- **[[chat-module/index|πŸ’¬ Chat Module]]** - Encrypted messaging system - **[[events-module/index|🎟️ Events Module]]** - Lightning event ticketing - **[[market-module/index|πŸ›’ Market Module]]** - Nostr marketplace - **[[nostr-feed-module/index|πŸ“° Nostr Feed]]** - Social feed functionality diff --git a/docs/02-modules/wallet-module/index.md b/docs/02-modules/wallet-module/index.md new file mode 100644 index 0000000..84de301 --- /dev/null +++ b/docs/02-modules/wallet-module/index.md @@ -0,0 +1,512 @@ +# πŸ’° Wallet Module + +> **Lightning Network wallet management** with real-time balance updates, payment processing, and comprehensive transaction management integrated with LNbits. + +## Table of Contents + +- [[#Overview]] +- [[#Core Features]] +- [[#Architecture]] +- [[#Real-Time WebSocket Integration]] +- [[#Services]] +- [[#Components]] +- [[#Payment Processing]] +- [[#Configuration]] +- [[#Development Guide]] + +## Overview + +The Wallet Module provides comprehensive Lightning Network wallet functionality for the Ario application. It integrates with LNbits to handle payments, manage wallet balances, and provide real-time updates through WebSocket connections. + +### **Key Capabilities** +- **Real-time balance updates** via WebSocket connection to LNbits +- **Payment processing** for Lightning invoices, Lightning addresses, and LNURL +- **Transaction management** with comprehensive history and status tracking +- **Pay link creation** for receiving payments with LNURL and Lightning addresses +- **Multi-wallet support** with automatic wallet selection +- **Battery optimization** through VisibilityService integration + +### **Dependencies** +- `['base']` - Requires base module for authentication and core services +- **LNbits Server** - External Lightning wallet backend +- **PaymentService** - Core payment processing service + +## Core Features + +### **πŸ”„ Real-Time Balance Updates** +Automatic wallet balance synchronization without page refreshes: + +- **WebSocket Connection** - Direct connection to LNbits WebSocket API +- **Instant Updates** - Balance changes reflect immediately in UI +- **Smart Unit Conversion** - Handles LNbits sats/millisats conversion differences +- **Payment Notifications** - Toast notifications for incoming payments +- **Connection Management** - Automatic reconnection with exponential backoff + +### **πŸ’Έ Payment Processing** +Comprehensive Lightning payment handling: + +- **Lightning Invoices** - Pay BOLT11 invoices directly +- **Lightning Addresses** - Send to Lightning addresses (user@domain.com) +- **LNURL Pay** - Support for LNURL payment requests +- **Payment Validation** - Pre-flight checks for sufficient balance +- **Error Handling** - User-friendly error messages and recovery + +### **πŸ“Š Transaction Management** +Complete transaction history and tracking: + +- **Transaction History** - Chronological list of all payments +- **Real-time Updates** - New transactions appear instantly +- **Transaction Details** - Amount, description, timestamp, fees, status +- **Transaction Types** - Sent, received, pending, confirmed, failed +- **Search and Filter** - Find specific transactions quickly + +### **πŸ”— Payment Links (LNURL)** +Create reusable payment endpoints: + +- **LNURL Generation** - Create payment links for receiving +- **Lightning Addresses** - Generate username@domain addresses +- **Amount Ranges** - Set minimum and maximum payment amounts +- **Comments Support** - Allow payment comments +- **Link Management** - Create, view, and delete payment links + +## Architecture + +### **Service Layer** +``` +src/modules/wallet/services/ +β”œβ”€β”€ WalletService.ts # Core wallet operations +β”œβ”€β”€ WalletWebSocketService.ts # Real-time balance updates +└── WalletAPI.ts # LNbits API integration +``` + +### **Component Layer** +``` +src/modules/wallet/components/ +β”œβ”€β”€ SendDialog.vue # Payment sending interface +β”œβ”€β”€ ReceiveDialog.vue # Payment receiving interface +β”œβ”€β”€ TransactionList.vue # Transaction history display +β”œβ”€β”€ PayLinkManager.vue # LNURL payment link management +└── BalanceDisplay.vue # Wallet balance component +``` + +### **Views Layer** +``` +src/modules/wallet/views/ +└── WalletPage.vue # Main wallet interface +``` + +## Real-Time WebSocket Integration + +### **Connection Architecture** +The WebSocket service provides seamless real-time updates: + +```typescript +// WebSocket URL format +wss://your-lnbits-server/api/v1/ws/{walletInkey} + +// Connection lifecycle +β”Œβ”€ Authentication Event ──→ Connect WebSocket +β”œβ”€ Payment Received ─────→ Update Balance + Show Toast +β”œβ”€ Payment Sent ─────────→ Update Balance +β”œβ”€ Connection Lost ──────→ Automatic Reconnection +└─ App Hidden ───────────→ Pause (Battery Optimization) +``` + +### **Balance Update Logic** +Handles LNbits WebSocket behavior differences: + +```typescript +// Incoming payments: LNbits sends post-payment balance +if (payment.amount > 0) { + // Use balance as-is (already includes received amount) + updateBalance(websocket_balance) +} + +// Outgoing payments: LNbits sends pre-payment balance +if (payment.amount < 0) { + // Subtract payment amount from reported balance + final_balance = websocket_balance - payment_amount_sats + updateBalance(final_balance) +} +``` + +### **Connection Management** +- **Auto-reconnection** with exponential backoff (1s, 2s, 4s, 8s, 16s) +- **VisibilityService integration** for battery optimization +- **Connection health monitoring** with status indicators +- **Graceful disconnection** on logout + +### **Error Handling** +- Connection failures with retry logic +- Invalid wallet credentials handling +- Network interruption recovery +- WebSocket protocol error handling + +## Services + +### **WalletService** 🏦 +**Purpose:** Core wallet operations and transaction management +**Location:** `src/modules/wallet/services/WalletService.ts` +**Token:** `SERVICE_TOKENS.WALLET_SERVICE` + +**Key Features:** +- Send Lightning payments (invoices, addresses, LNURL) +- Create and manage LNURL payment links +- Transaction history management +- Payment link generation with Lightning addresses + +**Reactive State:** +```typescript +interface WalletService { + transactions: ComputedRef // Transaction history + payLinks: ComputedRef // Created payment links + isCreatingPayLink: ComputedRef // Pay link creation state + isSendingPayment: ComputedRef // Payment sending state + error: ComputedRef // Error state +} +``` + +**Key Methods:** +- `sendPayment(request: SendPaymentRequest)` - Send Lightning payment +- `createReceiveAddress(params)` - Create LNURL payment link +- `deletePayLink(linkId: string)` - Remove payment link +- `refresh()` - Reload transactions and payment links + +### **WalletWebSocketService** ⚑ +**Purpose:** Real-time wallet balance updates via WebSocket +**Location:** `src/modules/wallet/services/WalletWebSocketService.ts` +**Token:** `SERVICE_TOKENS.WALLET_WEBSOCKET_SERVICE` + +**Key Features:** +- WebSocket connection to LNbits +- Real-time balance updates +- Payment notification handling +- Connection health management +- Battery optimization via VisibilityService + +**Reactive State:** +```typescript +interface WalletWebSocketService { + isConnected: Ref // Connection status + connectionStatus: Ref // Connection state +} +``` + +**Connection States:** +- `disconnected` - Not connected +- `connecting` - Connection in progress +- `connected` - Successfully connected +- `reconnecting` - Attempting to reconnect +- `error` - Connection failed +- `failed` - Max reconnection attempts reached + +**Key Methods:** +- `reconnect()` - Manual reconnection trigger +- `disconnect()` - Graceful disconnection +- `cleanup()` - Service disposal + +### **PaymentService Integration** πŸ’³ +The wallet module integrates with the core PaymentService: + +**Shared Functionality:** +- Wallet balance management via `PaymentService.updateWalletBalance()` +- Preferred wallet selection with `PaymentService.getPreferredWallet()` +- Admin/invoice key access for API operations +- Multi-wallet support with consistent selection logic + +## Components + +### **SendDialog.vue** πŸ“€ +Payment sending interface with comprehensive validation: + +**Features:** +- Support for Lightning invoices, addresses, and LNURL +- Amount validation against available balance +- Payment request parsing and validation +- Real-time fee estimation +- Error handling with user-friendly messages + +**Form Fields:** +- Destination (invoice, address, or LNURL) +- Amount (when not specified in invoice) +- Comment (for Lightning addresses) + +### **ReceiveDialog.vue** πŸ“₯ +Payment receiving interface for creating payment requests: + +**Features:** +- LNURL payment link creation +- Lightning address generation +- Customizable amount ranges +- Comment support configuration +- QR code generation for sharing + +**Form Fields:** +- Description +- Minimum amount +- Maximum amount +- Username (for Lightning address) +- Allow comments toggle + +### **TransactionList.vue** πŸ“‹ +Comprehensive transaction history display: + +**Features:** +- Chronological transaction listing +- Real-time transaction updates +- Transaction status indicators +- Amount formatting with proper units +- Transaction type differentiation (sent/received) +- Fee information display + +### **BalanceDisplay.vue** πŸ’° +Wallet balance component with real-time updates: + +**Features:** +- Real-time balance updates via WebSocket +- Multiple unit display (sats, millisats) +- Loading state indicators +- Connection status awareness + +## Payment Processing + +### **Payment Flow Architecture** +``` +User Action ──→ Validation ──→ Payment ──→ Confirmation ──→ UI Update + β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ └─ Real-time via WebSocket + β”‚ β”‚ β”‚ └─ Transaction recorded + β”‚ β”‚ └─ LNbits API call + β”‚ └─ Balance check, format validation + └─ Send/Receive dialog interaction +``` + +### **Payment Types Supported** + +#### **Lightning Invoices (BOLT11)** +```typescript +// Direct invoice payment +await walletService.sendPayment({ + destination: "lnbc1000n1p3xh4v...", + amount: 1000 // Optional if invoice has amount +}) +``` + +#### **Lightning Addresses** +```typescript +// Lightning address payment +await walletService.sendPayment({ + destination: "user@stacker.news", + amount: 1000, + comment: "Great post!" +}) +``` + +#### **LNURL Pay** +```typescript +// LNURL payment +await walletService.sendPayment({ + destination: "LNURL1DP68GURN8GHJ7UM9WFMXJCM99E3K7MF0V9CXJ0M385EKVCENXC6R2C35XVUKXEFCV5MKVV34X5EKZD3EV56NYD3HXQURZEPEXEJXXEPNXSCRVWFNV9NXZCN9XQ6XYEFHVGCXXCMYXYMNSERXFQ5FNS", + amount: 1000 +}) +``` + +### **Error Handling** +Comprehensive error handling for payment failures: + +- **Insufficient balance** - Clear messaging with current balance +- **Invalid payment request** - Format validation errors +- **Network failures** - Retry options and offline handling +- **Payment routing failures** - Lightning network routing errors +- **Timeout handling** - Payment timeout with status updates + +## Configuration + +### **Module Configuration** +Configure the wallet module in `src/app.config.ts`: + +```typescript +modules: { + wallet: { + enabled: true, + config: { + // WebSocket configuration + websocket: { + enabled: true, // Enable real-time updates + reconnectDelay: 1000, // Initial reconnection delay (ms) + maxReconnectAttempts: 5 // Maximum reconnection attempts + }, + + // Payment configuration + payments: { + defaultUnit: 'sats', // Default amount unit + showFees: true, // Display fee information + confirmLarge: 10000 // Confirm payments above this amount + }, + + // UI configuration + ui: { + showBalance: true, // Display balance in UI + showTransactions: true, // Show transaction history + transactionLimit: 100 // Max transactions to display + } + } + } +} +``` + +### **Environment Variables** +Required environment setup: + +```bash +# LNbits server URL +VITE_LNBITS_BASE_URL=https://your-lnbits-server.com + +# Optional: Default wallet configuration +VITE_DEFAULT_CURRENCY=sats +VITE_PAYMENT_TIMEOUT=30000 +``` + +## Development Guide + +### **Adding New Payment Types** +To add support for new payment methods: + +1. **Extend SendPaymentRequest interface:** +```typescript +interface SendPaymentRequest { + destination: string + amount: number + comment?: string + newPaymentType?: NewPaymentParams // Add new type +} +``` + +2. **Update WalletService.sendPayment():** +```typescript +async sendPayment(request: SendPaymentRequest): Promise { + // Add detection logic + if (this.isNewPaymentType(request.destination)) { + return this.handleNewPaymentType(request) + } + // ... existing logic +} +``` + +3. **Add validation and processing:** +```typescript +private isNewPaymentType(destination: string): boolean { + // Detection logic +} + +private async handleNewPaymentType(request: SendPaymentRequest): Promise { + // Processing logic +} +``` + +### **Extending Transaction Types** +To add new transaction types: + +1. **Update PaymentTransaction interface:** +```typescript +interface PaymentTransaction { + // ... existing fields + type: 'sent' | 'received' | 'new_type' + metadata?: NewTypeMetadata +} +``` + +2. **Update transaction mapping:** +```typescript +private mapPaymentToTransaction(payment: any): PaymentTransaction { + // Add new type detection and mapping +} +``` + +### **Custom WebSocket Handlers** +To add custom WebSocket message handling: + +```typescript +class WalletWebSocketService extends BaseService { + private handleMessage(event: MessageEvent): void { + const data = JSON.parse(event.data) + + // Handle existing message types + if (data.payment) { + this.handlePaymentNotification(data.payment) + } + + // Add custom message handling + if (data.custom_event) { + this.handleCustomEvent(data.custom_event) + } + } + + private handleCustomEvent(event: CustomEvent): void { + // Custom event processing + } +} +``` + +### **Testing Wallet Functionality** + +#### **Unit Tests** +```typescript +describe('WalletService', () => { + let service: WalletService + + beforeEach(() => { + service = new WalletService() + }) + + it('should send Lightning payment', async () => { + const request = { + destination: 'lnbc1000n...', + amount: 1000 + } + + const result = await service.sendPayment(request) + expect(result).toBe(true) + }) +}) +``` + +#### **Integration Tests** +```typescript +describe('Wallet Integration', () => { + it('should update balance after payment', async () => { + const websocketService = new WalletWebSocketService() + const paymentService = new PaymentService() + + // Mock payment notification + await websocketService.handlePaymentNotification({ + amount: 1000, + wallet_balance: 5000 + }) + + expect(paymentService.totalBalance).toBe(5000000) // millisats + }) +}) +``` + +## See Also + +### Related Documentation +- **[[../base-module/index|πŸ—οΈ Base Module]]** - Authentication and core services +- **[[../../03-core-services/payment-service|πŸ’³ Payment Service]]** - Core payment processing +- **[[websocket-integration|⚑ WebSocket Integration]]** - Real-time update details +- **[[payment-processing|πŸ’Έ Payment Processing]]** - Payment flow documentation + +### API References +- **[[../../05-api-reference/lnbits-api|⚑ LNbits API]]** - Backend API integration +- **[[../../05-api-reference/lightning-payments|πŸ’° Lightning Payments]]** - Payment protocol details + +### Development Guides +- **[[../../04-development/testing|πŸ§ͺ Testing Guide]]** - Testing strategies +- **[[../../04-development/debugging|πŸ› Debugging]]** - Troubleshooting guide + +--- + +**Tags:** #wallet #lightning #payments #websocket #real-time #module +**Last Updated:** 2025-09-18 +**Author:** Development Team \ No newline at end of file diff --git a/docs/02-modules/wallet-module/websocket-integration.md b/docs/02-modules/wallet-module/websocket-integration.md new file mode 100644 index 0000000..386a649 --- /dev/null +++ b/docs/02-modules/wallet-module/websocket-integration.md @@ -0,0 +1,590 @@ +# ⚑ WebSocket Integration + +> **Real-time wallet balance updates** through LNbits WebSocket API with automatic reconnection, battery optimization, and smart unit conversion handling. + +## Table of Contents + +- [[#Overview]] +- [[#Architecture]] +- [[#Connection Management]] +- [[#Message Processing]] +- [[#Balance Update Logic]] +- [[#Error Handling]] +- [[#Battery Optimization]] +- [[#Configuration]] +- [[#Troubleshooting]] + +## Overview + +The Wallet WebSocket integration provides real-time synchronization between the Ario wallet interface and the LNbits Lightning backend. This enables instant balance updates and payment notifications without requiring page refreshes or manual polling. + +### **Key Benefits** +- **Instant UI Updates** - Balance changes appear immediately when payments are sent or received +- **Payment Notifications** - Toast notifications for incoming payments +- **Battery Efficient** - Pauses when app is not visible to save mobile battery +- **Reliable Connection** - Automatic reconnection with exponential backoff +- **Smart Conversion** - Handles LNbits sats/millisats behavior differences + +### **WebSocket Endpoint** +``` +wss://your-lnbits-server/api/v1/ws/{walletInkey} +``` + +Where `walletInkey` is the invoice/readonly key for the wallet. + +## Architecture + +### **Service Integration** +``` +β”Œβ”€ WalletWebSocketService ─┐ β”Œβ”€ PaymentService ─┐ β”Œβ”€ UI Components ─┐ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β€’ WebSocket Connection │───▢│ β€’ Balance Update │───▢│ β€’ Balance Displayβ”‚ +β”‚ β€’ Message Processing β”‚ β”‚ β€’ Wallet Mgmt β”‚ β”‚ β€’ Toast Notifications +β”‚ β€’ Reconnection Logic β”‚ β”‚ β€’ Multi-wallet β”‚ β”‚ β€’ Transaction List β”‚ +β”‚ β€’ Battery Optimization β”‚ β”‚ β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β”‚ β”‚ + β–Ό β–Ό +β”Œβ”€ VisibilityService ─────┐ β”Œβ”€ AuthService ──────┐ +β”‚ β”‚ β”‚ β”‚ +β”‚ β€’ App Visibility β”‚ β”‚ β€’ User Wallets β”‚ +β”‚ β€’ Connection Pausing β”‚ β”‚ β€’ Authentication β”‚ +β”‚ β€’ Resume Management β”‚ β”‚ β€’ Wallet Selection β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### **Dependency Graph** +``` +WalletWebSocketService +β”œβ”€β”€ BaseService (lifecycle management) +β”œβ”€β”€ PaymentService (balance updates) +β”œβ”€β”€ WalletService (transaction management) +β”œβ”€β”€ AuthService (wallet credentials) +└── VisibilityService (battery optimization) +``` + +### **Initialization Flow** +``` +1. Module Installation + β”œβ”€β”€ Create WalletWebSocketService instance + β”œβ”€β”€ Register in DI container + └── Initialize with dependencies + +2. Service Initialization + β”œβ”€β”€ Wait for dependencies (AuthService, PaymentService) + β”œβ”€β”€ Register with VisibilityService + β”œβ”€β”€ Set up auth event listeners + └── Attempt initial connection + +3. Authentication Events + β”œβ”€β”€ auth:login β†’ Connect WebSocket + └── auth:logout β†’ Disconnect WebSocket + +4. Connection Lifecycle + β”œβ”€β”€ Connect β†’ Update status β†’ Listen for messages + β”œβ”€β”€ Message β†’ Process β†’ Update balance + β”œβ”€β”€ Disconnect β†’ Attempt reconnection + └── Visibility Change β†’ Pause/Resume +``` + +## Connection Management + +### **Connection Lifecycle** + +#### **Initial Connection** +```typescript +// Triggered by authentication events +eventBus.on('auth:login', () => { + setTimeout(() => { + this.connectIfNeeded() + }, 500) // Small delay for auth processing +}) +``` + +#### **Connection Process** +```typescript +private async connect(walletInkey: string): Promise { + // 1. Build WebSocket URL + const baseUrl = import.meta.env.VITE_LNBITS_BASE_URL + const wsProtocol = baseUrl.startsWith('https') ? 'wss:' : 'ws:' + const host = baseUrl.replace(/^https?:\/\//, '').replace(/\/$/, '') + const wsUrl = `${wsProtocol}//${host}/api/v1/ws/${walletInkey}` + + // 2. Create WebSocket connection + this.ws = new WebSocket(wsUrl) + + // 3. Set up event handlers + this.ws.onopen = this.handleOpen.bind(this) + this.ws.onmessage = this.handleMessage.bind(this) + this.ws.onclose = this.handleClose.bind(this) + this.ws.onerror = this.handleWebSocketError.bind(this) +} +``` + +### **Reconnection Strategy** + +#### **Exponential Backoff** +```typescript +private scheduleReconnect(): void { + if (this.reconnectAttempts >= this.config.maxReconnectAttempts) { + this.connectionStatus.value = 'failed' + return + } + + // Exponential backoff: 1s, 2s, 4s, 8s, 16s + const delay = this.config.reconnectDelay * Math.pow(2, this.reconnectAttempts) + this.reconnectAttempts++ + + this.reconnectTimer = setTimeout(() => { + this.connectIfNeeded() + }, delay) +} +``` + +#### **Connection Health Monitoring** +```typescript +// Connection states tracked +enum ConnectionStatus { + DISCONNECTED = 'disconnected', + CONNECTING = 'connecting', + CONNECTED = 'connected', + RECONNECTING = 'reconnecting', + ERROR = 'error', + FAILED = 'failed' +} +``` + +### **Graceful Disconnection** +```typescript +public disconnect(): void { + // Clear reconnection timer + if (this.reconnectTimer) { + clearTimeout(this.reconnectTimer) + this.reconnectTimer = null + } + + // Close WebSocket with normal closure code + if (this.ws) { + this.ws.close(1000, 'Client disconnect') + this.ws = null + } + + // Update reactive state + this.isConnected.value = false + this.connectionStatus.value = 'disconnected' +} +``` + +## Message Processing + +### **Message Structure** +LNbits WebSocket sends messages in this format: +```json +{ + "wallet_balance": 1000820, // Balance in sats + "payment": { // Payment details (optional) + "amount": 100000, // Amount in millisats (positive = received, negative = sent) + "payment_hash": "abc123...", + "description": "Payment description", + "time": 1694123456, + "pending": false + } +} +``` + +### **Message Handler** +```typescript +private handleMessage(event: MessageEvent): void { + try { + const data = JSON.parse(event.data) + + // Process payment notification first + if (data.payment) { + this.handlePaymentNotification(data.payment) + } + + // Process balance update + if (data.wallet_balance !== undefined) { + this.processBalanceUpdate(data) + } + } catch (error) { + console.error('Failed to parse WebSocket message:', error) + } +} +``` + +### **Payment Notification Processing** +```typescript +private handlePaymentNotification(payment: any): void { + // Add to transaction history via WalletService + if (this.walletService?.addTransaction) { + this.walletService.addTransaction(payment) + } + + // Show toast notification for incoming payments + if (payment.amount > 0 && !payment.pending) { + const amountSats = Math.abs(payment.amount / 1000) + this.toast.success(`Received ${amountSats} sats!`) + } +} +``` + +## Balance Update Logic + +### **LNbits WebSocket Behavior** +LNbits has different behavior for incoming vs outgoing payments: + +- **Incoming payments**: WebSocket sends **post-payment balance** (already includes received amount) +- **Outgoing payments**: WebSocket sends **pre-payment balance** (before deduction) + +### **Smart Balance Conversion** +```typescript +private processBalanceUpdate(data: any): void { + let finalBalance = data.wallet_balance // Balance in sats from LNbits + + if (data.payment) { + if (data.payment.amount < 0) { + // Outgoing payment - LNbits sends pre-payment balance + // We need to subtract the payment amount + const paymentSats = Math.abs(data.payment.amount) / 1000 + finalBalance = data.wallet_balance - paymentSats + + console.log('Outgoing payment adjustment:', { + originalBalance: data.wallet_balance, + paymentSats: paymentSats, + finalBalance: finalBalance + }) + } else if (data.payment.amount > 0) { + // Incoming payment - LNbits sends post-payment balance + // Use balance as-is + console.log('Incoming payment - using balance as-is:', data.wallet_balance) + } + } + + // Update balance via PaymentService + this.updateWalletBalance(finalBalance) +} +``` + +### **Balance Update Integration** +```typescript +private updateWalletBalance(balanceSats: number): void { + // Convert sats to millisats for internal storage + const balanceMsat = balanceSats * 1000 + + // Get connected wallet ID + const wallet = this.paymentService?.getPreferredWallet?.() + const walletId = wallet?.id + + // Update via PaymentService for consistency + if (this.paymentService?.updateWalletBalance) { + this.paymentService.updateWalletBalance(balanceMsat, walletId) + } +} +``` + +### **Unit Conversion Table** +| Source | Unit | Internal Storage | Display | +|--------|------|------------------|---------| +| LNbits WebSocket | sats | millisats Γ— 1000 | sats Γ· 1000 | +| LNbits API | millisats | millisats | sats Γ· 1000 | +| Payment amounts | millisats | millisats | sats Γ· 1000 | +| UI display | sats | millisats Γ· 1000 | sats | + +## Error Handling + +### **Connection Errors** +```typescript +private handleWebSocketError(event: Event): void { + console.error('WebSocket error:', event) + this.connectionStatus.value = 'error' + + // Log additional error details + if (this.ws) { + console.error('WebSocket state:', this.ws.readyState) + console.error('WebSocket URL:', this.ws.url) + } +} +``` + +### **Connection Close Handling** +```typescript +private handleClose(event: CloseEvent): void { + console.log('WebSocket closed:', event.code, event.reason) + + this.isConnected.value = false + this.connectionStatus.value = 'disconnected' + this.ws = null + + // Only reconnect if not a normal closure + if (event.code !== 1000) { + this.scheduleReconnect() + } +} +``` + +### **Error Recovery Strategies** + +#### **Authentication Errors (Code 1002)** +```typescript +// Invalid wallet credentials - clear and require re-authentication +if (event.code === 1002) { + this.authService?.logout() + this.toast.error('Wallet credentials invalid. Please login again.') +} +``` + +#### **Network Errors** +```typescript +// Network connectivity issues - retry with backoff +if (!navigator.onLine) { + window.addEventListener('online', () => { + this.reconnectAttempts = 0 + this.connectIfNeeded() + }, { once: true }) +} +``` + +#### **Server Errors (Code 1011)** +```typescript +// Server internal error - longer backoff +if (event.code === 1011) { + this.config.reconnectDelay = 5000 // Increase delay + this.scheduleReconnect() +} +``` + +## Battery Optimization + +### **VisibilityService Integration** +Mobile browsers suspend WebSocket connections when the app loses visibility. The WebSocket service integrates with VisibilityService to handle this efficiently: + +```typescript +protected async onInitialize(): Promise { + // Register with VisibilityService + if (this.visibilityService) { + this.visibilityService.registerService( + this.metadata.name, + this.onResume.bind(this), + this.onPause.bind(this) + ) + } +} +``` + +### **Pause Behavior** +```typescript +private async onPause(): Promise { + console.log('WebSocket pausing - app not visible') + + // Disconnect to save battery + this.disconnect() +} +``` + +### **Resume Behavior** +```typescript +private async onResume(): Promise { + console.log('WebSocket resuming - app visible') + + // Reconnect if not already connected + if (!this.isConnected.value) { + this.reconnectAttempts = 0 // Reset attempt counter + await this.connectIfNeeded() + } +} +``` + +### **Visibility States** +| App State | WebSocket Action | Battery Impact | +|-----------|------------------|----------------| +| Visible | Connected | Normal | +| Hidden/Background | Disconnected | Minimal | +| Tab Switch | Disconnected | Minimal | +| Resume | Reconnect | Brief spike | + +## Configuration + +### **WebSocket Configuration** +Configure WebSocket behavior in module config: + +```typescript +// app.config.ts +modules: { + wallet: { + enabled: true, + config: { + websocket: { + enabled: true, // Enable WebSocket functionality + reconnectDelay: 1000, // Initial reconnection delay (ms) + maxReconnectAttempts: 5 // Maximum reconnection attempts + } + } + } +} +``` + +### **Environment Variables** +```bash +# LNbits server URL - must be accessible for WebSocket +VITE_LNBITS_BASE_URL=https://your-lnbits-server.com + +# Development mode - enables verbose WebSocket logging +VITE_DEV_MODE=true +``` + +### **Runtime Configuration Access** +```typescript +// Access configuration in service +const appConfig = (window as any).appConfig +if (appConfig?.modules?.wallet?.config?.websocket) { + this.config = { ...this.config, ...appConfig.modules.wallet.config.websocket } +} +``` + +## Troubleshooting + +### **Common Issues** + +#### **WebSocket Connection Fails** +**Symptoms:** Connection status shows 'error' or 'failed' + +**Debugging Steps:** +1. Check LNbits server accessibility +2. Verify VITE_LNBITS_BASE_URL environment variable +3. Check browser network tab for WebSocket connection attempts +4. Verify wallet credentials (inkey) are valid + +**Solutions:** +```bash +# Test LNbits server connectivity +curl https://your-lnbits-server.com/api/v1/wallet + +# Check WebSocket endpoint manually +# Open browser console and test: +const ws = new WebSocket('wss://your-server/api/v1/ws/your-inkey') +``` + +#### **Balance Not Updating** +**Symptoms:** Payments are processed but UI balance doesn't change + +**Debugging Steps:** +1. Check browser console for WebSocket messages +2. Verify PaymentService is receiving updateWalletBalance calls +3. Check if wallet ID matches between services + +**Debug Logging:** +```typescript +// Enable debug logging in WalletWebSocketService +console.log('WebSocket message:', data) +console.log('Balance update:', { old: oldBalance, new: finalBalance }) +``` + +#### **Frequent Disconnections** +**Symptoms:** WebSocket constantly reconnecting + +**Potential Causes:** +- Network instability +- LNbits server restarts +- Proxy/firewall interference +- Mobile browser background throttling + +**Solutions:** +- Increase reconnectDelay in configuration +- Check server logs for connection issues +- Verify VisibilityService is working correctly + +### **Diagnostic Tools** + +#### **Connection Status Component** +```vue + + + +``` + +#### **Debug Console Commands** +```javascript +// Access services from browser console +const wsService = window.__DI_CONTAINER__.get('WALLET_WEBSOCKET_SERVICE') + +// Check connection status +console.log('Connected:', wsService.isConnected.value) +console.log('Status:', wsService.connectionStatus.value) + +// Manual reconnection +wsService.reconnect() + +// View configuration +console.log('Config:', wsService.config) +``` + +### **Performance Monitoring** + +#### **Connection Metrics** +```typescript +// Track connection performance +class ConnectionMetrics { + private connectionAttempts = 0 + private successfulConnections = 0 + private totalDowntime = 0 + private lastConnectTime = 0 + + onConnectionAttempt() { + this.connectionAttempts++ + this.lastConnectTime = Date.now() + } + + onConnectionSuccess() { + this.successfulConnections++ + const connectTime = Date.now() - this.lastConnectTime + console.log(`Connected in ${connectTime}ms`) + } + + getSuccessRate(): number { + return this.successfulConnections / this.connectionAttempts + } +} +``` + +## See Also + +### Related Documentation +- **[[index|πŸ’° Wallet Module Overview]]** - Main wallet module documentation +- **[[../../03-core-services/visibility-service|πŸ‘οΈ Visibility Service]]** - Battery optimization service +- **[[../../03-core-services/payment-service|πŸ’³ Payment Service]]** - Core payment processing + +### API References +- **[[../../05-api-reference/lnbits-api|⚑ LNbits API]]** - Backend API documentation +- **[[../../05-api-reference/websocket-protocol|πŸ”Œ WebSocket Protocol]]** - WebSocket message formats + +### Development Guides +- **[[../../04-development/testing|πŸ§ͺ Testing Guide]]** - Testing WebSocket functionality +- **[[../../04-development/debugging|πŸ› Debugging]]** - Debugging WebSocket issues + +--- + +**Tags:** #websocket #real-time #lightning #lnbits #battery-optimization #connection-management +**Last Updated:** 2025-09-18 +**Author:** Development Team \ No newline at end of file diff --git a/docs/03-core-services/index.md b/docs/03-core-services/index.md index e1d36c7..55f7aa2 100644 --- a/docs/03-core-services/index.md +++ b/docs/03-core-services/index.md @@ -80,6 +80,43 @@ interface AuthService { **See:** [[authentication|πŸ“– Authentication Service Documentation]] +### **PaymentService** πŸ’³ +**Purpose:** Centralized Lightning payment processing and wallet management +**Location:** `src/core/services/PaymentService.ts` +**Token:** `SERVICE_TOKENS.PAYMENT_SERVICE` + +**Key Features:** +- **Wallet Management** - Multi-wallet support with preferred wallet selection +- **Payment Processing** - Lightning invoices, QR code generation, and external wallet handling +- **Balance Management** - Real-time wallet balance updates and tracking +- **Payment Validation** - Balance checking and payment amount validation +- **Error Handling** - Consistent payment error handling and user feedback + +**Reactive State:** +```typescript +interface PaymentService { + isProcessingPayment: ComputedRef // Payment in progress + paymentError: ComputedRef // Payment error state + totalBalance: number // Total balance across wallets (getter) + hasWalletWithBalance: boolean // Wallet availability check (getter) +} +``` + +**Key Methods:** +- `payWithWallet(paymentRequest, amount?, options?)` - Process Lightning payment +- `generateQRCode(paymentRequest, options?)` - Generate payment QR codes +- `openExternalWallet(paymentRequest)` - Launch external Lightning wallet +- `updateWalletBalance(balanceMsat, walletId?)` - Update wallet balance from WebSocket +- `getPreferredWallet()` - Get the primary wallet for operations +- `getWalletWithBalance(requiredAmount?)` - Find wallet with sufficient balance + +**Wallet Selection Logic:** +- Always uses first wallet (`wallets[0]`) for consistency across modules +- Provides helper methods for wallet selection and balance checking +- Integrates with AuthService for wallet credentials and management + +**See:** [[payment-service|πŸ“– Payment Service Documentation]] + ### **RelayHub** 🌐 **Purpose:** Centralized Nostr relay connection management **Location:** `src/modules/base/nostr/relay-hub.ts` @@ -222,6 +259,74 @@ interface EventBusEvents { **See:** [[../01-architecture/event-bus|πŸ“– Event Bus Communication Documentation]] +### **WalletService** 🏦 +**Purpose:** Wallet operations and transaction management +**Location:** `src/modules/wallet/services/WalletService.ts` +**Token:** `SERVICE_TOKENS.WALLET_SERVICE` + +**Key Features:** +- **Payment Operations** - Send Lightning payments to invoices, addresses, and LNURL +- **Payment Link Management** - Create and manage LNURL payment links and Lightning addresses +- **Transaction History** - Load and manage comprehensive transaction history +- **Real-time Updates** - Add new transactions from WebSocket notifications + +**Reactive State:** +```typescript +interface WalletService { + transactions: ComputedRef // Transaction history + payLinks: ComputedRef // Created payment links + isCreatingPayLink: ComputedRef // Pay link creation state + isSendingPayment: ComputedRef // Payment sending state + error: ComputedRef // Error state +} +``` + +**Key Methods:** +- `sendPayment(request: SendPaymentRequest)` - Send Lightning payment +- `createReceiveAddress(params)` - Create LNURL payment link with Lightning address +- `deletePayLink(linkId: string)` - Remove payment link +- `addTransaction(payment)` - Add transaction from WebSocket notification +- `refresh()` - Reload transactions and payment links + +### **WalletWebSocketService** ⚑ +**Purpose:** Real-time wallet balance updates via WebSocket +**Location:** `src/modules/wallet/services/WalletWebSocketService.ts` +**Token:** `SERVICE_TOKENS.WALLET_WEBSOCKET_SERVICE` + +**Key Features:** +- **Real-time Connection** - WebSocket connection to LNbits for instant updates +- **Balance Synchronization** - Smart balance updates with unit conversion handling +- **Payment Notifications** - Toast notifications for incoming payments +- **Connection Management** - Automatic reconnection with exponential backoff +- **Battery Optimization** - VisibilityService integration for mobile efficiency + +**Reactive State:** +```typescript +interface WalletWebSocketService { + isConnected: Ref // WebSocket connection status + connectionStatus: Ref // Connection state details +} +``` + +**Connection States:** +- `disconnected` - Not connected +- `connecting` - Connection in progress +- `connected` - Successfully connected +- `reconnecting` - Attempting to reconnect +- `error` - Connection failed +- `failed` - Max reconnection attempts reached + +**Key Methods:** +- `reconnect()` - Manual reconnection trigger +- `disconnect()` - Graceful disconnection +- `cleanup()` - Service disposal + +**WebSocket Integration:** +- Connects to `wss://lnbits-server/api/v1/ws/{walletInkey}` +- Handles incoming/outgoing payment balance differences +- Updates PaymentService with converted balance (sats β†’ millisats) +- Integrates with WalletService for transaction updates + ## Service Lifecycle ### **Initialization Phase** @@ -479,9 +584,11 @@ describe('Service Integration', () => { ### Service Documentation - **[[authentication|πŸ” Authentication Service]]** - User identity and session management +- **[[payment-service|πŸ’³ Payment Service]]** - Lightning payment processing and wallet management - **[[storage-service|πŸ’Ύ Storage Service]]** - User-scoped data persistence - **[[toast-service|πŸ“’ Toast Service]]** - User notifications and feedback - **[[visibility-service|πŸ‘οΈ Visibility Service]]** - Dynamic UI component control +- **[[../02-modules/wallet-module/index|πŸ’° Wallet Services]]** - WalletService and WebSocket integration ### Architecture References - **[[../01-architecture/dependency-injection|βš™οΈ Dependency Injection]]** - DI container system diff --git a/docs/03-core-services/payment-service.md b/docs/03-core-services/payment-service.md new file mode 100644 index 0000000..39c978b --- /dev/null +++ b/docs/03-core-services/payment-service.md @@ -0,0 +1,507 @@ +# πŸ’³ Payment Service + +> **Centralized Lightning payment processing** with wallet management, QR code generation, and real-time balance tracking integrated with LNbits. + +## Table of Contents + +- [[#Overview]] +- [[#Architecture]] +- [[#Payment Processing]] +- [[#Wallet Management]] +- [[#Balance Management]] +- [[#QR Code Generation]] +- [[#Error Handling]] +- [[#Integration with WebSocket]] +- [[#API Reference]] + +## Overview + +The PaymentService is a core infrastructure service that centralizes all Lightning Network payment operations in the Ario application. It provides a clean abstraction layer over LNbits operations and manages wallet state across all modules. + +### **Key Responsibilities** +- **Payment Processing** - Handle Lightning invoices, external wallets, and payment validation +- **Wallet Management** - Multi-wallet support with consistent wallet selection +- **Balance Tracking** - Real-time balance updates from WebSocket integration +- **QR Code Generation** - Payment request and custom data QR codes +- **Error Handling** - Consistent payment error handling and user feedback + +### **Service Integration** +``` +β”Œβ”€ UI Components ─┐ β”Œβ”€ PaymentService ─┐ β”Œβ”€ External Services ─┐ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β€’ Send Dialog │───▢│ β€’ Payment Logic │───▢│ β€’ LNbits API β”‚ +β”‚ β€’ Balance Displayβ”‚ β”‚ β€’ Wallet Mgmt β”‚ β”‚ β€’ External Wallets β”‚ +β”‚ β€’ QR Generator β”‚ β”‚ β€’ Balance State β”‚ β”‚ β€’ QR Library β”‚ +β”‚ β”‚ β”‚ β€’ Error Handling β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€ AuthService ─────┐ + β”‚ β”‚ + β”‚ β€’ User Wallets β”‚ + β”‚ β€’ Authentication β”‚ + β”‚ β€’ Wallet Keys β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Architecture + +### **Service Structure** +```typescript +export class PaymentService extends BaseService { + // Service metadata + protected readonly metadata = { + name: 'PaymentService', + version: '1.0.0', + dependencies: ['AuthService'] + } + + // Reactive state + private _isProcessingPayment = ref(false) + private _paymentError = ref(null) + + // Public computed state + public readonly isProcessingPayment = computed(() => this._isProcessingPayment.value) + public readonly paymentError = computed(() => this._paymentError.value) +} +``` + +### **Dependencies** +- **AuthService** - User authentication and wallet access +- **BaseService** - Service lifecycle and error handling +- **Vue Reactivity** - Reactive state management + +### **External Integrations** +- **LNbits API** - Lightning wallet backend +- **QRCode Library** - QR code generation +- **External Wallets** - Lightning wallet applications +- **Browser APIs** - Clipboard, window.open for external wallets + +## Payment Processing + +### **Payment Types Supported** + +#### **Lightning Invoices (BOLT11)** +Process Lightning payment requests directly: +```typescript +await paymentService.payWithWallet( + 'lnbc1000n1p3xh4v...', // Lightning invoice + undefined, // Amount already in invoice + { + successMessage: 'Payment sent successfully!', + showToast: true + } +) +``` + +#### **External Wallet Fallback** +Automatically fall back to external wallets when user wallet lacks balance: +```typescript +// Automatic payment handling with fallback +const result = await paymentService.handlePayment( + paymentRequest, + requiredAmount, + { successMessage: 'Payment completed!' } +) + +// Returns PaymentResult for wallet payments, null for external wallet +if (result) { + console.log('Paid with user wallet:', result.payment_hash) +} else { + console.log('Opened external wallet') +} +``` + +### **Payment Flow** +``` +1. Payment Request Validation + β”œβ”€β”€ Check payment request format + β”œβ”€β”€ Extract amount if present + └── Validate against available balance + +2. Wallet Selection + β”œβ”€β”€ Get preferred wallet + β”œβ”€β”€ Check sufficient balance + └── Retrieve wallet credentials + +3. Payment Execution + β”œβ”€β”€ Call LNbits payment API + β”œβ”€β”€ Handle response/errors + └── Update UI state + +4. Completion Handling + β”œβ”€β”€ Show success/error notifications + β”œβ”€β”€ Reset payment state + └── Emit completion events +``` + +### **Payment Options** +```typescript +interface PaymentOptions { + successMessage?: string // Custom success message + errorMessage?: string // Custom error message + showToast?: boolean // Show toast notifications (default: true) +} +``` + +## Wallet Management + +### **Multi-Wallet Support** +PaymentService provides consistent wallet selection across all modules: + +```typescript +// Preferred wallet selection (always first wallet) +const wallet = paymentService.getPreferredWallet() +// Returns: wallets[0] or null if no wallets + +// Wallet with sufficient balance +const wallet = paymentService.getWalletWithBalance(1000) // 1000 sats +// Returns: first wallet with >= 1000 sats or null + +// Wallet credentials access +const adminKey = paymentService.getPreferredWalletAdminKey() +const invoiceKey = paymentService.getPreferredWalletInvoiceKey() +``` + +### **Wallet Selection Logic** +The service follows a consistent wallet selection strategy: + +1. **Preferred Wallet**: Always use `wallets[0]` for consistency +2. **Balance Checking**: Check if preferred wallet has sufficient balance +3. **Fallback Strategy**: No automatic fallback - use external wallet instead +4. **Credential Access**: Provide admin/invoice keys for API operations + +### **Balance Access** +```typescript +// Total balance across all wallets (in millisats) +const totalBalance = paymentService.totalBalance + +// Check if any wallet has balance +const hasBalance = paymentService.hasWalletWithBalance + +// Balance formatted for display +const balanceSats = Math.round(totalBalance / 1000) +``` + +## Balance Management + +### **Real-Time Balance Updates** +PaymentService receives balance updates from WalletWebSocketService: + +```typescript +// Called by WebSocket service when balance changes +paymentService.updateWalletBalance(balanceMsat, walletId) +``` + +### **Balance Update Logic** +```typescript +updateWalletBalance(balanceMsat: number, walletId?: string): void { + // Determine target wallet + let walletToUpdate + if (walletId) { + walletToUpdate = this.authService.user.value.wallets.find(w => w.id === walletId) + } else { + walletToUpdate = this.getPreferredWallet() // Default to first wallet + } + + if (walletToUpdate) { + const oldBalance = walletToUpdate.balance_msat + walletToUpdate.balance_msat = balanceMsat + + // Trigger Vue reactivity + this.authService.user.value = { ...this.authService.user.value } + + console.log(`Wallet ${walletToUpdate.id} balance: ${oldBalance} β†’ ${balanceMsat} msat`) + } +} +``` + +### **Balance State Management** +- **Storage**: Balances stored in AuthService user object +- **Reactivity**: Vue reactivity ensures UI updates automatically +- **Consistency**: Single source of truth for wallet balances +- **Persistence**: Balances persist across app sessions via AuthService + +## QR Code Generation + +### **Payment Request QR Codes** +Generate QR codes for Lightning payment requests: +```typescript +// Standard payment QR code +const qrDataUrl = await paymentService.generateQRCode( + 'lnbc1000n1p3xh4v...', // Payment request + { + width: 256, // QR code size + margin: 2, // Border margin + darkColor: '#000000', // QR code color + lightColor: '#FFFFFF' // Background color + } +) + +// Use in components +Payment QR Code +``` + +### **Custom Data QR Codes** +Generate QR codes for tickets, links, or other data: +```typescript +// Ticket QR code +const ticketQR = await paymentService.generateCustomQRCode( + JSON.stringify({ + eventId: 'event123', + ticketId: 'ticket456', + timestamp: Date.now() + }), + { width: 128 } // Smaller size for tickets +) +``` + +### **QR Code Options** +```typescript +interface QRCodeOptions { + width?: number // QR code width in pixels (default: 256) + margin?: number // Border margin (default: 2) + darkColor?: string // QR code color (default: #000000) + lightColor?: string // Background color (default: #FFFFFF) +} +``` + +## Error Handling + +### **Payment Error Types** +```typescript +// Common payment errors +enum PaymentErrorType { + INSUFFICIENT_BALANCE = 'Insufficient wallet balance', + INVALID_INVOICE = 'Invalid payment request', + NETWORK_ERROR = 'Network connection failed', + TIMEOUT = 'Payment timeout', + ROUTING_FAILED = 'Lightning routing failed', + WALLET_LOCKED = 'Wallet is locked', + UNKNOWN = 'Unknown payment error' +} +``` + +### **Error Handling Pattern** +```typescript +async payWithWallet(paymentRequest: string): Promise { + try { + this._isProcessingPayment.value = true + this._paymentError.value = null + + // Payment processing logic + const result = await this.processPayment(paymentRequest) + + // Success notification + toast.success('Payment successful!') + return result + + } catch (error) { + // Error handling + const errorMessage = this.parsePaymentError(error) + this._paymentError.value = errorMessage + + // User notification + toast.error('Payment failed', { + description: errorMessage + }) + + throw error + } finally { + this._isProcessingPayment.value = false + } +} +``` + +### **Error Recovery** +```typescript +// Clear error state +paymentService.clearPaymentError() + +// Force reset payment state (for debugging) +paymentService.forceResetPaymentState() + +// Retry payment after error +await paymentService.payWithWallet(paymentRequest, amount, { + errorMessage: 'Retry failed - please try again' +}) +``` + +## Integration with WebSocket + +### **WebSocket Collaboration** +PaymentService works closely with WalletWebSocketService: + +``` +β”Œβ”€ WalletWebSocketService ─┐ β”Œβ”€ PaymentService ─┐ +β”‚ β”‚ β”‚ β”‚ +β”‚ 1. Receive WS Message β”‚ β”‚ β”‚ +β”‚ 2. Parse Balance Update │───▢│ 4. Update Balanceβ”‚ +β”‚ 3. Convert Satsβ†’MSats β”‚ β”‚ 5. Trigger UI β”‚ +β”‚ β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### **Balance Update Flow** +1. **WebSocket Message**: WalletWebSocketService receives balance update +2. **Unit Conversion**: Convert sats to millisats for internal consistency +3. **Balance Update**: Call `PaymentService.updateWalletBalance()` +4. **State Update**: PaymentService updates wallet balance in AuthService +5. **UI Reactivity**: Vue reactivity updates all UI components + +### **Payment Notifications** +```typescript +// WebSocket triggers payment notification +eventBus.on('payment:received', (data) => { + // PaymentService can listen and handle accordingly + paymentService.handlePaymentNotification(data) +}) +``` + +## API Reference + +### **Public Methods** + +#### **Payment Operations** +```typescript +// Process Lightning payment with user wallet +payWithWallet( + paymentRequest: string, + requiredAmountSats?: number, + options?: PaymentOptions +): Promise + +// Handle payment with automatic fallback +handlePayment( + paymentRequest: string, + requiredAmountSats?: number, + options?: PaymentOptions +): Promise + +// Open external Lightning wallet +openExternalWallet(paymentRequest: string): void +``` + +#### **Wallet Management** +```typescript +// Get preferred wallet (first wallet) +getPreferredWallet(): Wallet | null + +// Get wallet with sufficient balance +getWalletWithBalance(requiredAmountSats?: number): Wallet | null + +// Get wallet credentials +getPreferredWalletAdminKey(): string | null +getPreferredWalletInvoiceKey(): string | null + +// Update wallet balance (called by WebSocket) +updateWalletBalance(balanceMsat: number, walletId?: string): void +``` + +#### **QR Code Generation** +```typescript +// Generate payment QR code +generateQRCode( + paymentRequest: string, + options?: QRCodeOptions +): Promise + +// Generate custom data QR code +generateCustomQRCode( + data: string, + options?: QRCodeOptions +): Promise +``` + +#### **State Management** +```typescript +// Clear payment error +clearPaymentError(): void + +// Reset payment state +resetPaymentState(): void + +// Force reset (for debugging) +forceResetPaymentState(): void +``` + +### **Reactive State** +```typescript +// Access reactive state +const paymentService = injectService(SERVICE_TOKENS.PAYMENT_SERVICE) + +// Payment processing state +const isProcessing = paymentService.isProcessingPayment +const error = paymentService.paymentError + +// Wallet information +const totalBalance = paymentService.totalBalance +const hasBalance = paymentService.hasWalletWithBalance +``` + +### **Integration Example** +```vue + + + +``` + +## See Also + +### Related Documentation +- **[[../02-modules/wallet-module/index|πŸ’° Wallet Module]]** - Wallet UI and WebSocket integration +- **[[../02-modules/wallet-module/websocket-integration|⚑ WebSocket Integration]]** - Real-time balance updates +- **[[authentication|πŸ” Authentication Service]]** - User wallets and credentials + +### API References +- **[[../05-api-reference/lnbits-api|⚑ LNbits API]]** - Backend Lightning wallet API +- **[[../05-api-reference/lightning-payments|πŸ’° Lightning Payments]]** - Payment protocol details + +### Development Guides +- **[[../04-development/testing|πŸ§ͺ Testing Guide]]** - Testing payment functionality +- **[[../04-development/debugging|πŸ› Debugging]]** - Payment troubleshooting + +--- + +**Tags:** #payment #lightning #service #wallet #qr-code #lnbits +**Last Updated:** 2025-09-18 +**Author:** Development Team \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 1a7102a..e71c0d8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -84,6 +84,7 @@ docs/ ### Module Documentation - **[[02-modules/base-module/index|Base Module]]** - Core infrastructure (Nostr, Auth, PWA) +- **[[02-modules/wallet-module/index|Wallet Module]]** - Lightning wallet with real-time WebSocket updates - **[[02-modules/market-module/index|Market Module]]** - Nostr marketplace implementation - **[[02-modules/chat-module/index|Chat Module]]** - Encrypted DM system - **[[02-modules/events-module/index|Events Module]]** - Lightning ticketing system @@ -162,6 +163,7 @@ Content... | Module | Status | Coverage | |--------|--------|----------| | Base Module | βœ… Complete | 100% | +| Wallet Module | βœ… Complete | 100% | | Market Module | βœ… Complete | 100% | | Chat Module | βœ… Complete | 100% | | Events Module | βœ… Complete | 100% |