feat: nostr transport layer for HTTP-free API access #3

Open
padreug wants to merge 2 commits from nostr-native-transport-forgejo into dev
Owner

Summary

  • Add a nostr event transport layer so LNbits API can be accessed over nostr relays (NIP-44 v2 encrypted kind-21000 events), modeled after Lightning.pub's architecture
  • Eliminates the need for port forwarding, DNS, or SSL -- the instance connects outbound to commodity relays and clients communicate via encrypted nostr events
  • HTTP API continues to work in parallel, this is an additional transport, not a replacement

Architecture

                    HTTP (existing)
Client ──────────────────────────────────► LNbits FastAPI ──► Service Layer
                                                ▲
Client ──► Nostr Relay ──► NostrTransport ──────┘
           (commodity,      (new module,
            untrusted)       decrypts & dispatches)

New module: lnbits/core/services/nostr_transport/

File Purpose
models.py NostrRpcRequest / NostrRpcResponse pydantic models
crypto.py NIP-44 v2 encryption (ECDH + HKDF + ChaCha20 + HMAC-SHA256)
auth.py Nostr pubkey → LNbits Account → Wallet auth resolution
relay_pool.py Multi-relay WebSocket pool with auto-reconnect + event dedup
dispatcher.py RPC registry with 7 core wallet endpoints
__init__.py Entry point: keypair init, RPC registration, pool lifecycle

Registered RPCs

rpc_name Auth HTTP equivalent
create_invoice invoice_key POST /api/v1/payments {out:false}
pay_invoice admin_key POST /api/v1/payments {out:true}
get_payment none GET /api/v1/payments/{hash}
list_payments invoice_key GET /api/v1/payments
get_wallet invoice_key GET /api/v1/wallet
create_wallet account POST /api/v1/wallet
decode_payment none POST /api/v1/payments/decode

Configuration

NOSTR_TRANSPORT_ENABLED=true
NOSTR_TRANSPORT_PRIVATE_KEY=<64-char-hex-or-nsec>
NOSTR_TRANSPORT_RELAYS=["wss://relay.damus.io","wss://relay.primal.net"]

Test plan

  • Verify LNbits starts cleanly with NOSTR_TRANSPORT_ENABLED=false (no change in behavior)
  • Verify LNbits starts and connects to relays with transport enabled
  • Send a kind-21000 NIP-44 encrypted RPC event from a test client and verify response
  • Test create_invoice / pay_invoice / get_wallet RPCs over nostr
  • Verify auto-account creation for new nostr pubkeys
  • Verify wallet ownership check prevents cross-account access

🤖 Generated with Claude Code

## Summary - Add a nostr event transport layer so LNbits API can be accessed over nostr relays (NIP-44 v2 encrypted kind-21000 events), modeled after [Lightning.pub](https://github.com/shocknet/Lightning.Pub)'s architecture - Eliminates the need for port forwarding, DNS, or SSL -- the instance connects outbound to commodity relays and clients communicate via encrypted nostr events - HTTP API continues to work in parallel, this is an additional transport, not a replacement ## Architecture ``` HTTP (existing) Client ──────────────────────────────────► LNbits FastAPI ──► Service Layer ▲ Client ──► Nostr Relay ──► NostrTransport ──────┘ (commodity, (new module, untrusted) decrypts & dispatches) ``` ## New module: `lnbits/core/services/nostr_transport/` | File | Purpose | |------|---------| | `models.py` | `NostrRpcRequest` / `NostrRpcResponse` pydantic models | | `crypto.py` | NIP-44 v2 encryption (ECDH + HKDF + ChaCha20 + HMAC-SHA256) | | `auth.py` | Nostr pubkey → LNbits Account → Wallet auth resolution | | `relay_pool.py` | Multi-relay WebSocket pool with auto-reconnect + event dedup | | `dispatcher.py` | RPC registry with 7 core wallet endpoints | | `__init__.py` | Entry point: keypair init, RPC registration, pool lifecycle | ## Registered RPCs | `rpc_name` | Auth | HTTP equivalent | |------------|------|-----------------| | `create_invoice` | invoice_key | `POST /api/v1/payments {out:false}` | | `pay_invoice` | admin_key | `POST /api/v1/payments {out:true}` | | `get_payment` | none | `GET /api/v1/payments/{hash}` | | `list_payments` | invoice_key | `GET /api/v1/payments` | | `get_wallet` | invoice_key | `GET /api/v1/wallet` | | `create_wallet` | account | `POST /api/v1/wallet` | | `decode_payment` | none | `POST /api/v1/payments/decode` | ## Configuration ```env NOSTR_TRANSPORT_ENABLED=true NOSTR_TRANSPORT_PRIVATE_KEY=<64-char-hex-or-nsec> NOSTR_TRANSPORT_RELAYS=["wss://relay.damus.io","wss://relay.primal.net"] ``` ## Test plan - [ ] Verify LNbits starts cleanly with `NOSTR_TRANSPORT_ENABLED=false` (no change in behavior) - [ ] Verify LNbits starts and connects to relays with transport enabled - [ ] Send a kind-21000 NIP-44 encrypted RPC event from a test client and verify response - [ ] Test `create_invoice` / `pay_invoice` / `get_wallet` RPCs over nostr - [ ] Verify auto-account creation for new nostr pubkeys - [ ] Verify wallet ownership check prevents cross-account access 🤖 Generated with [Claude Code](https://claude.com/claude-code)
padreug added 2 commits 2026-04-10 09:50:48 +00:00
Enable LNbits API access over nostr relays using NIP-44 v2 encrypted
kind-21000 events, modeled after Lightning.pub's architecture. This
eliminates the need for port forwarding, DNS, or SSL -- the instance
connects outbound to commodity relays and clients communicate via
encrypted nostr events.

New module: lnbits/core/services/nostr_transport/
- crypto.py: NIP-44 v2 (ECDH + HKDF + ChaCha20 + HMAC-SHA256)
- relay_pool.py: multi-relay WebSocket pool with auto-reconnect
- dispatcher.py: RPC registry with 7 core wallet endpoints
- auth.py: nostr pubkey -> LNbits account/wallet resolution
- models.py: request/response pydantic models

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix: adapt nostr transport to forgejo fork's secp256k1 library
Some checks failed
codeql / analyze (pull_request) Has been cancelled
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (CoreLightningRestWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (pull_request) Has been cancelled
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (pull_request) Has been cancelled
LNbits CI / migration (3.10) (pull_request) Has been cancelled
LNbits CI / migration (3.11) (pull_request) Has been cancelled
LNbits CI / migration (3.12) (pull_request) Has been cancelled
LNbits CI / openapi (pull_request) Has been cancelled
LNbits CI / test-api (, 3.10) (pull_request) Has been cancelled
LNbits CI / test-api (, 3.11) (pull_request) Has been cancelled
LNbits CI / test-api (, 3.12) (pull_request) Has been cancelled
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (pull_request) Has been cancelled
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (pull_request) Has been cancelled
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (pull_request) Has been cancelled
LNbits CI / test-wallets (, 3.10) (pull_request) Has been cancelled
LNbits CI / test-wallets (, 3.11) (pull_request) Has been cancelled
LNbits CI / test-wallets (, 3.12) (pull_request) Has been cancelled
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (pull_request) Has been cancelled
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (pull_request) Has been cancelled
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (pull_request) Has been cancelled
LNbits CI / test-unit (, 3.10) (pull_request) Has been cancelled
LNbits CI / test-unit (, 3.11) (pull_request) Has been cancelled
LNbits CI / test-unit (, 3.12) (pull_request) Has been cancelled
LNbits CI / regtest (CoreLightningWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (EclairWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (LNbitsWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (LndRestWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (LndWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / jmeter (3.10) (pull_request) Has been cancelled
bae881587c
The aiolabs/lnbits fork uses python-secp256k1 instead of coincurve
for elliptic curve operations. Update crypto.py, relay_pool.py, and
__init__.py to use the secp256k1 API (tweak_mul, schnorr_sign).

Also comment out account.activated check since this field doesn't
exist in the current fork (present in upstream dev).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Some checks failed
LNbits CI / lint (pull_request) Has been cancelled
codeql / analyze (pull_request) Has been cancelled
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (CoreLightningRestWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (pull_request) Has been cancelled
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (pull_request) Has been cancelled
LNbits CI / migration (3.10) (pull_request) Has been cancelled
LNbits CI / migration (3.11) (pull_request) Has been cancelled
LNbits CI / migration (3.12) (pull_request) Has been cancelled
LNbits CI / openapi (pull_request) Has been cancelled
LNbits CI / test-api (, 3.10) (pull_request) Has been cancelled
LNbits CI / test-api (, 3.11) (pull_request) Has been cancelled
LNbits CI / test-api (, 3.12) (pull_request) Has been cancelled
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (pull_request) Has been cancelled
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (pull_request) Has been cancelled
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (pull_request) Has been cancelled
LNbits CI / test-wallets (, 3.10) (pull_request) Has been cancelled
LNbits CI / test-wallets (, 3.11) (pull_request) Has been cancelled
LNbits CI / test-wallets (, 3.12) (pull_request) Has been cancelled
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (pull_request) Has been cancelled
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (pull_request) Has been cancelled
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (pull_request) Has been cancelled
LNbits CI / test-unit (, 3.10) (pull_request) Has been cancelled
LNbits CI / test-unit (, 3.11) (pull_request) Has been cancelled
LNbits CI / test-unit (, 3.12) (pull_request) Has been cancelled
LNbits CI / regtest (CoreLightningWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (EclairWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (LNbitsWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (LndRestWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / regtest (LndWallet, 3.10) (pull_request) Has been cancelled
LNbits CI / jmeter (3.10) (pull_request) Has been cancelled
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin nostr-native-transport-forgejo:nostr-native-transport-forgejo
git checkout nostr-native-transport-forgejo

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git checkout dev
git merge --no-ff nostr-native-transport-forgejo
git checkout nostr-native-transport-forgejo
git rebase dev
git checkout dev
git merge --ff-only nostr-native-transport-forgejo
git checkout nostr-native-transport-forgejo
git rebase dev
git checkout dev
git merge --no-ff nostr-native-transport-forgejo
git checkout dev
git merge --squash nostr-native-transport-forgejo
git checkout dev
git merge --ff-only nostr-native-transport-forgejo
git checkout dev
git merge nostr-native-transport-forgejo
git push origin dev
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: aiolabs/lnbits#3
No description provided.