aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ln.ts38
-rw-r--r--lib/payments.ts36
2 files changed, 58 insertions, 16 deletions
diff --git a/lib/ln.ts b/lib/ln.ts
index 0ef99fc5..4dff06af 100644
--- a/lib/ln.ts
+++ b/lib/ln.ts
@@ -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);
};