From cddafe5ef8fc90559d5163d4ecaa0da37c7947f7 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Mon, 18 May 2026 00:00:10 -0700 Subject: freezeCheck: only count spendable channels in lnbalance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous calc summed our_amount_msat across every channel regardless of state, including ONCHAIN (channels that have been closed and are waiting for the on-chain sweep). Those funds are not actually usable for lightning sends, but were inflating lnbalance — and therefore inflating ${type}:limit — by the locked-up amount. With several closed channels pending sweep, the effective threshold floor was tens of megasats lower than the configured lightning:threshold suggested. Filter to CHANNELD_NORMAL (and CHANNELD_AWAITING_SPLICE so an in-flight splice doesn't briefly pin the limit to zero). Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/payments.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/payments.ts b/lib/payments.ts index 22bbafb4..380b5e7b 100644 --- a/lib/payments.ts +++ b/lib/payments.ts @@ -975,8 +975,16 @@ const freezeCheck = async () => { let lnbalance: number | undefined; try { const funds = await ln.listfunds(); + // Only spendable channels — ONCHAIN/CLOSING funds are locked in pending + // sweeps and aren't usable for lightning sends, so counting them inflates + // the limit. CHANNELD_AWAITING_SPLICE is included so an in-flight splice + // doesn't briefly drop the limit to zero. lnbalance = Math.round( - funds.channels.reduce((a, b) => a + b.our_amount_msat, 0) / 1000, + funds.channels + .filter((c) => + c.state === "CHANNELD_NORMAL" || c.state === "CHANNELD_AWAITING_SPLICE", + ) + .reduce((a, b) => a + b.our_amount_msat, 0) / 1000, ); } catch (e: any) { warnThrottled("freezeCheck lightning", e.message); -- cgit v1.2.3