From d60697c8d1cc0b862d7488be4cf8ee21cafdfd1d Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sun, 2 Aug 2026 22:41:39 -0700 Subject: Push notifications for payments and messages; offline Spending notice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nwcpush notifier grows a second registration kind alongside NWC: a notify watch of what it can see without keys — kind-1059 wraps p-tagged at the user (DMs, direct invites), zap receipts (9735/9737), and wraps authored by the user's community channel keys (chat). It pushes a typed nudge, throttled per device (chat bursts collapse); the service worker shows a generic notification unless a window is visible, and tapping opens the app. The names registrar reports settled lightning-address receives server-to-server (token-gated /notify), so the common payment path notifies even with no nostr event in sight. The app registers silently whenever permission is already granted and keeps the watch current as communities change; a dismissible card on the chat home offers to enable it otherwise. Ark zap receipts (9737) join the relay whitelist so the payment watch can see them. Also: the offline Spending receive pane now says you're offline and offers a one-tap switch to Savings instead of spinning forever. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi --- names/server.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'names') diff --git a/names/server.js b/names/server.js index d9aa299..99552dc 100644 --- a/names/server.js +++ b/names/server.js @@ -301,6 +301,13 @@ async function settleLoop() { if (!name) continue; // not one of ours (e.g. the ASP's own invoices) const sat = Math.floor((inv.amount_received_msat?.msat ?? inv.amount_received_msat ?? 0) / 1000); if (!sat) continue; + // money has arrived for this name — push-notify their devices (best effort) + if (CFG.push && CFG.push.url && state.names[name]) { + fetch(`${CFG.push.url}/notify`, { + method: 'POST', headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ token: CFG.push.token, pubkey: state.names[name].pubkey, amountSat: sat }), + }).catch(() => {}); + } if (pending) { if (pending.zap) publishZapReceipt(pending, inv).catch(() => {}); delete state.invoices[inv.payment_hash]; -- cgit v1.2.3