From ce9616f62d0ac682c1e92956ef4cb48f053df27d Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 4 Jun 2026 18:40:42 -0700 Subject: nwc: pay_invoice honors request amount for amountless bolt11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pay_invoice derived the amount solely from the decoded invoice, so an amountless bolt11 yielded amount = round(undefined/1000) = NaN and sendLightning rejected it with "Invalid amount". NIP-47 allows the client to specify the amount (msat) in the request for exactly this case (AlbyHub supports it; Alby Go and others hit the error). Fall back to the request's `amount` field when the invoice carries none; invoice amount still takes precedence when present, and a still-missing amount returns a clear error instead of NaN. sendLightning/sendInternal already handle amountless invoices given a valid amount — the bug was only the handler dropping it. Fixes #83 Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/nwc.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/nwc.ts b/lib/nwc.ts index 2213d68a..3a1ae5b0 100644 --- a/lib/nwc.ts +++ b/lib/nwc.ts @@ -222,10 +222,22 @@ export default () => { const handle = (method, params, ev, app, user) => ({ async pay_invoice() { - const { invoice: pr, metadata } = params; + const { invoice: pr, metadata, amount: reqAmountMsat } = params; const { amount_msat, payee } = await ln.decode(pr); const { id } = await ln.getinfo(); - const amount = Math.round(amount_msat / 1000); + // For an amountless bolt11, the invoice carries no amount — NIP-47 lets the + // client specify it in the request's `amount` field (msat). Fall back to + // that so amountless invoices aren't rejected with "Invalid amount" + // (issue #83). Invoice amount takes precedence when present. + const amountMsat = amount_msat || reqAmountMsat; + if (!amountMsat) { + return error({ + code: "OTHER", + message: + "Amountless invoice requires an amount; specify amount (msat) in the request", + }); + } + const amount = Math.round(amountMsat / 1000); const { max_amount, max_fee, budget_renewal, pubkey, created } = app; const periods = { -- cgit v1.2.3