Skip to content

Browser push notification#50

Closed
Opeyemi01-del wants to merge 2 commits into
wraith-protocol:mainfrom
Opeyemi01-del:browser-push-notification
Closed

Browser push notification#50
Opeyemi01-del wants to merge 2 commits into
wraith-protocol:mainfrom
Opeyemi01-del:browser-push-notification

Conversation

@Opeyemi01-del
Copy link
Copy Markdown

feat(stellar): browser push notifications for incoming payments

Closes #21

Add a service-worker-driven, opt-in notification system that alerts
users when a Stellar stealth payment arrives — even when the Receive
tab is closed. Default OFF; the user must affirmatively enable.

New files

src/lib/notification-storage.ts

IndexedDB wrapper and AES-256-GCM crypto helpers. Persists the
encrypted viewing key, cursor, and rate-limit timestamp. The viewing
key is encrypted with a key derived via PBKDF2 (100 000 iterations)
from the wallet signing output — it never leaves the device in
plaintext. Disabling notifications calls clearState(), which
immediately deletes the key from storage.

src/hooks/useStellarNotifications.ts

React hook managing the full opt-in lifecycle:

  1. Request Notification.permission
  2. Register /stellar-notification-sw.js as a service worker
  3. Register the Periodic Background Sync tag 'wraith-stellar-scan'
    (Chrome/Edge 80+), or fall back to a 5-minute setInterval ping
    loop when PBS is unavailable (Firefox, iOS Safari)
  4. Encrypt the viewing key with AES-GCM and persist to IndexedDB
  5. Post WRAITH_SCAN_NOW to trigger an immediate scan on enable
    Disable() unregisters PBS, clears IndexedDB state, and stops the
    ping loop.

src/components/StellarNotificationToggle.tsx

Self-contained opt-in widget for the Receive page:

  • Toggle switch (aria-role=switch) gated on keysReady prop
  • Privacy disclosure modal shown before first opt-in — explains
    the viewing key storage trade-off and spending key guarantee
  • "Permission blocked" hint with actionable instruction when
    Notification.permission === 'denied'
  • Browser compatibility note: "Best on Chrome / Edge / Firefox.
    iOS Safari support is limited."
  • Active status line distinguishes PBS mode from ping-loop mode

src/sw/stellar-notification-sw.ts → public/stellar-notification-sw.js

Service worker handling three events:

  • 'periodicsync' (tag: wraith-stellar-scan) Chrome/Edge PBS
  • 'message' WRAITH_SCAN_PING / WRAITH_SCAN_NOW fallback loop
  • 'notificationclick' focuses existing /receive tab or opens new

Core scan flow:
1. Read NotificationState from IndexedDB
2. Decrypt viewing key in memory via PBKDF2 + AES-GCM
3. Fetch Horizon announcements since lastSeenCursor
4. Spawn Web Worker (/stellar-scan-worker.js) for EC math
5. showNotification() if matches found and not rate-limited
6. Persist nextCursor and lastNotifiedAt

Notification design:
- Title: "Wraith Payment received" (single) or
"Wraith N new payments" (batch)
- Body: "Stellar payment of X XLM to your stealth address GABCD…EF12"
- Icon: /wraith-192.png, badge: /wraith-badge-96.png
- data.chain: 'stellar' (prevents cross-chain confusion)
- Rate limit: one notification per 5 min per chain; multiple
arrivals batched into a single summary notification

Includes inline IndexedDB and PBKDF2/AES-GCM helpers duplicated
from notification-storage.ts — SWs cannot import main-thread
modules so the crypto is self-contained.

src/workers/stellar-scan-worker.ts → public/stellar-scan-worker.js

Standalone Web Worker spawned by the SW. Calls
scanAnnouncements() from @wraith-protocol/sdk/chains/stellar, posts
{ matches } or { error } back to the SW. Offloads EC math to avoid
blocking the SW event loop, which would delay the notification.

scripts/build-sw.sh

esbuild script compiling the SW and scan worker to public/ without
requiring vite-plugin-pwa. Run before pnpm dev for the first time.

Modified files

vite.config.ts

Adds the scan worker as a named Rollup entry (stellar-scan-worker)
so it lands at /stellar-scan-worker.js where the SW can new Worker()
it. Adds optional vite-plugin-pwa integration in injectManifest mode
for teams that want the full PWA pipeline.

Integration (StellarReceive.tsx three-line patch)

See src/components/StellarReceive.integration.ts. Summary:

  1. Import StellarNotificationToggle
  2. Persist signingOutput from the Freighter signMessage() call
  3. Render <StellarNotificationToggle ... /> below the meta-address

Privacy model

  • Viewing key stored encrypted (AES-256-GCM / PBKDF2). Attacker
    with IndexedDB access cannot decrypt without the wallet signature.
  • Spending key is never stored. Funds cannot be moved.
  • Privacy disclosure shown to user before first opt-in.
  • Default OFF explicit user action required to enable.

Browser compatibility

Chrome/Edge 80+ Full PBS, background scans when tab is closed
Firefox Ping-loop fallback, works while tab is open
iOS Safari 16.4+ Limited; PBS fires infrequently, PWA only
Other Ping-loop only (tab must stay open)

Acceptance criteria

[x] Opt-in flow + permission handling (granted / denied / unsupported)
[x] Service worker periodic scan (PBS tag wraith-stellar-scan)
[x] Notifications fire with correct title / body / icon / chain tag
[x] Privacy disclosure visible at opt-in
[x] Killswitch: disable() unregisters PBS + clears IndexedDB state
[x] Rate limiting: max 1 notification per 5 min, batching for N > 1
[x] Notification click focuses/opens /receive
[x] iOS / Firefox fallback documented and implemented

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 2, 2026

@Rocket1960 is attempting to deploy a commit to the truthixify's projects Team on Vercel.

A member of the Team first needs to authorize it.

@truthixify
Copy link
Copy Markdown
Contributor

Closing this one because it overlaps fully with your other open PR #49: every src/wallets/stellar/* file, the picker UI, the hook, the wallet tests, the Playwright spec are all also in #49. Two parallel PRs touching the same files from the same author will conflict.

Let's split cleanly:

That keeps each PR focused on one issue and avoids the conflict.

Thanks @Opeyemi01-del.

@truthixify truthixify closed this Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Browser push notifications for incoming Stellar payments

3 participants