Skip to main content

Nostr Wallet Connect (NWC)

Nostr Wallet Connect (NWC) is an open protocol that enables Nostr apps to interact with Lightning wallets. Defined by NIP-47, it's the standard for wallet connectivity in the Nostr ecosystem.

What is NWC?​

NWC provides:

  • Standardized communication between apps and wallets
  • Encrypted messages via Nostr relays
  • Budget controls for spending limits
  • Cross-platform compatibility

How NWC Works​

Connection Flow​

  1. Wallet generates connection string
  2. User imports into app
  3. App sends encrypted requests
  4. Wallet processes and responds

Communication​

All messages are NIP-04 encrypted Nostr events:

The relay only sees encrypted blobs - it can't read payment details.

Connection String Format​

nostr+walletconnect://[wallet_pubkey]?
relay=[relay_url]&
secret=[shared_secret]&
lud16=[optional_lightning_address]

Components​

ComponentPurpose
wallet_pubkeyWallet's Nostr public key
relayRelay for communication
secretEncryption key (hex)
lud16Optional Lightning address

Example​

nostr+walletconnect://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?
relay=wss%3A%2F%2Frelay.getalby.com%2Fv1&
secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c

NWC Commands​

pay_invoice​

Pay a Lightning invoice:

{
"method": "pay_invoice",
"params": {
"invoice": "lnbc1000n1..."
}
}

Response:

{
"result_type": "pay_invoice",
"result": {
"preimage": "payment_preimage_hex"
}
}

make_invoice​

Create an invoice:

{
"method": "make_invoice",
"params": {
"amount": 1000,
"description": "Payment for service",
"expiry": 3600
}
}

Response:

{
"result_type": "make_invoice",
"result": {
"invoice": "lnbc1000n1...",
"payment_hash": "..."
}
}

get_balance​

Check wallet balance:

{
"method": "get_balance",
"params": {}
}

Response:

{
"result_type": "get_balance",
"result": {
"balance": 50000
}
}

get_info​

Get wallet information:

{
"method": "get_info",
"params": {}
}

Response:

{
"result_type": "get_info",
"result": {
"alias": "My Wallet",
"color": "#ff9900",
"pubkey": "node_pubkey",
"network": "mainnet",
"methods": ["pay_invoice", "make_invoice", "get_balance"]
}
}

lookup_invoice​

Check invoice status:

{
"method": "lookup_invoice",
"params": {
"payment_hash": "..."
}
}

list_transactions​

Get transaction history:

{
"method": "list_transactions",
"params": {
"limit": 10,
"offset": 0
}
}

Event Kinds​

KindPurpose
23194NWC Request (app → wallet)
23195NWC Response (wallet → app)
13194NWC Info event

Setting Up NWC​

Wallet Side (Service)​

  1. Generate keypair for NWC connections
  2. Set up relay for communication
  3. Generate connection strings for users
  4. Process incoming requests
  5. Send encrypted responses

App Side (Client)​

  1. Parse connection string
  2. Store wallet pubkey and secret
  3. Subscribe to response events
  4. Send encrypted requests
  5. Handle responses

Example: Connecting Alby to Damus​

  1. In Alby:

    • Go to Settings → Connections
    • Create new app connection
    • Copy NWC connection string
  2. In Damus:

    • Go to Settings → Wallet
    • Select "Nostr Wallet Connect"
    • Paste connection string
    • Test with small zap

Budget Controls​

Wallets can implement spending limits:

const connection = {
budgetMsat: 100000000, // 100,000 sats
budgetRenewal: "monthly",
singlePaymentLimit: 10000000 // 10,000 sats max per payment
};
Security Practice

Always set a reasonable budget when creating NWC connections. This limits damage if the connection is compromised.

Error Handling​

Error Response Format​

{
"result_type": "pay_invoice",
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Not enough funds"
}
}

Common Error Codes​

CodeMeaning
RATE_LIMITEDToo many requests
NOT_IMPLEMENTEDMethod not supported
INSUFFICIENT_BALANCENot enough funds
PAYMENT_FAILEDLightning payment failed
NOT_FOUNDInvoice not found
QUOTA_EXCEEDEDBudget limit reached
RESTRICTEDPermission denied
UNAUTHORIZEDInvalid connection
INTERNALServer error

Implementations​

Wallet Services​

  • Alby - Full NWC support
  • Alby Hub - Self-hosted NWC
  • Mutiny - NWC enabled
  • LNbits - NWC extension
  • Zeus - Mobile NWC

Libraries​

  • @getalby/sdk - JavaScript SDK
  • nwc - Rust library
  • nostr-tools - TypeScript utilities
  • NDK - Nostr Development Kit

Example Code​

import { webln } from '@getalby/sdk';

// Connect via NWC
const nwc = new webln.NWC({
nostrWalletConnectUrl: 'nostr+walletconnect://...'
});

await nwc.enable();

// Pay invoice
const result = await nwc.sendPayment('lnbc1000n1...');
console.log('Payment preimage:', result.preimage);

// Get balance
const balance = await nwc.getBalance();
console.log('Balance:', balance.balance, 'sats');

Security Considerations​

Connection String Safety​

  • Treat like a password
  • Don't share publicly
  • Regenerate if compromised
  • Use separate connections per app

Relay Trust​

The relay can see:

  • That communication is happening
  • Event kinds and pubkeys
  • Cannot read encrypted content

Revocation​

To revoke access:

  1. Delete the connection in wallet
  2. Wallet stops responding to requests
  3. App can no longer make payments

Resources​


Universal Protocol

NWC eliminates the need for apps to integrate with each wallet individually. One protocol connects any app to any compatible wallet.