aboutsummaryrefslogtreecommitdiffstats
path: root/lib/payments.ts
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-07-30 08:51:36 -0700
committerAdam Soltys <[email protected]>2026-07-30 08:51:36 -0700
commitadd3ad93ff37f1daaedab5788f00663be299555c (patch)
treede0523f7f6d13e57e58c26d8b03dabbdcb5790cb /lib/payments.ts
parent81c3593f1eec7f94dc9cbc22edc3456fa57b95cb (diff)
downloadcoinos-server-add3ad93ff37f1daaedab5788f00663be299555c.tar.gz
coinos-server-add3ad93ff37f1daaedab5788f00663be299555c.zip
bolt12 zaps: pay offers, NWC pay/receive, per-user offers, NIP-44
- sendLightning fetches an invoice from lno1 offers (payer_note passthrough for NIP-177 zap intents) and pays it through the existing bolt12 path - NWC: new nwc#2 pay/receive methods (BIP-321 URIs, payer proofs stubbed until CLN 26.06 createproof), nip44_v2 alongside nip04 with per-request scheme detection, dual 23196/23197 notifications, 13194 refreshed when its content or encryption tag goes stale - standing per-user bolt12 offer via GET /offer; incoming bolt12 payments record invreq_payer_note as memo - parse/fetchinvoice routes handle offers; zap display parses kind 9736 receipts (amount tag + embedded intent) and drops a call to a sync() helper that never existed Co-Authored-By: Claude Fable 5 <[email protected]>
Diffstat (limited to 'lib/payments.ts')
-rw-r--r--lib/payments.ts24
1 files changed, 23 insertions, 1 deletions
diff --git a/lib/payments.ts b/lib/payments.ts
index df2c8857..56aa08de 100644
--- a/lib/payments.ts
+++ b/lib/payments.ts
@@ -717,6 +717,7 @@ export const sendLightning = async ({
amount,
fee = undefined,
memo = undefined,
+ payerNote = undefined,
}) => {
let p;
@@ -736,8 +737,29 @@ export const sendLightning = async ({
}
}
+ let decoded = await ln.decode(pr);
+
+ // A bolt12 offer (lno1...) isn't payable directly — fetch a real invoice
+ // from it over onion messages, then pay that. payerNote rides along in
+ // invreq_payer_note (NIP-177 bolt12 zaps put nostr:nip177:<intent-id> there).
+ if (decoded.type === "bolt12 offer") {
+ if (decoded.offer_currency)
+ fail("Currency-denominated offers are not supported");
+ if (!decoded.offer_amount_msat && !amount) fail("Amount required");
+
+ const { invoice } = await ln.fetchinvoice({
+ offer: pr,
+ amount_msat: decoded.offer_amount_msat ? undefined : amount * 1000,
+ payer_note: payerNote,
+ timeout: 60,
+ });
+
+ pr = invoice.replace(/\s/g, "").toLowerCase();
+ decoded = await ln.decode(pr);
+ }
+
let { type, invoice_amount_msat, amount_msat, invoice_node_id, payee } =
- await ln.decode(pr);
+ decoded;
if (type.includes("bolt12")) {
amount_msat = invoice_amount_msat;
payee = invoice_node_id;