diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/ln.ts | 38 | ||||
| -rw-r--r-- | lib/payments.ts | 36 |
2 files changed, 58 insertions, 16 deletions
@@ -1,4 +1,30 @@ import config from "$config"; +import { existsSync } from "fs"; +import net from "net"; + +// Patch net.Socket.prototype.connect to prevent Bun from crashing when +// connecting to a non-existent unix socket. Bun's net.createConnection +// throws ENOENT in a way that bypasses all JS error handlers. +// Instead, we check if the socket file exists and emit a proper error event. +const origConnect = net.Socket.prototype.connect; +net.Socket.prototype.connect = function (...args: any[]) { + const sockPath = typeof args[0] === "string" ? args[0] : args[0]?.path; + if (typeof sockPath === "string" && sockPath.startsWith("/") && !existsSync(sockPath)) { + process.nextTick(() => { + this.emit( + "error", + Object.assign(new Error(`connect ENOENT ${sockPath}`), { + code: "ENOENT", + errno: -2, + syscall: "connect", + address: sockPath, + }), + ); + }); + return this; + } + return origConnect.apply(this, args); +}; const mod = (await import("@asoltys/clightning-client")).default; const { LightningClient } = mod as { LightningClient: any }; @@ -36,8 +62,20 @@ function lightningProxy(rpcPath: string) { throw new LightningUnavailableError(`Lightning not ready at ${rpcPath}`); } + if (!existsSync(rpcPath)) { + nextTryAt = Date.now() + backoff; + backoff = Math.min(maxBackoff, Math.floor(backoff * 1.8)); + throw new LightningUnavailableError( + `Lightning RPC socket not found at ${rpcPath}` + ); + } + try { client = new LightningClient(rpcPath); + // Prevent unhandled 'error' events from crashing the process + client.on("error", (e: any) => { + if (isSocketDied(e)) client = null; + }); backoff = 250; nextTryAt = 0; return client; diff --git a/lib/payments.ts b/lib/payments.ts index b0140f52..eed9b4c5 100644 --- a/lib/payments.ts +++ b/lib/payments.ts @@ -851,26 +851,30 @@ const reverse = async (p) => { }; const freezeCheck = async () => { - const funds = await ln.listfunds(); - const lnbalance = Math.round( - funds.channels.reduce((a, b) => a + b.our_amount_msat, 0) / 1000, - ); + try { + const funds = await ln.listfunds(); + const lnbalance = Math.round( + funds.channels.reduce((a, b) => a + b.our_amount_msat, 0) / 1000, + ); - const bcbalance = Math.round((await bc.getBalance()) * SATS); - const { bitcoin } = await lq.getBalance(); - const lqbalance = Math.round(bitcoin * SATS); + const bcbalance = Math.round((await bc.getBalance()) * SATS); + const { bitcoin } = await lq.getBalance(); + const lqbalance = Math.round(bitcoin * SATS); - const lnthreshold = await g("lightning:threshold"); - const bcthreshold = await g("bitcoin:threshold"); - const lqthreshold = await g("liquid:threshold"); + const lnthreshold = await g("lightning:threshold"); + const bcthreshold = await g("bitcoin:threshold"); + const lqthreshold = await g("liquid:threshold"); - await s("lightning:limit", Math.max(lnbalance - lnthreshold, 0)); - await s("bitcoin:limit", Math.max(bcbalance - bcthreshold, 0)); - await s("liquid:limit", Math.max(lqbalance - lqthreshold, 0)); + await s("lightning:limit", Math.max(lnbalance - lnthreshold, 0)); + await s("bitcoin:limit", Math.max(bcbalance - bcthreshold, 0)); + await s("liquid:limit", Math.max(lqbalance - lqthreshold, 0)); - await s("fund:limit", Math.max(lnbalance - lnthreshold, 0)); - await s("ecash:limit", Math.max(lnbalance - lnthreshold, 0)); - await s("bolt12:limit", Math.max(lnbalance - lnthreshold, 0)); + await s("fund:limit", Math.max(lnbalance - lnthreshold, 0)); + await s("ecash:limit", Math.max(lnbalance - lnthreshold, 0)); + await s("bolt12:limit", Math.max(lnbalance - lnthreshold, 0)); + } catch (e: any) { + warn("freezeCheck failed:", e.message); + } setTimeout(freezeCheck, 10000); }; |
