38 Commits

Author SHA1 Message Date
f321x fd230cf9d1 plugin: nwc: handle 'null' params in request
Some clients send 'params: null' instead of 'params: {}' or no
params key at all.
2026-04-07 09:52:13 +02:00
f321x b9a24ae1cf plugin: nwc: handle missing params dict in request
Even though the NIP-47 specification kind of defines that requests should
always pass a params dict in their request i witnessed way too often
that clients don't include it in some requests where it is technically
not neccessary and we fail on it.
Handling this gracefully improves compatibility without obvious
downsides.
2026-03-27 15:05:15 +01:00
f321x f64923b472 plugin: nwc: lookup_invoice: fix exc, include b11
Fixes exception in lookup_invoice:
```
 62.69 | E | plugins.nwc.nwcserver.NWCServer | Error handling nwc request
Traceback (most recent call last):
  File "/home/user/code/vibecoding_vm/electrum/electrum/plugins/nwc/nwcserver.py", line 381, in run_request_task
    await task
  File "/home/user/code/vibecoding_vm/electrum/electrum/util.py", line 1211, in wrapper
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/code/vibecoding_vm/electrum/electrum/plugins/nwc/nwcserver.py", line 526, in handle_lookup_invoice
    info = self.wallet.lnworker.get_payment_info(invoice.payment_hash, direction=RECEIVED)
                                                 ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Invoice' object has no attribute 'payment_hash'
```

Always includes bolt11 invoice in response, even if the client already
sent it to us in the request. It doesn't seem useful and is marked
optional in the spec but https://sandbox.albylabs.com considers the
response invalid if the invoice is not included.
2026-03-06 14:42:42 +01:00
f321x f53203d171 plugin: nwc: consider inflight htlcs in get_payment_info
Also consider htlcs that are still inflight when calculating
the amount/fee of a payment to prevent calculating an incorrect
payment value/fee when calling get_payment_info directly after
a payment succeeds (one htlc settled, but others could still be
inflight).
This assumes that once a payments htlc got settled all other inflight
htlcs will also get settled.
2026-03-06 12:09:07 +01:00
f321x 9b4d4d61bb plugin: nwc: add update timer to connection list 2026-03-06 12:09:05 +01:00
f321x 8ccdc3f7af plugin: nwc: consider routing fees for payment budget
Include the lightning routing fees into the payment budget accounting
to prevent untrusted nwc clients from exceeding the budget by crafting
a high fee route.
2026-03-06 12:09:03 +01:00
f321x 8dddb5d538 plugin: nwc: unify budget_allows_spend and add_to_budget
There is now only add_to_budget which will return None if the budget
doesn't allow for this spend. It will always add the spend to the
budget, even if the user has no budget so it can be used for display
purposes (and simpler code, only one path).
2026-03-06 12:08:58 +01:00
f321x 835ab39d77 plugin: nwc: bump version to 0.0.2
these changes deserve a new version
2026-03-03 18:04:54 +01:00
f321x ea1e2c8240 plugin: nwc: add 'state' field to responses
NIP-47 got extended to include an optional 'state' field in responses.
Implementing this acutally fixes an issue of Alby Go showing succeeded
payments as failed that appeared recently.
2026-03-03 18:04:52 +01:00
f321x 5222374046 plugin: nwc: improved budget accounting
Increase the payment budget before attempting the payment
and decrease again if the payment fails. This prevents a race
where multiple concurrent payments could pass the budget check
before the budget is incremented through any of the other payments.

A lock around the budget is not suitable either as then one long
stuck payment (hold invoice) would render the budget inaccessible for
all other payment attempts.
2026-03-03 18:04:51 +01:00
f321x 3956bff068 plugin: nwc: do budget accounting in msat
Keep track of the spent amount in msat instead of sat to prevent
issues due to rounding.
The budget is still specified in sat.
2026-03-03 18:04:47 +01:00
f321x 0dc08fdf24 plugin: nwc: handle encryption scheme signaling
NIP-47 now defines how client/server should communicate their supported
encryption schemes. For backwards compatibility its not strictly
neccessary to implement this but it seems cleaner to explicitly handle
it.
2026-03-03 11:27:09 +01:00
f321x 4c703ea278 plugin: nwc: remove multi_pay_invoice rpc
It got removed from the spec so we don't need to support it anymore.
https://github.com/nostr-protocol/nips/pull/2210
2026-03-03 11:22:07 +01:00
f321x 4556d59fc0 plugin: nwc: qt: fix thread safety bug
Call `NWCServer.event_handler_task.cancel()` on asyncio thread.

```
 File "/home/user/Documents/electrum/electrum/plugins/nwc/nwcserver.py", line 281, in restart_event_handler
   self.event_handler_task.cancel()
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
 File "/usr/lib64/python3.14/asyncio/base_events.py", line 829, in call_soon
   self._check_thread()
   ~~~~~~~~~~~~~~~~~~^^
 File "/usr/lib64/python3.14/asyncio/base_events.py", line 866, in _check_thread
   raise RuntimeError(
       "Non-thread-safe operation invoked on an event loop other "
       "than the current one")
RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one
```
2026-02-16 09:28:16 +01:00
ghost43 f8fc2b63e3 Merge pull request #10271 from f321x/fix_save_payment_info
lightning: fix self payments (e.g. rebalance)
2025-12-05 17:19:39 +00:00
SomberNight 75ac8bcee1 plugins: nwc: don't mutate aionostr Event
I want to change the Event class to be immutable.
2025-12-04 00:47:32 +00:00
f321x 923d48f9db lnworker: differentiate PaymentInfo by direction
Allows storing two different payment info of the same payment hash by
including the direction into the db key.
We create and store PaymentInfo for sending attempts and for requests (receiving),
if we try to pay ourself (e.g. through a channel rebalance) the checks
in `save_payment_info` would prevent this and throw an exception.
By storing the PaymentInfos of outgoing and incoming payments separately in
the db this collision is avoided and it makes it easier to reason about
which PaymentInfo belongs where.
2025-12-01 18:39:56 +01:00
f321x 286fc4b86e lnworker: enforce creation of PaymentInfo for b11
Enforce that the information used to create a bolt11 invoice using
`get_bolt11_invoice()` is similar to the related instance of PaymentInfo
by requiring a PaymentInfo as argument for `get_bolt11_invoice()`.
This way the invoice cannot differ from the created PaymentInfo.
This allows to use the information in PaymentInfo for validation of
incoming htlcs more reliably.

To cover all required information for the creation of a b11 invoice the
PaymentInfo class has to be extended with a expiry and
min_final_cltv_expiry. This requires a db upgrade.
2025-09-30 09:54:35 +02:00
SomberNight 81be0554a3 swaps: more robust parsing 2025-08-19 13:42:21 +00:00
Sander van Grieken 3c9c6a286c imports, whitespace, type hints, copyright headers 2025-06-12 14:32:00 +02:00
ghost43 448cbc7869 Merge pull request #9936 from f321x/nwc_incoming_event_filtering
plugin: nwc: improve filtering of expired requests
2025-06-10 18:32:13 +00:00
f321x 0f442f4c85 plugin: nwc: improve filtering of expired requests
improve the filtering of incoming requests by checking if they have
explicitly set an expiration tag. If so, they will only be ignored if
this timestamp is exceeded. Otherwise requests older than 30 secons will
get ignored and an error will get sent to the client so the client is
aware it's request arrived too late.
This is done to prevent handling requests the user may already expects
to have failed.
2025-06-10 19:29:19 +02:00
SomberNight 527d9e8215 plugins: nwc: clean-up imports
Try to follow PEP-8 import grouping, to make things readable.
I want to be able to quickly spot 3rd-party library imports! :P
2025-06-10 15:22:13 +00:00
SomberNight dd7a284fd9 plugins: nwc: fix constants.net import
"# don't import net directly, import the module instead (so that net is singleton)"

set_as_network does not work if net is not a singleton, it results in a split worldview.
2025-06-10 15:22:10 +00:00
f321x 3daed92be2 nwc: don't announce spending methods if limit is 0
don't return the spending methods pay_invoice and multi_pay_invoice in
the get_info request and the info event so connections can be used for
services that enforce receive only connections.
2025-06-03 14:13:32 +02:00
SomberNight 6c11c75d58 follow-up prev 2025-05-14 13:29:30 +00:00
SomberNight 44f3444795 lnworker: make "preimages" dict private
I want to hook into lnworker.save_preimage (not done yet).
Other modules should not put preimages into the dict directly.
2025-05-14 13:23:02 +00:00
ThomasV 0d1b6aa432 nwc plugin: improve dialog layout 2025-05-07 12:10:20 +02:00
f321x e80551192b plugins: structure plugin storage in wallet
store all plugin data by plugin name in a root dictionary `plugin_data`
inside the wallet db so that plugin data can get deleted again.
Prunes the data of plugins from the wallet db on wallet stop if the
plugin is not installed anymore.
2025-05-06 13:16:49 +02:00
ThomasV a92e65c561 plugins: add plugin icon to menu in init_menubar 2025-04-15 10:33:14 +02:00
ThomasV dcf632ed1e add icons for nwc and labels plugins 2025-04-15 10:23:05 +02:00
ThomasV 0831fc3b80 plugins: move wallet-related settings to the wallet menu
Plugins should use the init_menubar hook.
References are kept to the various menu objects.
2025-04-15 10:01:00 +02:00
ThomasV 8c028f7528 Add/remove plugins from GUI
- both internal and external plugins require GUI install
   (except internal HW plugins, which are 'auto-loaded' and hidden)
 - remove init_qt hook
 - in Qt, reload wallet windows if plugin enabled/disabled
 - add 'uninstall' button to PluginDialog
 - add 'add plugins' button to wizard hw screen
 - add icons to the plugin list
2025-04-15 08:35:10 +02:00
ThomasV c93b13f6d9 Make it possible to create zip plugins from internal plugins
specifically:
 - add 'name' field to manifest.json
 - make 'version' optional in contrib/make_plugin
 - fix import in jade plugin
2025-04-14 11:54:04 +02:00
ThomasV eff8b65355 Plugins: pass wallet to settings_dialog
Also, remove settings_widget method.
The widget should always be a button.

nwc: is_initialized -> initialized
2025-04-12 11:09:15 +02:00
ThomasV 3a18000f7a nwc plugin: settings_dialog is wallet agnostic.
instead, test wallet in start_plugin.
prevent plugin from using several wallets.
2025-04-11 20:16:59 +02:00
ThomasV 13024be4da nwc plugin: fix config key 2025-04-11 20:06:42 +02:00
f321x 253ab6849a implement NIP47 plugin 2025-04-10 10:22:29 +02:00