Update client package version and replace all references to 'Electrum' with 'Pallectrum' in the codebase. Also updates the description to reflect Palladium instead of Bitcoin.
Simplify the block explorers configuration by removing all entries except for the Palladium Explorer. This change focuses the application on a single, more relevant explorer service.
The changes introduce a new URI scheme 'palladium' alongside the existing 'bitcoin' scheme for BIP21 payment URIs. This allows the wallet to parse and handle palladium payment URIs in the same way as bitcoin URIs.
Update all references to 'Electrum' in user-facing messages to 'Pallectrum' to reflect the new branding. Also updates references to 'Bitcoin' to 'Palladium' where applicable and makes minor wording adjustments for consistency.
Update all instances of BTC currency references to PLM across multiple files including UI components, utility functions, and command descriptions to reflect the new currency denomination
Add SKIP_POW_DIFFICULTY_VALIDATION flag to AbstractNet for chains using custom difficulty algorithms like LWMA. Update blockchain.py to skip pow validation when flag is set, relying on server validation and checkpoints instead. Also update Palladium checkpoints.
Add initial configuration files for Palladium chain including servers, checkpoints, and fallback nodes.
Update constants to use Palladium as default network and rename PalladiumMainnet to Palladium for consistency.
Add comprehensive changelog documenting the initial fork from Electrum v4.6.2
and planned development roadmap for Pallectrum wallet. Includes network
parameters, address format support, and rebranding changes.
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...
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')
```