diff --git a/apps/machine/package.json b/apps/machine/package.json index 2a4b205..21896f5 100644 --- a/apps/machine/package.json +++ b/apps/machine/package.json @@ -24,6 +24,7 @@ "@bitSpire/clink": "workspace:*", "@bitSpire/hal": "workspace:*", "@bitSpire/lightning": "workspace:*", + "@bitSpire/lnbits": "workspace:*", "@bitSpire/nostr-client": "workspace:*", "@bitSpire/state-machine": "workspace:*", "@scure/base": "^1.2.0", diff --git a/apps/machine/src/services/lightning.ts b/apps/machine/src/services/lightning.ts index 5423856..9e3408d 100644 --- a/apps/machine/src/services/lightning.ts +++ b/apps/machine/src/services/lightning.ts @@ -24,6 +24,7 @@ import { } from '@bitSpire/nostr-client' import { verifyEvent } from 'nostr-tools' import { LightningPubClient } from '@bitSpire/lightning' +import { LnbitsClient } from '@bitSpire/lnbits' import { CLINKClient, createOfferSuccess, @@ -63,6 +64,13 @@ interface LightningConfig { atmPrivateKey: string appId: string operatorPubkeys: string[] + /** + * LNbits nostr-transport server pubkey. Optional during the LP→LNbits + * migration: when empty, the LnbitsClient is not instantiated and the + * file behaves identically to its LP-only past. Once 3c wires the env + * var, this is required. + */ + lnbitsServerPubkey: string } /** @@ -83,6 +91,7 @@ async function loadLightningConfig(): Promise { atmPrivateKey: '', appId: '30270e761f2e30b1737f34ce661df45f521352b408b8ed18fcc09f3f0dec5097', // ATM app ID — regenerated for bitSpire so stale LP server-side associations don't accidentally rehydrate operatorPubkeys: [], + lnbitsServerPubkey: '', } // In Electron, get runtime config from main process @@ -105,6 +114,9 @@ async function loadLightningConfig(): Promise { .map((k: string) => k.trim()) .filter(Boolean) : defaults.operatorPubkeys, + lnbitsServerPubkey: + (runtimeConfig as { lnbitsServerPubkey?: string }).lnbitsServerPubkey || + defaults.lnbitsServerPubkey, } } catch (e) { console.warn('[Lightning] Failed to get runtime config from Electron:', e) @@ -120,6 +132,9 @@ async function loadLightningConfig(): Promise { adminToken: import.meta.env.VITE_ADMIN_TOKEN || defaults.adminToken, atmPrivateKey: import.meta.env.VITE_ATM_PRIVATE_KEY || defaults.atmPrivateKey, appId: import.meta.env.VITE_APP_ID || defaults.appId, + lnbitsServerPubkey: + (import.meta.env.VITE_LNBITS_SERVER_PUBKEY as string | undefined) || + defaults.lnbitsServerPubkey, operatorPubkeys: import.meta.env.VITE_OPERATOR_PUBKEYS ? (import.meta.env.VITE_OPERATOR_PUBKEYS as string) .split(',') @@ -369,6 +384,17 @@ function expireLnurlSession(uniqueHash: string, lightningPub: LightningPubClient /** Clean up all active LNURL sessions. Called when state machine returns to idle. */ let _lightningPubRef: LightningPubClient | null = null +/** LNbits client reference, set during initializeLightningServices if + * VITE_LNBITS_SERVER_PUBKEY is configured. Parallel to _lightningPubRef + * during the LP→LNbits migration; 3b.2+ swap call sites over. */ +let _lnbitsRef: LnbitsClient | null = null + +/** Internal accessor — used by 3b.2+ call sites that need to invoke + * the LNbits client from outside `createATMServices`. Returns null + * when the LNbits server pubkey isn't configured. */ +export function _getLnbitsClient(): LnbitsClient | null { + return _lnbitsRef +} function cleanupAllLnurlSessions(): void { if (!_lightningPubRef) return @@ -930,6 +956,23 @@ export async function initializeLightningServices(options?: { _lightningPubRef = lightningPub console.log('[Lightning] Lightning.Pub client initialized') + // LNbits client — wired in parallel with Lightning.Pub during the + // migration. In 3b.1 it's instantiated but not yet wired into any + // ATMServices method; 3b.2-3b.4 will gradually move call sites over. + // When VITE_LNBITS_SERVER_PUBKEY isn't set we skip the init so the + // file remains LP-only at runtime. + if (CONFIG.lnbitsServerPubkey) { + const lnbits = new LnbitsClient({ + serverPubkey: CONFIG.lnbitsServerPubkey, + relays: [CONFIG.relayUrl], + }) + lnbits.initialize(nostrClient, identity) + _lnbitsRef = lnbits + console.log('[Lightning] LNbits client initialized (parallel to LP)') + } else { + console.log('[Lightning] VITE_LNBITS_SERVER_PUBKEY not set — LNbits client disabled') + } + // Create CLINK client const clink = new CLINKClient({ nostrClient, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b2b55f8..d323da1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,9 @@ importers: '@bitSpire/lightning': specifier: workspace:* version: link:../../packages/lightning + '@bitSpire/lnbits': + specifier: workspace:* + version: link:../../packages/lnbits '@bitSpire/nostr-client': specifier: workspace:* version: link:../../packages/nostr-client