aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/nwc.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-14 01:13:47 -0700
committerAdam Soltys <[email protected]>2026-08-14 01:13:47 -0700
commit5b23470f5d9ec7ee7cc33c2b4b936ddd24fa17cc (patch)
treed1a34086526be29d123922ff45af40878ba4c25d /src/features/nwc.js
parentc6404bae2ddbc402baa01349c5196d9fcebcf78a (diff)
downloadcoinosv3-5b23470f5d9ec7ee7cc33c2b4b936ddd24fa17cc.tar.gz
coinosv3-5b23470f5d9ec7ee7cc33c2b4b936ddd24fa17cc.zip
Money leaving while you're not looking gets a notification: NWC pays from the worker or a hidden tab announce themselves — amount, fee, and which app asked
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
Diffstat (limited to 'src/features/nwc.js')
-rw-r--r--src/features/nwc.js17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/features/nwc.js b/src/features/nwc.js
index 686b11f..d6bfdea 100644
--- a/src/features/nwc.js
+++ b/src/features/nwc.js
@@ -212,6 +212,22 @@ export function nwcFeature(ctx) {
? nip44.encrypt(txt, nip44.getConversationKey(sk, pk))
: nip04.encrypt(sk, pk, txt));
+ // A pay answered by a hidden tab is as invisible as one paid by the
+ // worker — surface it the same way. A visible tab already shows it live.
+ async function notifySent(c, amountSat, feeSat) {
+ try {
+ if (typeof document === 'undefined' || !document.hidden) return;
+ if (typeof Notification === 'undefined' || Notification.permission !== 'granted') return;
+ const reg = await navigator.serviceWorker.ready;
+ await reg.showNotification(t('nwcPaidTitle'), {
+ body: t('nwcPaidBody', { amount: amountSat.toLocaleString(), name: c.name || 'app' })
+ + (feeSat ? ` (+${feeSat} fee)` : ''),
+ icon: 'icon-192.png', badge: 'icon-192.png',
+ tag: 'nwc-sent', renotify: true, data: { url: './' },
+ });
+ } catch {}
+ }
+
// Every request gets a reply, including failures — a client that never
// hears back just hangs.
async function reply(c, ev, scheme, payload) {
@@ -358,6 +374,7 @@ export function nwcFeature(ctx) {
const res = await hook('arkPayInvoice', invoice, { maxAmountSat: c.maxSat });
// the ark seam throws on failure, so reaching here means it settled
recordSpend(c, (res.amountSat || 0) + (res.feeSat || 0));
+ notifySent(c, res.amountSat || 0, res.feeSat || 0);
return { result: { preimage: res.preimage, fees_paid: (res.feeSat || 0) * 1000 } };
}