diff --git a/src/index.ts b/src/index.ts index d5f30bdb..ac32d29f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,7 +17,7 @@ const start = async () => { log("manual process ended") return } - const { apps, mainHandler, liquidityProviderInfo, wizard } = keepOn + const { apps, mainHandler, liquidityProviderInfo, wizard, adminManager } = keepOn const serverMethods = GetServerMethods(mainHandler) const nostrSettings = LoadNosrtSettingsFromEnv() log("initializing nostr middleware") @@ -28,9 +28,11 @@ const start = async () => { log("starting server") mainHandler.attachNostrSend(Send) mainHandler.StartBeacons() + const appNprofile = encodeNprofile({ pubkey: liquidityProviderInfo.publicKey, relays: nostrSettings.relays }) if (wizard) { - wizard.AddConnectInfo(encodeNprofile({ pubkey: liquidityProviderInfo.publicKey, relays: nostrSettings.relays }), nostrSettings.relays) + wizard.AddConnectInfo(appNprofile, nostrSettings.relays) } + adminManager.setAppNprofile(appNprofile) const Server = NewServer(serverMethods, serverOptions(mainHandler)) Server.Listen(mainSettings.servicePort) } diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index d5ec2778..7ed9a0e8 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -236,7 +236,6 @@ export default class { async NewAddress(addressType: Types.AddressType, { useProvider, from }: TxActionOptions): Promise { - await this.Health() let lndAddressType: AddressType switch (addressType) { case Types.AddressType.NESTED_PUBKEY_HASH: @@ -254,6 +253,7 @@ export default class { if (useProvider) { throw new Error("provider payments not support chain payments yet") } + await this.Health() try { const res = await this.lightning.newAddress({ account: "", type: lndAddressType }, DeadLineMetadata()) this.utils.stateBundler.AddTxPoint('addedAddress', 1, { from, used: 'lnd' }) @@ -265,12 +265,12 @@ export default class { } async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions): Promise { - await this.Health() if (useProvider) { const invoice = await this.liquidProvider.AddInvoice(value, memo, from) const providerDst = this.liquidProvider.GetProviderDestination() return { payRequest: invoice, providerDst } } + await this.Health() try { const res = await this.lightning.addInvoice(AddInvoiceReq(value, expiry, true, memo), DeadLineMetadata()) this.utils.stateBundler.AddTxPoint('addedInvoice', value, { from, used: 'lnd' }) @@ -304,12 +304,12 @@ export default class { this.log("outgoing ops locked, rejecting payment request") throw new Error("lnd node is currently out of sync") } - await this.Health() if (useProvider) { const res = await this.liquidProvider.PayInvoice(invoice, decodedAmount, from) const providerDst = this.liquidProvider.GetProviderDestination() return { feeSat: res.network_fee + res.service_fee, valueSat: res.amount_paid, paymentPreimage: res.preimage, providerDst } } + await this.Health() try { const abortController = new AbortController() const req = PayInvoiceReq(invoice, amount, feeLimit) @@ -320,6 +320,7 @@ export default class { rej(error) }) stream.responses.onMessage(payment => { + console.log("payment", payment) switch (payment.status) { case Payment_PaymentStatus.FAILED: this.log("invoice payment failed", payment.failureReason) @@ -358,8 +359,8 @@ export default class { if (useProvider) { throw new Error("provider payments not support chain payments yet") } + await this.Health() try { - await this.Health() const res = await this.lightning.sendCoins(SendCoinsReq(address, amount, satPerVByte, label), DeadLineMetadata()) this.utils.stateBundler.AddTxPoint('paidAnAddress', amount, { from, used: 'lnd', timeDiscount: true }) return res.response @@ -370,7 +371,6 @@ export default class { } async GetTransactions(startHeight: number): Promise { - await this.Health() const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "" }, DeadLineMetadata()) return res.response } diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 906c652f..f4aa302d 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -10,14 +10,29 @@ export class AdminManager { dataDir: string adminNpubPath: string adminEnrollTokenPath: string + adminConnectPath: string + appNprofilePath: string interval: NodeJS.Timer + appNprofile: string constructor(mainSettings: MainSettings, storage: Storage) { this.storage = storage this.dataDir = mainSettings.storageSettings.dataDir this.adminNpubPath = getDataPath(this.dataDir, 'admin.npub') this.adminEnrollTokenPath = getDataPath(this.dataDir, '.admin_enroll') + this.adminConnectPath = getDataPath(this.dataDir, '.admin_connect') + this.appNprofilePath = getDataPath(this.dataDir, 'app.nprofile') this.start() } + + setAppNprofile = (nprofile: string) => { + this.appNprofile = nprofile + const enrollToken = this.ReadAdminEnrollToken() + fs.writeFileSync(this.appNprofilePath, this.appNprofile) + if (enrollToken) { + const connectString = `${this.appNprofile}:${enrollToken}` + fs.writeFileSync(this.adminConnectPath, connectString) + } + } Stop = () => { clearInterval(this.interval) } @@ -25,6 +40,8 @@ export class AdminManager { GenerateAdminEnrollToken = async () => { const token = crypto.randomBytes(32).toString('hex') fs.writeFileSync(this.adminEnrollTokenPath, token) + const connectString = `${this.appNprofile}:${token}` + fs.writeFileSync(this.adminConnectPath, connectString) return token } @@ -92,6 +109,7 @@ export class AdminManager { } fs.writeFileSync(this.adminNpubPath, npub) fs.unlinkSync(this.adminEnrollTokenPath) + fs.unlinkSync(this.adminConnectPath) this.adminNpub = npub } } \ No newline at end of file diff --git a/src/services/main/liquidityProvider.ts b/src/services/main/liquidityProvider.ts index 47f44b17..fabab3af 100644 --- a/src/services/main/liquidityProvider.ts +++ b/src/services/main/liquidityProvider.ts @@ -89,15 +89,19 @@ export class LiquidityProvider { this.ready = true this.queue.forEach(q => q('ready')) this.log("subbing to user operations") - this.client.GetLiveUserOperations(res => { + this.client.GetLiveUserOperations(async res => { if (res.status === 'ERROR') { this.log("error getting user operations", res.reason) return } //this.log("got user operation", res.operation) if (res.operation.type === Types.UserOperationType.INCOMING_INVOICE) { - this.incrementProviderBalance(res.operation.amount) - this.invoicePaidCb(res.operation.identifier, res.operation.amount, 'provider') + try { + await this.invoicePaidCb(res.operation.identifier, res.operation.amount, 'provider') + this.incrementProviderBalance(res.operation.amount) + } catch (err: any) { + this.log("error processing incoming invoice", err.message) + } } }) } @@ -105,7 +109,9 @@ export class LiquidityProvider { GetUserState = async () => { const res = await Promise.race([this.client.GetUserInfo(), new Promise(res => setTimeout(() => res({ status: 'ERROR', reason: 'timeout' }), 10 * 1000))]) if (res.status === 'ERROR') { - this.log("error getting user info", res.reason) + if (res.reason !== 'timeout') { + this.log("error getting user info", res.reason) + } return res } this.utils.stateBundler.AddBalancePoint('providerBalance', res.balance) diff --git a/src/services/main/unlocker.ts b/src/services/main/unlocker.ts index 6dbe0ecc..2b20fb61 100644 --- a/src/services/main/unlocker.ts +++ b/src/services/main/unlocker.ts @@ -240,8 +240,9 @@ export class Unlocker { try { const { encryptedData } = this.EncryptBackup(Buffer.from(msg.multiChanBackup.multiChanBackup)) await this.storage.liquidityStorage.SaveNodeBackup(pub, JSON.stringify(encryptedData)) + this.log("new channel backup saved correctly") } catch (err: any) { - this.log("failed to save backup", err.message) + this.log("new channel backup was not saved") } } }) diff --git a/src/services/wizard/index.ts b/src/services/wizard/index.ts index 00558384..debe8cb4 100644 --- a/src/services/wizard/index.ts +++ b/src/services/wizard/index.ts @@ -98,6 +98,7 @@ export class Wizard { AddConnectInfo = (nprofile: string, relays: string[]) => { this.nprofile = nprofile + this.relays = relays this.awaitingNprofile.forEach(q => q.res(nprofile)) this.awaitingNprofile = [] }