Implement logic to claim a reverse swap funding output to any given
address. This allows to do onchain payments to external recipients
through a submarine swap.
Feerate is passed to `Commands._get_fee_policy()` as str which then
tried to multiply the string by 1000. Now it first casts the string to
`Decimal` and multiplies the decimal.
Fixes https://github.com/spesmilo/electrum/issues/10315
This assert is needed because I don't want to reason about
what could happen without it.
We currently use fixed 400 bytes trampoline onion sizes, which would
implicitly prevent this. However the current bolts PR actually specifies
variable size trampoline onions.
Using `@functools.lru_cache` on an instance method behaves in interesting ways.
The cache kept a ref around for `self`, so in effect we were never GC-ing keystore objects. Effectively there was a single global cache for derive_pubkey, with keys `(keystore, for_change, n)`.
This PR now changes the caching to be per-keystore:
each ks has a cache, keyed `(for_change, n)`.
GC-ing individual keystores should now be possible, which should result in cleaning up just their own cache.
This also enables the corresponding previously silence flake8-bugbear check for `@functools.lru_cache`. (note that the check can selectively be disabled by adding a comment on the relevant line: `# noqa: B019`)
I needed such a tx to test something in electrumx and wanted to copy-paste one from the electrum unit tests. Weird that we were lacking such a test case, I was fairly certain there was one already...
Currently on master the qml fee histogram colours are calculated for feerates clamped to [1, 600] sat/vbyte. I want to extend it to now cover [0, 600] sat/vbyte.
I would like to extend it in a way that does not change the existing colour meanings/mapping, so not just e.g. doing an offset.
follow-up bd6dfc53a2
Instead of storing its own path, each StoredDict element stores
its own key and a pointer to its parent. If a dict is removed
from the db, its parent pointer is set to None. This makes
self.path return None for all branches that have been pruned.
This passes tests/tests_json_db.py and fixes issue #10000
StoredDict to json_db.
convert_key, convert_value are used to convert json objects
to python classes, do not call them in StoredDict.__setitem__
This makes StoredDict agnostic about the type of database we use.
This changes the "Pay to" label to "Pay to many" if the user enables the
"Pay to many" option and aligns it at the top of the payto_e instead of
moving ot to the center when the payto_e expands.
The toolbar button is very small and some users probably don't even
notice it. As we have lots of space in the toolbar anyways i think it
makes sense to add some text to it to make it more visible and easier to
click. Maybe this is also useful for screen readers.
Launch `WatchtowerPlugin.watchtower.start_watching()` through
asyncio.run_coroutine_threadsafe instead of ensure_future to prevent the
following exception from happening when running python with
`PYTHONASYNCIODEBUG=1`.
```
20251103T165007.087746Z | ERROR | plugin.Plugins | cannot initialize plugin watchtower: Error loading watchtower plugin: RuntimeError('Non-thread-safe operation invoked on an event loop other than the current one')
Traceback (most recent call last):
File "/home/user/code/electrum-fork/electrum/plugin.py", line 629, in load_plugin_by_name
plugin = module.Plugin(self, self.config, name)
File "/home/user/code/electrum-fork/electrum/plugins/watchtower/watchtower.py", line 59, in __init__
asyncio.ensure_future(self.watchtower.start_watching())
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.14/asyncio/tasks.py", line 732, in ensure_future
return loop.create_task(coro_or_future)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.14/asyncio/base_events.py", line 468, in create_task
return self._task_factory(self, coro, **kwargs)
~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/code/electrum-fork/electrum/util.py", line 1773, in factory
task = asyncio.Task(coro, loop=loop_, **kwargs)
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
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/user/code/electrum-fork/electrum/plugin.py", line 184, in load_plugins
self.load_plugin_by_name(name)
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/home/user/code/electrum-fork/electrum/plugin.py", line 631, in load_plugin_by_name
raise Exception(f"Error loading {name} plugin: {repr(e)}") from e
Exception: Error loading watchtower plugin: RuntimeError('Non-thread-safe operation invoked on an event loop other than the current one')
```