Skip to content

nostrver-se/nostr-php-nwc

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Nostr Wallet Connect (NIP-47) implementation in PHP (nostr-php)

CI Packagist PHP Version

This project contains a complete client-side implementation of NIP-47 Nostr Wallet Connect for PHP, building upon nostr-php.

This project applied for the NWC Hackathon Grant on Geyser (Geyser project)

Async websocket communication is implemented using valtzu/guzzle-websocket-middleware, which is an opinionated decision and therefore the NWC functionality is provided as a separate library instead of added to the core functionality.

Overview

Nostr Wallet Connect (NWC) allows applications to connect to Lightning wallets over the Nostr protocol in a secure, decentralized way. This implementation provides:

  • Client-side functionality for connecting to NWC wallet services
  • Complete command support for all major Lightning operations
  • Secure encryption using NIP-04 (deprecated) or NIP-44 (recommended) for wallet communications
  • Comprehensive error handling with specific exception types
  • Event-driven architecture following Nostr patterns

Key Features

πŸ”— URI Parsing & Validation

  • Parse and validate NWC connection URIs
  • Support for multiple relays and optional Lightning addresses
  • Secure parameter validation and format checking

πŸ’° Lightning Operations

  • Get Balance - Check wallet balance
  • Pay Invoice - Pay Lightning invoices
  • Make Invoice - Create Lightning invoices
  • Lookup Invoice - Query invoice status
  • Get Info - Retrieve wallet capabilities

πŸ” Security

  • NIP-04/NIP-44 encryption for wallet communications
  • Proper key management and validation
  • Secure event signing and verification

⚑ Events

  • Request Events (kind 23194) - Encrypted commands to wallets
  • Response Events (kind 23195) - Encrypted responses from wallets
  • Info Events (kind 13194) - Public wallet capability announcements

Quick Start

1. Basic Connection

use dsbaars\nostr\Nip47\NwcClient;
use dsbaars\nostr\Nip47\NwcUri;

// Parse NWC URI
$nwcUri = 'nostr+walletconnect://wallet_pubkey?relay=wss://relay.com&secret=client_secret';
$client = new NwcClient($nwcUri);

// Check wallet capabilities
$info = $client->getWalletInfo();
echo "Supported methods: " . implode(', ', $info->getMethods());

2. Balance Check

$balance = $client->getBalance();
if ($balance->isSuccess()) {
    echo "Balance: " . $balance->getBalance() . " msats";
    echo "(" . $balance->getBalanceInSats() . " sats)";
}

3. Create Invoice

$invoice = $client->makeInvoice(
    amount: 1000,        // 1000 msats = 1 sat
    description: "Test payment",
    expiry: 3600         // 1 hour
);

if ($invoice->isSuccess()) {
    echo "Invoice: " . $invoice->getInvoice();
    echo "Payment hash: " . $invoice->getPaymentHash();
}

4. Pay Invoice

$payment = $client->payInvoice("lnbc1000n1...");
if ($payment->isPaymentSuccessful()) {
    echo "Payment successful!";
    echo "Preimage: " . $payment->getPreimage();
}

NIP-47 Implementation Status

This implementation provides complete coverage of the NIP-47 specification. Below are detailed tables showing all functionality and implementation status.

πŸ“‘ Event Kinds

Kind Description Purpose Implementation Class
13194 Info Event Wallet capability announcement βœ… InfoEvent.php
23194 Request Event Encrypted commands to wallet βœ… RequestEvent.php
23195 Response Event Encrypted responses from wallet βœ… ResponseEvent.php
23196 Notification Event Real-time wallet notifications βœ… NotificationEvent.php

πŸš€ Commands

Command Description Parameters Implementation Class
get_info Get wallet capabilities None βœ… GetInfoCommand.php
get_balance Get wallet balance None βœ… GetBalanceCommand.php
pay_invoice Pay Lightning invoice invoice, amount? βœ… PayInvoiceCommand.php
make_invoice Create Lightning invoice amount, description?, description_hash?, expiry? βœ… MakeInvoiceCommand.php
lookup_invoice Lookup invoice details payment_hash?, invoice? βœ… LookupInvoiceCommand.php
list_transactions List wallet transactions from?, until?, limit?, offset?, unpaid?, type? βœ… ListTransactionsCommand.php
pay_keysend Send keysend payment amount, pubkey, preimage?, tlv_records? βœ… PayKeysendCommand.php
multi_pay_invoice Pay multiple invoices invoices[] βœ… MultiPayInvoiceCommand.php
multi_pay_keysend Send multiple keysends keysends[] βœ… MultiPayKeysendCommand.php

πŸ“¨ Responses

Response Description Fields Implementation Class
get_info Wallet info response alias, color, pubkey, network, block_height, block_hash, methods[], notifications[] βœ… GetInfoResponse.php
get_balance Balance response balance βœ… GetBalanceResponse.php
pay_invoice Payment response preimage, fees_paid? βœ… PayInvoiceResponse.php
make_invoice Invoice creation response type, invoice?, description?, description_hash?, preimage?, payment_hash, amount, fees_paid, created_at, expires_at?, metadata? βœ… MakeInvoiceResponse.php
lookup_invoice Invoice lookup response type, invoice?, description?, description_hash?, preimage?, payment_hash, amount, fees_paid, created_at, expires_at?, settled_at?, metadata? βœ… LookupInvoiceResponse.php
list_transactions Transaction list response transactions[] βœ… ListTransactionsResponse.php
pay_keysend Keysend payment response preimage, fees_paid? βœ… PayKeysendResponse.php
multi_pay_invoice Multi-payment response Multiple individual responses βœ… MultiPayInvoiceResponse.php
multi_pay_keysend Multi-keysend response Multiple individual responses βœ… MultiPayKeysendResponse.php

πŸ”” Notifications

Type Description Fields Implementation Class
payment_received Payment successfully received type, invoice, description?, description_hash?, preimage, payment_hash, amount, fees_paid, created_at, expires_at?, settled_at, metadata? βœ… PaymentReceivedNotification.php
payment_sent Payment successfully sent type, invoice, description?, description_hash?, preimage, payment_hash, amount, fees_paid, created_at, expires_at?, settled_at, metadata? βœ… PaymentSentNotification.php

❌ Error Codes

Code Description When Used Implementation
RATE_LIMITED Client sending commands too fast Rate limiting exceeded βœ…
NOT_IMPLEMENTED Command not known/implemented Unsupported methods βœ…
INSUFFICIENT_BALANCE Not enough funds available Payment amount > balance βœ…
QUOTA_EXCEEDED Spending quota exceeded Budget limits reached βœ…
RESTRICTED Operation not allowed Permission denied βœ…
UNAUTHORIZED No wallet connected Invalid authorization βœ…
INTERNAL Internal wallet error Server-side issues βœ…
OTHER Other unspecified error Catch-all error βœ…
PAYMENT_FAILED Payment processing failed Routing/capacity issues βœ…
NOT_FOUND Invoice not found Invalid payment hash/invoice βœ…

πŸ”— URI Components

Component Description Required Format Implementation
Protocol NWC protocol identifier βœ… nostr+walletconnect:// βœ…
Pubkey Wallet service public key βœ… 32-byte hex βœ…
relay Relay URL(s) for communication βœ… WebSocket URL βœ…
secret Client private key βœ… 32-byte hex βœ…
lud16 Lightning address ❌ Lightning address format βœ…

πŸ” Security Features

Feature Description Implementation Notes
NIP-04 Encryption End-to-end encryption of commands/responses βœ… Deprecated, using NIP-44 recommended
NIP-44 Encryption End-to-end encryption of commands/responses βœ… All wallet communications encrypted
Event Signing Cryptographic signatures on all events βœ… Prevents tampering
Key Isolation Unique keys per wallet connection βœ… Improves privacy
Relay Authentication Optional relay-level auth βœ… Metadata protection
Request Expiration Time-bounded request validity βœ… Prevents replay attacks

🎯 Advanced Features

Feature Description Implementation Class
WebSocket Communication Real-time relay communication βœ… NwcClient.php
Notification Listener Real-time payment notifications βœ… NwcNotificationListener.php
Multi-Command Support Batch payment operations βœ… MultiPay*Command.php
Filter Management Subscription filtering βœ… NwcClient.php
Connection Validation URI and capability validation βœ… NwcUri.php
Error Handling Comprehensive exception system βœ… Exception/ namespace
Logging Support Configurable logging βœ… PSR-3 compatible

Directory Structure

src/Nip47/
β”œβ”€β”€ NwcClient.php                    # Main client implementation
β”œβ”€β”€ NwcNotificationListener.php      # Real-time notification listener  
β”œβ”€β”€ NwcUri.php                       # URI parsing and validation
β”œβ”€β”€ NwcUriInterface.php              # URI interface
β”œβ”€β”€ ErrorCode.php                    # NWC error codes enum
β”‚
β”œβ”€β”€ Command/                         # Command implementations
β”‚   β”œβ”€β”€ CommandInterface.php
β”‚   β”œβ”€β”€ AbstractCommand.php
β”‚   β”œβ”€β”€ GetBalanceCommand.php        # βœ… get_balance
β”‚   β”œβ”€β”€ GetInfoCommand.php           # βœ… get_info
β”‚   β”œβ”€β”€ PayInvoiceCommand.php        # βœ… pay_invoice
β”‚   β”œβ”€β”€ MakeInvoiceCommand.php       # βœ… make_invoice
β”‚   β”œβ”€β”€ LookupInvoiceCommand.php     # βœ… lookup_invoice
β”‚   β”œβ”€β”€ ListTransactionsCommand.php  # βœ… list_transactions
β”‚   β”œβ”€β”€ PayKeysendCommand.php        # βœ… pay_keysend
β”‚   β”œβ”€β”€ MultiPayInvoiceCommand.php   # βœ… multi_pay_invoice
β”‚   └── MultiPayKeysendCommand.php   # βœ… multi_pay_keysend
β”‚
β”œβ”€β”€ Response/                        # Response implementations
β”‚   β”œβ”€β”€ ResponseInterface.php
β”‚   β”œβ”€β”€ AbstractResponse.php
β”‚   β”œβ”€β”€ GetBalanceResponse.php       # βœ… Balance data + conversions
β”‚   β”œβ”€β”€ GetInfoResponse.php          # βœ… Wallet info + capability checks
β”‚   β”œβ”€β”€ PayInvoiceResponse.php       # βœ… Payment confirmation
β”‚   β”œβ”€β”€ MakeInvoiceResponse.php      # βœ… Invoice creation
β”‚   β”œβ”€β”€ LookupInvoiceResponse.php    # βœ… Invoice details + status
β”‚   β”œβ”€β”€ ListTransactionsResponse.php # βœ… Transaction history
β”‚   β”œβ”€β”€ PayKeysendResponse.php       # βœ… Keysend confirmation
β”‚   β”œβ”€β”€ MultiPayInvoiceResponse.php  # βœ… Batch payment results
β”‚   └── MultiPayKeysendResponse.php  # βœ… Batch keysend results
β”‚
β”œβ”€β”€ Event/                           # Nostr event implementations
β”‚   β”œβ”€β”€ RequestEvent.php             # βœ… kind 23194
β”‚   β”œβ”€β”€ ResponseEvent.php            # βœ… kind 23195
β”‚   β”œβ”€β”€ InfoEvent.php                # βœ… kind 13194
β”‚   └── NotificationEvent.php        # βœ… kind 23196
β”‚
β”œβ”€β”€ Notification/                    # Notification system
β”‚   β”œβ”€β”€ NotificationInterface.php
β”‚   β”œβ”€β”€ NotificationFactory.php      # βœ… Factory for creating notifications
β”‚   β”œβ”€β”€ PaymentReceivedNotification.php # βœ… payment_received
β”‚   └── PaymentSentNotification.php     # βœ… payment_sent
β”‚
└── Exception/                       # Exception hierarchy
    β”œβ”€β”€ NwcException.php
    β”œβ”€β”€ InvalidUriException.php
    β”œβ”€β”€ CommandException.php
    β”œβ”€β”€ PaymentFailedException.php
    β”œβ”€β”€ InsufficientBalanceException.php
    β”œβ”€β”€ UnauthorizedException.php
    └── RateLimitedException.php

Examples

This project includes working examples demonstrating all NIP-47 functionality with a centralized configuration system.

Quick Start

First, configure your wallet connection:

cd examples/
cp config.php.example config.php
# Edit config.php with your actual NWC URI

Running Examples

cd examples/

# Complete wallet functionality demo
php client-example.php

# URI parsing and validation
php uri-parsing-example.php

# End-to-end payment workflow
php payment-flow-example.php

# Real-time notification listening
php notification-listener.php

# Simple wallet info and balance check
php get-info-command.php

Configuration

The examples use environment variables for easy configuration:

# Set your NWC URI
export NWC_URI="nostr+walletconnect://your-wallet-details"

# Enable verbose output
export NWC_VERBOSE=true

# Run any example
php client-example.php

Example Output

Nostr Wallet Connect Client Example
===================================

1. Parsing NWC URI...
   βœ“ Wallet Pubkey: b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4
   βœ“ Relays: wss://relay.getalby.com/v1
   βœ“ Secret: 71a8c14c...
   βœ“ Lightning Address: wallet@example.com

2. Creating NWC client...
   βœ“ Client created with pubkey: a1b2c3d4e5f6789...

3. Getting wallet info...
   βœ“ Wallet connected successfully!
     - Alias: My Lightning Wallet
     - Network: bitcoin
     - Supported methods: get_balance, pay_invoice, make_invoice, lookup_invoice
     - Supported notifications: payment_received, payment_sent

4. Getting wallet balance...
   βœ“ Balance: 100000 msats
     - In sats: 100 sats
     - In BTC: 0.00000100 BTC

5. Creating invoice...
   βœ“ Invoice created!
     - Amount: 21000 msats
     - Description: Test invoice from NWC client
     - Invoice: lnbc210n1pjw8...

6. List transactions...
   βœ“ Found 5 transactions
   - Incoming: 3
   - Outgoing: 2
   - Total amount: 150000 msats
   - Total fees: 2100 msats

Example completed successfully!

Error Handling

The implementation includes comprehensive error handling:

use dsbaars\nostr\Nip47\Exception\PaymentFailedException;
use dsbaars\nostr\Nip47\Exception\InsufficientBalanceException;

try {
    $payment = $client->payInvoice($invoice);
} catch (PaymentFailedException $e) {
    echo "Payment failed: " . $e->getMessage();
} catch (InsufficientBalanceException $e) {
    echo "Insufficient balance: " . $e->getMessage();
} catch (NwcException $e) {
    echo "General NWC error: " . $e->getMessage();
}

NIP-47 Compliance

This implementation supports:

  • βœ… All required event kinds (23194, 23195, 13194, 23196)
  • βœ… All standard commands (get_info, get_balance, pay_invoice, make_invoice, lookup_invoice, list_transactions, pay_keysend, multi_pay_invoice, multi_pay_keysend)
  • βœ… All notification types (payment_received, payment_sent)
  • βœ… All error codes per specification
  • βœ… Proper NIP-04/NIP-44 encryption
  • βœ… URI format validation
  • βœ… Relay communication
  • βœ… Event signing and verification
  • βœ… Real-time WebSocket notifications

Security Considerations

  • Encryption: All communications are encrypted using NIP-04/NIP-44
  • Authentication: Events are signed with client private keys
  • Validation: All inputs are validated before processing
  • Error Handling: Sensitive information is not leaked in errors
  • Timeouts: Commands have reasonable timeout limits
  • Rate Limiting: Built-in support for rate limit handling

Testing

⚠️ Important: Be careful when testing with real wallets and real Bitcoin!

Running Tests

# Run all tests
php vendor/bin/phpunit tests/

# Run specific test file
php vendor/bin/phpunit tests/Nip47Test.php

Testing with Examples

  1. Use testnet wallets for development
  2. Start with small amounts - examples use 1-100 sats by default
  3. Configure safely - set NWC_VERBOSE=true for detailed output
  4. Verify parameters before executing payments
  5. Check capabilities with get-info-command.php first

Test Configuration

# Use testnet amounts
export NWC_TEST_AMOUNT=1000      # 1 sat
export NWC_SMALL_AMOUNT=21000    # 21 sats  
export NWC_MEDIUM_AMOUNT=100000  # 100 sats

# Enable verbose mode
export NWC_VERBOSE=true

# Test basic functionality
cd examples/
php get-info-command.php
php client-example.php

Integration

To integrate NWC into your application:

  1. Parse the NWC URI from user input or configuration
  2. Create an NwcClient instance
  3. Check wallet capabilities with getWalletInfo()
  4. Implement your payment flow using the available commands
  5. Handle errors gracefully with proper exception handling

About

Nostr Wallet Connect (NIP-47) implementation in PHP (nostr-php)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • PHP 100.0%