No description
Find a file
daywalker90 c41d71302b bound list_transactions work to prevent DoS
list_transactions was a DoS vector: it loaded the full invoice and
payment history, made one decode rpc-call per entry, and re-serialized
the whole result set for every trimmed entry (O(n^2)), all while holding
the global rpc lock that serializes every other nwc request and command.

- run list_transactions on a dedicated rpc connection so it no longer
  stalls the rest of the plugin
- page backwards through listinvoices by created_index instead of
  fetching the whole history, using the wait rpc to get the newest index
- only decode the kept candidates and honor the from/until and unpaid
  filters while collecting them
- cap work per request at MAX_TRANSACTIONS (500) regardless of node
  history size
- limit pays and hold invoices to the same bound before decoding
- make trim_to_size a single serialization pass instead of O(n^2)
2026-08-09 14:18:57 +02:00
.cargo add linker config for cargo 2026-04-03 10:30:45 +02:00
.github Bump actions/setup-python from 6 to 7 2026-08-08 15:18:53 +02:00
protos add support for holdinvoices 2026-08-08 15:06:37 +02:00
src bound list_transactions work to prevent DoS 2026-08-09 14:18:57 +02:00
tests reserve budget during in-flight payments, drop lock while paying 2026-08-09 12:29:09 +02:00
tools init 2025-04-02 17:38:52 +02:00
.gitignore tests: use nostr-rs-relay instead of nostr_relay 2025-12-31 23:56:36 +01:00
.rustfmt.toml add rustfmt.toml and apply it 2025-11-10 15:36:56 +01:00
build.rs update dependencies, upgrade nostr and cln dependencies 2026-08-08 15:06:37 +02:00
Cargo.lock update for nostr 0.45 release version 2026-08-08 15:06:37 +02:00
Cargo.toml update for nostr 0.45 release version 2026-08-08 15:06:37 +02:00
CHANGELOG.md use xkeysend on CLN v26.06+ 2026-08-08 15:06:37 +02:00
coffee.yml fix budget race condition 2026-04-23 11:04:47 +02:00
flake.lock nix: update lock, remove unused follow 2025-08-26 15:30:34 +02:00
flake.nix nix: update lock, remove unused follow 2025-08-26 15:30:34 +02:00
LICENSE init 2025-04-02 17:38:52 +02:00
README.md README: update binaries notes 2026-08-08 15:19:11 +02:00
SECURITY.md SECURITY.md: init 2026-08-08 15:08:48 +02:00

cln-nip47

A core lightning plugin to connect wallets via Nostr Wallet Connect (NWC) as specified in NIP-47.

Installation

For general plugin installation instructions see the plugins repo README.md

Release binaries for

  • x86_64-linux
  • armv7-linux (Raspberry Pi 32bit)
  • aarch64-linux (Raspberry Pi 64bit)
  • universal-apple-darwin (macOS)

can be found on the release page. If you are unsure about your architecture you can run uname -m.

Building

You can build the plugin yourself instead of using the release binaries. First clone the repo:

git clone https://github.com/daywalker90/cln-nip47.git

Install a recent rust version (rustup is recommended) and in the cln-nip47 folder run:

cargo build --release

After that the binary will be here: target/release/cln-nip47

Note: Release binaries are built with the optimized profile.

Documentation

Receive-only NWC

If you want a receive-only NWC which also announces itself without any pay methods use nip47-create or nip47-budget and set budget_msat to 0. Do NOT set an interval on these.

Relays

It is highly recommended to use your own private relay since public relays may limit content length, amount of public keys per IP or require unsupported things like proof of work or payments. Each NWC you create is a separate public key and the list_transactions method can have quite a large content length! If you still want to use public relays, consider if you need nip47 notifications: if not, disable them with nip47-notifications=false. This will reduce the amount of events send to the relay and maybe not get you rate limited as quickly.

For a private relay you can for example use nostr-rs-relay with pubkey_whitelist set to both clientkey_public and walletkey_public (returned from nip47-create/nip47-list).

Options

  • nip47-relays: Specify the relays that you want to use with your NWC. Can be set multiple times to use multiple relays. NWC's you create will save these and even if you add or remove relays keep the relays from the moment you created that NWC. You must set this atleast one time.
  • nip47-notifications: Enable/disable nip47 notifications. Default is enabled (true)

Methods

  • nip47-create label [budget_msat] [interval]

    • create a new NWC string (uri) with the currently configured relays. For example: nip47-create mynwc 10000 1d will let you spend 10 satoshis every day using that NWC
    • label: a label to identify this NWC
    • budget_msat: optional. Set an absolute budget in msat that this NWC is allowed to use. This will also be your balance in your wallet. If you don't set this, the NWC will be allowed to use your whole node balance and show that aswell in your wallet! Set it to 0 to disable paying anything with this NWC
    • interval: optional. Set an amount of time after which the budget will be refreshed to the amount specified in budget_msat, e.g.:5seconds or 4weeks. Supported time units are:
      • seconds: "second", "seconds", "sec", "secs", "s"
      • minutes: "minute", "minutes", "min", "mins", "m"
      • hours: "hour", "hours", "h"
      • days: "day", "days", "d"
      • weeks: "week", "weeks", "w"
  • nip47-revoke label

    • revoke and remove all data related to a previously created NWC with label
    • label: the label the NWC was created with
  • nip47-budget label [budget_msat] [interval]

    • update/add/remove a budget for an existing NWC. For example: nip47-budget mynwc 10000 1d will let you spend 10 satoshis every day using that NWC
    • label: a label to identify this NWC
    • budget_msat: optional. Set an absolute budget in msat that this NWC is allowed to use. This will also be your balance in your wallet. If you don't set this, the NWC will be allowed to use your whole node balance and show that aswell in your wallet! Set it to 0 to disable paying anything with this NWC
    • interval: optional. Set an amount of time after which the budget will be refreshed to the amount specified in budget_msat, e.g.:5seconds or 4weeks. Supported time units are the same as in nip47-create
  • nip47-list [label]

    • list all NWC configurations or just the one with label
    • label: optional. The label the NWC was created with

Holdinvoice support

For methods or notifications related to holdinvoices you need v0.3.2+ of hold with enabled grpc (which is the default just make sure the port is free)

Supported NWC methods

  • pay_invoice
  • pay_keysend (no preimage in request allowed since CLN only supports generating it itself)
  • make_invoice
  • lookup_invoice
  • list_transactions
  • get_balance
  • get_info (no block_hash)
  • make_hold_invoice (requires Holdinvoice support)
  • cancel_hold_invoice (requires Holdinvoice support)
  • settle_hold_invoice (requires Holdinvoice support)

Supported NWC notifications

Supported content encryption: