interface LoginCredentials { username: string password: string } interface RegisterData { username: string email?: string password: string password_repeat: string } interface AuthResponse { access_token: string user_id: string username?: string email?: string } interface Wallet { id: string user: string name: string adminkey: string inkey: string deleted: boolean created_at: string updated_at: string currency?: string balance_msat: number extra?: { icon: string color: string pinned: boolean } } interface User { id: string username?: string email?: string pubkey?: string prvkey?: string // Nostr private key for user external_id?: string extensions: string[] wallets: Wallet[] admin: boolean super_user: boolean fiat_providers: string[] has_password: boolean created_at: string updated_at: string extra?: { email_verified?: boolean first_name?: string last_name?: string display_name?: string picture?: string provider?: string visible_wallet_count?: number } } import { BaseService } from '@/core/base/BaseService' import { getApiUrl, getAuthToken, setAuthToken, removeAuthToken } from '@/lib/config/lnbits' export class LnbitsAPI extends BaseService { // Service metadata protected readonly metadata = { name: 'LnbitsAPI', version: '1.0.0', dependencies: [] // No dependencies - this is a core infrastructure service } private accessToken: string | null = null constructor() { super() // Try to load token from localStorage this.accessToken = getAuthToken() } /** * Service-specific initialization (called by BaseService) */ protected async onInitialize(): Promise { this.debug('LnbitsAPI initialized') // Service is ready to use } private async request( endpoint: string, options: RequestInit = {} ): Promise { const url = getApiUrl(endpoint) console.log('🔧 LNBits API request:', { endpoint, fullUrl: url }) const headers: HeadersInit = { 'Content-Type': 'application/json', ...options.headers, } if (this.accessToken) { (headers as Record)['Authorization'] = `Bearer ${this.accessToken}` } const response = await fetch(url, { ...options, headers, }) if (!response.ok) { const errorText = await response.text() console.error('LNBits API Error:', { status: response.status, statusText: response.statusText, errorText }) throw new Error(`API request failed: ${response.status} ${response.statusText}`) } const data = await response.json() return data } async login(credentials: LoginCredentials): Promise { const response = await this.request('/auth', { method: 'POST', body: JSON.stringify(credentials), }) this.accessToken = response.access_token setAuthToken(response.access_token) return response } async register(data: RegisterData): Promise { const response = await this.request('/auth/register', { method: 'POST', body: JSON.stringify(data), }) this.accessToken = response.access_token setAuthToken(response.access_token) return response } async logout(): Promise { // Just clear local state - no API call needed for logout this.accessToken = null removeAuthToken() } async getCurrentUser(): Promise { // First get basic user info from /auth const basicUser = await this.request('/auth') // Then get Nostr keys from /auth/nostr/me (this was working in main branch) try { const nostrUser = await this.request('/auth/nostr/me') // Merge the data - basic user info + Nostr keys return { ...basicUser, pubkey: nostrUser.pubkey, prvkey: nostrUser.prvkey } } catch (error) { console.warn('Failed to fetch Nostr keys, returning basic user info:', error) // Return basic user info without Nostr keys if the endpoint fails return basicUser } } async updatePassword(currentPassword: string, newPassword: string): Promise { return this.request('/auth/password', { method: 'PUT', body: JSON.stringify({ current_password: currentPassword, new_password: newPassword, }), }) } async updateProfile(data: Partial): Promise { return this.request('/auth/update', { method: 'PUT', body: JSON.stringify(data), }) } isAuthenticated(): boolean { return !!this.accessToken } getAccessToken(): string | null { return this.accessToken } } // Service is now registered in the DI container export type { LoginCredentials, RegisterData, AuthResponse, User }