diff options
| author | Adam Soltys <[email protected]> | 2026-07-30 08:51:36 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-07-30 08:51:36 -0700 |
| commit | add3ad93ff37f1daaedab5788f00663be299555c (patch) | |
| tree | de0523f7f6d13e57e58c26d8b03dabbdcb5790cb /lib/notifications.ts | |
| parent | 81c3593f1eec7f94dc9cbc22edc3456fa57b95cb (diff) | |
| download | coinos-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/notifications.ts')
| -rw-r--r-- | lib/notifications.ts | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/lib/notifications.ts b/lib/notifications.ts index eeb6e8c1..09f4fb2b 100644 --- a/lib/notifications.ts +++ b/lib/notifications.ts @@ -4,11 +4,11 @@ import ln from "$lib/ln"; import { err, l, warn } from "$lib/logging"; import { mail, templates } from "$lib/mail"; import mqtt from "$lib/mqtt"; -import { publish, serverSecret2 } from "$lib/nostr"; +import { encryptPayload, publish, serverSecret2 } from "$lib/nostr"; import { emit } from "$lib/sockets"; import { f, fiat, fmt, getUser, link, nada, t } from "$lib/utils"; import { hexToBytes } from "@noble/hashes/utils"; -import { finalizeEvent, nip04 } from "nostr-tools"; +import { finalizeEvent } from "nostr-tools"; import webpush from "web-push"; if (config.vapid) { @@ -84,8 +84,15 @@ export const nwcNotify = async (p) => { const user = await getUser(p.uid); const pubkeys = await db.sMembers(`${user.id}:apps`); if (pubkeys.length) { - let payment_hash = ""; - if (p.type === "lightning") ({ payment_hash } = await ln.decode(p.hash)); + let payment_hash = p.payment_hash || ""; + if (!payment_hash && (p.type === "lightning" || p.type === "bolt12")) { + try { + const d = await ln.decode(p.hash); + // bolt11 decodes expose payment_hash, bolt12 invoices + // invoice_payment_hash + payment_hash = d.payment_hash || d.invoice_payment_hash || ""; + } catch (e) {} + } for (const pubkey of pubkeys) { const { notify } = await g(`app:${pubkey}`); if (!notify) continue; @@ -108,18 +115,30 @@ export const nwcNotify = async (p) => { notification, }); - const content = await nip04.encrypt(serverSecret2, pubkey, payload); + // NIP-47: a wallet supporting both schemes publishes each notification + // twice — kind 23196 nip04-encrypted, kind 23197 nip44-encrypted + for (const [scheme, kind] of [ + ["nip04", 23196], + ["nip44_v2", 23197], + ] as const) { + const content = await encryptPayload( + scheme, + serverSecret2, + pubkey, + payload, + ); - const unsigned = { - content, - tags: [["p", pubkey]], - kind: 23196, - created_at: Math.floor(Date.now() / 1000), - }; + const unsigned = { + content, + tags: [["p", pubkey]], + kind, + created_at: Math.floor(Date.now() / 1000), + }; - const event = finalizeEvent(unsigned, hexToBytes(serverSecret2)); + const event = finalizeEvent(unsigned, hexToBytes(serverSecret2)); - publish(event).catch(nada); + publish(event).catch(nada); + } } } } catch (e) { |
