Skip to content

[Enhancement] - add nostr wallet connect #239

@islandbitcoin

Description

@islandbitcoin

Feature: Nostr Wallet Connect (NWC / NIP-47) Support

Overview

Implement Nostr Wallet Connect (NIP-47) as a "wallet service" in the Flash stack, allowing external Nostr-enabled apps to send Lightning payments from a user's Flash wallet using a connection URI, subject to configurable spending limits.

Goals

  • Users can create NWC connections from the Flash mobile app
  • Each connection has independent spending limits (separate from account limits)
  • External apps can use NWC URIs to send Lightning payments without manual confirmation
  • Users can view, manage, and revoke connections at any time
  • Full NIP-47 compliance with encryption (NIP-44/NIP-04)

References


Implementation Plan - 7 PRs

Each PR is independently deployable and reviewable.

PR #1: NWC Foundation & Feature Flag

~280 lines | Backend

Deliverables:

  • MongoDB schema for NwcConnection collection
  • TypeScript types for NWC connection records
  • Repository pattern implementation (NwcConnectionsRepository)
  • Database migration script
  • Feature flag environment variable (NWC_ENABLED)
  • Unit tests for repository CRUD operations

Files:

  • flash/src/services/mongoose/schema.ts
  • flash/src/services/mongoose/schema.types.d.ts
  • flash/src/services/mongoose/nwc-connections.ts
  • flash/src/migrations/[timestamp]-add-nwc-connections.ts
  • flash/src/config/index.ts
  • flash/test/unit/services/nwc/repository.spec.ts

Deployment:

  • Run migration, feature flag defaults to false, no user-facing changes

PR #2: NIP-47 Protocol Layer

~250 lines | Backend

Deliverables:

  • NIP-47 encryption/decryption utilities (NIP-44 & NIP-04)
  • Request/response type definitions
  • Info event creation (kind 13194)
  • Notification event creation (kind 23197)
  • NWC URI generator utility
  • Unit tests for all crypto functions

Files:

  • flash/src/services/nostr/nip47.ts
  • flash/src/services/nwc/uri-generator.ts
  • flash/test/unit/services/nostr/nip47.spec.ts

Deployment:

  • Pure utilities, no side effects, independently testable

PR #3: NWC Wallet Service Daemon

~450 lines | Backend

Deliverables:

  • NwcWalletService class with relay management
  • Nostr relay subscription handling
  • Request event processing (pay_invoice, get_balance, get_info)
  • NWC-specific spending limit enforcement (separate from account limits)
  • Integration with existing Payments.payInvoiceByWalletId()
  • Server entry point (nwc-wallet-service.ts)
  • Package.json script to run service
  • Unit tests for limit checking and request handling

Files:

  • flash/src/services/nwc/wallet-service.ts
  • flash/src/servers/nwc-wallet-service.ts
  • flash/package.json
  • flash/test/unit/services/nwc/wallet-service.spec.ts
  • flash/test/unit/services/nwc/limits.spec.ts

Deployment:

  • Service binary deployable, only starts if NWC_ENABLED=true
  • No user-facing impact yet

PR #4: GraphQL API Layer

~380 lines | Backend

Deliverables:

  • GraphQL object types (NwcConnection, NwcConnectionStatus)
  • GraphQL input types (NwcConnectionCreateInput, NwcConnectionRevokeInput)
  • nwcConnectionCreate mutation (generates NWC URI)
  • nwcConnectionRevoke mutation
  • nwcConnections query
  • Feature flag checks in resolvers
  • Integration tests for all GraphQL operations
  • Authorization tests (users can only manage own connections)

Files:

  • flash/src/graphql/public/types/object/nwc-connection.ts
  • flash/src/graphql/public/types/input/nwc-connection.ts
  • flash/src/graphql/public/root/mutation/nwc-connection-create.ts
  • flash/src/graphql/public/root/mutation/nwc-connection-revoke.ts
  • flash/src/graphql/public/root/query/nwc-connections.ts
  • flash/src/graphql/public/mutations.ts
  • flash/src/graphql/public/queries.ts
  • flash/test/integration/graphql/nwc-mutations.spec.ts

Deployment:

  • GraphQL endpoints available but gated by feature flag
  • Backend complete, ready for mobile integration

Key Technical Decisions

Code Reuse Strategy

  • Nostr Pool: Reuse existing pool from /flash/src/utils/nostr.ts
  • Payment Flow: Use Payments.payInvoiceByWalletId() (existing)
  • Invoice Validation: Use decodeInvoice() (existing)
  • Repositories: Follow existing Mongoose repository patterns
  • GraphQL: Follow existing mutation/query structure patterns
  • Mobile UI: Reuse SettingsRow, GaloyPrimaryButton, GaloyInput components
  • QR Codes: Use existing react-native-qrcode-svg integration

NWC-Specific Limits (Separate from Account Limits)

  • Independent tracking: totalSpentSats, spendingResetAt on NwcConnection
  • Connection-level limits: spendingLimitSats, maxSinglePaymentSats, spendingPeriodHours
  • Separate validation in checkNwcLimits() method
  • Account limits still enforced as secondary safeguard via existing payment flow

Feature Flag Strategy

Backend:

NWC_ENABLED=true|false  // Main feature toggle
NWC_DEFAULT_RELAYS=wss://relay1,wss://relay2
NWC_DEFAULT_SPENDING_LIMIT_SATS=50000

GraphQL:
- Mutations/queries return error if NWC_ENABLED=false

Mobile:
- Settings row conditionally shown based on backend feature availability
- Query nwcConnections to detect backend support

---
Deployment & Rollout Plan

| Step | Action                                           | Impact                     |
|------|--------------------------------------------------|----------------------------|
| 1    | Deploy PRs #1-4 to prod with NWC_ENABLED=false   | No user impact             |
| 2    | Test on staging with NWC_ENABLED=true            | Verify full backend        |
| 3    | Deploy PRs #5-7 to mobile (app store submission) | Users see disabled feature |
| 4    | Enable NWC_ENABLED=true in production            | Feature goes live          |
| 5    | Monitor logs, limits, and error rates            | Operational monitoring     |
| 6    | Announce feature to users                        | Documentation & support    |

Rollback Plan

- Set NWC_ENABLED=false to disable feature
- Stop nwc-wallet-service daemon
- Mobile app gracefully hides settings row

---
Testing Strategy

Unit Tests

- Repository CRUD operations (PR #1)
- NIP-47 encryption/decryption (PR #2)
- NWC limit checking logic (PR #3)
- GraphQL resolvers (PR #4)
- Mobile component rendering (PR #6, #7)

Integration Tests

- GraphQL mutation/query flows (PR #4)
- Payment flow with mock Nostr relay (PR #3)
- E2E mobile flow: create  display  copy (PR #7)

Manual Testing

- Connect external NWC client (e.g., Amethyst, Alby)
- Verify payments work end-to-end
- Test limit enforcement (single payment & period limits)
- Test connection revocation
- Test error scenarios (expired invoice, insufficient balance, etc.)

---
Success Criteria

- Users can create NWC connections with custom limits
- External Nostr apps can pay Lightning invoices via NWC URI
- Spending limits enforced correctly (connection-level)
- Users can view connection usage and revoke access
- NIP-47 spec compliance verified
- No existing payment flows broken
- Documentation complete (user + developer)
- Feature flag allows safe rollout

---
Dependencies

- nostr-tools (already in backend & mobile)
- react-native-qrcode-svg (already in mobile)
- @react-native-clipboard/clipboard (already in mobile)
- MongoDB 4.4+
- Redis (for existing infra)

Metadata

Metadata

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions