diff --git a/contrib/make_plugin b/contrib/make_plugin index 45083fe16..6c454e768 100755 --- a/contrib/make_plugin +++ b/contrib/make_plugin @@ -35,12 +35,18 @@ with zipfile.ZipFile(zip_path, 'w') as zip_object: print('added', dest_path) # read version -zip_file = zipimport.zipimporter(zip_path) -module = zip_file.load_module(plugin_name) -if not module.version: +try: + with open(os.path.join(source_dir, 'manifest.json'), 'r') as f: + manifest = json.load(f) + version = manifest.get('version') +except FileNotFoundError: + raise Exception(f"plugin doesn't contain manifest.json") + +if not version: raise Exception('version not set') -versioned_plugin_name = plugin_name + '-' + module.version + '.zip' + +versioned_plugin_name = plugin_name + '-' + version + '.zip' zip_path_with_version = os.path.join(dest_dir, versioned_plugin_name) # rename zip file os.rename(zip_path, zip_path_with_version) diff --git a/electrum/commands.py b/electrum/commands.py index 1a7d168f3..adc352f2a 100644 --- a/electrum/commands.py +++ b/electrum/commands.py @@ -1573,9 +1573,7 @@ def plugin_command(s, plugin_name): func.plugin_name = plugin_name name = plugin_name + '_' + func.__name__ if name in known_commands or hasattr(Commands, name): - # electrum plugins are always loaded before the plugin commands, - # so plugin commands cannot overwrite them - return + raise Exception(f"Command name {name} already exists. Plugin commands should not overwrite other commands.") assert asyncio.iscoroutinefunction(func), f"Plugin commands must be a coroutine: {name}" @command(s) @wraps(func) diff --git a/electrum/plugin.py b/electrum/plugin.py index 6585c3e00..8e675cbfd 100644 --- a/electrum/plugin.py +++ b/electrum/plugin.py @@ -23,6 +23,7 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +import json import os import pkgutil import importlib.util @@ -31,6 +32,7 @@ import threading import traceback import sys import aiohttp +import zipfile as zipfile_lib from typing import (NamedTuple, Any, Union, TYPE_CHECKING, Optional, Tuple, Dict, Iterable, List, Sequence, Callable, TypeVar, Mapping) @@ -58,6 +60,7 @@ _logger = get_logger(__name__) plugin_loaders = {} hook_names = set() hooks = {} +_root_permission_cache = {} class Plugins(DaemonThread): @@ -71,11 +74,11 @@ class Plugins(DaemonThread): self.cmd_only = cmd_only # type: bool self.internal_plugin_metadata = {} self.external_plugin_metadata = {} - self.loaded_command_modules = set() # type: set[str] if cmd_only: # only import the command modules of plugins Logger.__init__(self) self.find_plugins() + self.load_plugins() return DaemonThread.__init__(self) self.device_manager = DeviceMgr(config) @@ -101,46 +104,32 @@ class Plugins(DaemonThread): # we exclude the ones packaged as *code*, here: if loader.__class__.__qualname__ == "PyiFrozenImporter": continue - if self.cmd_only and self.config.get('enable_plugin_' + name) is not True: + module_path = os.path.join(pkg_path, name) + if external and not self._has_recursive_root_permissions(module_path): + self.logger.info(f"Not loading plugin {module_path}: directory has user write permissions") continue - base_name = 'electrum.plugins' if not external else 'electrum_external_plugins' - full_name = f'{base_name}.{name}' - if external: - module_path = os.path.join(pkg_path, name) - if not self._has_recursive_root_permissions(module_path): - self.logger.info(f"Not loading plugin {module_path}: directory has user write permissions") - continue - module_path = os.path.join(module_path, '__init__.py') - if not os.path.exists(module_path): - continue - spec = importlib.util.spec_from_file_location(full_name, module_path) - else: - spec = importlib.util.find_spec(full_name) - if spec is None: - if self.cmd_only: - continue # no commands module in this plugin - raise Exception(f"Error pre-loading {full_name}: no spec") - module = self.exec_module_from_spec(spec, full_name) - if self.cmd_only: - assert name not in self.loaded_command_modules, f"tried to load commands of {name} twice" - self.loaded_command_modules.add(name) + if self.cmd_only and not self.config.get('enable_plugin_' + name) is True: + continue + try: + with open(os.path.join(module_path, 'manifest.json'), 'r') as f: + d = json.load(f) + except FileNotFoundError: + self.logger.info(f"could not find manifest.json of plugin {name}, skipping...") continue - d = module.__dict__ if 'fullname' not in d: continue d['display_name'] = d['fullname'] - gui_good = self.gui_name in d.get('available_for', []) - if not gui_good: - continue - details = d.get('registers_wallet_type') - if details: - self.register_wallet_type(name, gui_good, details) - details = d.get('registers_keystore') - if details: - self.register_keystore(name, gui_good, details) - if d.get('requires_wallet_type'): - # trustedcoin will not be added to list - continue + d['path'] = module_path + if not self.cmd_only: + gui_good = self.gui_name in d.get('available_for', []) + if not gui_good: + continue + details = d.get('registers_wallet_type') + if details: + self.register_wallet_type(name, gui_good, details) + details = d.get('registers_keystore') + if details: + self.register_keystore(name, gui_good, details) if name in self.internal_plugin_metadata or name in self.external_plugin_metadata: _logger.info(f"Found the following plugin modules: {iter_modules=}") raise Exception(f"duplicate plugins? for {name=}") @@ -174,7 +163,10 @@ class Plugins(DaemonThread): for name, d in chain(self.internal_plugin_metadata.items(), self.external_plugin_metadata.items()): if not d.get('requires_wallet_type') and self.config.get('enable_plugin_' + name): try: - self.load_plugin_by_name(name) + if self.cmd_only: # only load init method to register commands + self.maybe_load_plugin_init_method(name) + else: + self.load_plugin_by_name(name) except BaseException as e: self.logger.exception(f"cannot initialize plugin {name}: {e}") @@ -184,12 +176,17 @@ class Plugins(DaemonThread): @profiler(min_threshold=0.5) def _has_recursive_root_permissions(self, path): """Check if a directory and all its subdirectories have root permissions""" + global _root_permission_cache + if _root_permission_cache.get(path) is not None: + return _root_permission_cache[path] + _root_permission_cache[path] = False for root, dirs, files in os.walk(path): if not self._has_root_permissions(root): return False for f in files: if not self._has_root_permissions(os.path.join(root, f)): return False + _root_permission_cache[path] = True return True def get_external_plugin_dir(self): @@ -237,23 +234,25 @@ class Plugins(DaemonThread): raise Exception(f"duplicate plugins for name={name}") if self.cmd_only and not self.config.get('enable_plugin_' + name): continue - module_path = f'electrum_external_plugins.{name}' if external else f'electrum.plugins.{name}' - spec = zipfile.find_spec(name) - module = self.exec_module_from_spec(spec, module_path) - if self.cmd_only: - assert name not in self.loaded_command_modules, f"tried to load commands of {name} twice" - self.loaded_command_modules.add(name) - continue - d = module.__dict__ - gui_good = self.gui_name in d.get('available_for', []) - if not gui_good: + try: + with zipfile_lib.ZipFile(path) as file: + manifest_path = os.path.join(name, 'manifest.json') + with file.open(manifest_path, 'r') as f: + d = json.load(f) + except Exception: + self.logger.info(f"could not load manifest.json from zip plugin {filename}", exc_info=True) continue d['filename'] = filename - if 'fullname' not in d: - continue - d['display_name'] = d['fullname'] - d['zip_hash_sha256'] = get_file_hash256(path) d['is_zip'] = True + d['path'] = path + if not self.cmd_only: + gui_good = self.gui_name in d.get('available_for', []) + if not gui_good: + continue + if 'fullname' not in d: + continue + d['display_name'] = d['fullname'] + d['zip_hash_sha256'] = get_file_hash256(path) if external: self.external_plugin_metadata[name] = d else: @@ -274,11 +273,35 @@ class Plugins(DaemonThread): else: raise Exception(f"could not find plugin {name!r}") - def load_plugin_by_name(self, name) -> 'BasePlugin': + def maybe_load_plugin_init_method(self, name: str) -> None: + """Loads the __init__.py module of the plugin if it is not already loaded.""" + is_external = name in self.external_plugin_metadata + base_name = (f'electrum_external_plugins.' if is_external else 'electrum.plugins.') + name + if base_name not in sys.modules: + metadata = self.get_metadata(name) + is_zip = metadata.get('is_zip', False) + # if the plugin was not enabled on startup the init module hasn't been loaded yet + if not is_zip: + if is_external: + path = os.path.join(metadata['path'], '__init__.py') + init_spec = importlib.util.spec_from_file_location(base_name, path) + else: + init_spec = importlib.util.find_spec(base_name) + else: + zipfile = zipimport.zipimporter(metadata['path']) + init_spec = zipfile.find_spec(name) + self.exec_module_from_spec(init_spec, base_name) + if name == "trustedcoin": + # removes trustedcoin after loading to not show it in the list of plugins + del self.internal_plugin_metadata[name] + + def load_plugin_by_name(self, name: str) -> 'BasePlugin': if name in self.plugins: return self.plugins[name] - is_zip = self.is_plugin_zip(name) + # if the plugin was not enabled on startup the init module hasn't been loaded yet + self.maybe_load_plugin_init_method(name) + is_external = name in self.external_plugin_metadata if not is_external: full_name = f'electrum.plugins.{name}.{self.gui_name}' @@ -289,11 +312,7 @@ class Plugins(DaemonThread): if spec is None: raise RuntimeError(f"{self.gui_name} implementation for {name} plugin not found") try: - if is_zip: - module = self.exec_module_from_spec(spec, full_name) - else: - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) + module = self.exec_module_from_spec(spec, full_name) plugin = module.Plugin(self, self.config, name) except Exception as e: raise Exception(f"Error loading {name} plugin: {repr(e)}") from e @@ -493,10 +512,9 @@ class BasePlugin(Logger): raise NotImplementedError() def read_file(self, filename: str) -> bytes: - import zipfile if self.parent.is_plugin_zip(self.name): plugin_filename = self.parent.zip_plugin_path(self.name) - with zipfile.ZipFile(plugin_filename) as myzip: + with zipfile_lib.ZipFile(plugin_filename) as myzip: with myzip.open(os.path.join(self.name, filename)) as myfile: return myfile.read() else: diff --git a/electrum/plugins/audio_modem/__init__.py b/electrum/plugins/audio_modem/__init__.py index 46c2d2091..e69de29bb 100644 --- a/electrum/plugins/audio_modem/__init__.py +++ b/electrum/plugins/audio_modem/__init__.py @@ -1,7 +0,0 @@ -from electrum.i18n import _ - -fullname = _('Audio MODEM') -description = _('Provides support for air-gapped transaction signing.') -requires = [('amodem', 'http://github.com/romanz/amodem/')] -available_for = ['qt'] - diff --git a/electrum/plugins/audio_modem/manifest.json b/electrum/plugins/audio_modem/manifest.json new file mode 100644 index 000000000..e3172861c --- /dev/null +++ b/electrum/plugins/audio_modem/manifest.json @@ -0,0 +1,6 @@ +{ + "fullname": "Audio MODEM", + "description": "Provides support for air-gapped transaction signing.", + "requires": [["amodem", "http://github.com/romanz/amodem/"]], + "available_for": ["qt"] +} \ No newline at end of file diff --git a/electrum/plugins/bitbox02/__init__.py b/electrum/plugins/bitbox02/__init__.py index 86812d564..e69de29bb 100644 --- a/electrum/plugins/bitbox02/__init__.py +++ b/electrum/plugins/bitbox02/__init__.py @@ -1,14 +0,0 @@ -from electrum.i18n import _ - -fullname = "BitBox02" -description = ( - "Provides support for the BitBox02 hardware wallet" -) -requires = [ - ( - "bitbox02", - "https://github.com/digitalbitbox/bitbox02-firmware/tree/master/py/bitbox02", - ) -] -registers_keystore = ("hardware", "bitbox02", _("BitBox02")) -available_for = ["qt"] diff --git a/electrum/plugins/bitbox02/manifest.json b/electrum/plugins/bitbox02/manifest.json new file mode 100644 index 000000000..ed4987043 --- /dev/null +++ b/electrum/plugins/bitbox02/manifest.json @@ -0,0 +1,7 @@ +{ + "fullname": "BitBox02", + "description": "Provides support for the BitBox02 hardware wallet", + "requires": [["bitbox02", "https://github.com/digitalbitbox/bitbox02-firmware/tree/master/py/bitbox02"]], + "registers_keystore": ["hardware", "bitbox02", "BitBox02"], + "available_for": ["qt"] +} \ No newline at end of file diff --git a/electrum/plugins/coldcard/__init__.py b/electrum/plugins/coldcard/__init__.py index 7cb033f42..8b1378917 100644 --- a/electrum/plugins/coldcard/__init__.py +++ b/electrum/plugins/coldcard/__init__.py @@ -1,7 +1 @@ -from electrum.i18n import _ -fullname = 'Coldcard Wallet' -description = 'Provides support for the Coldcard hardware wallet from Coinkite' -requires = [('ckcc-protocol', 'github.com/Coldcard/ckcc-protocol')] -registers_keystore = ('hardware', 'coldcard', _("Coldcard Wallet")) -available_for = ['qt', 'cmdline'] diff --git a/electrum/plugins/coldcard/manifest.json b/electrum/plugins/coldcard/manifest.json new file mode 100644 index 000000000..52fdfd5ee --- /dev/null +++ b/electrum/plugins/coldcard/manifest.json @@ -0,0 +1,7 @@ +{ + "fullname": "Coldcard Wallet", + "description": "Provides support for the Coldcard hardware wallet from Coinkite", + "requires": [["ckcc-protocol", "github.com/Coldcard/ckcc-protocol"]], + "registers_keystore": ["hardware", "coldcard", "Coldcard Wallet"], + "available_for": ["qt", "cmdline"] +} \ No newline at end of file diff --git a/electrum/plugins/digitalbitbox/__init__.py b/electrum/plugins/digitalbitbox/__init__.py index 5653d6161..e69de29bb 100644 --- a/electrum/plugins/digitalbitbox/__init__.py +++ b/electrum/plugins/digitalbitbox/__init__.py @@ -1,6 +0,0 @@ -from electrum.i18n import _ - -fullname = 'Digital Bitbox' -description = _('Provides support for Digital Bitbox hardware wallet') -registers_keystore = ('hardware', 'digitalbitbox', _("Digital Bitbox wallet")) -available_for = ['qt', 'cmdline'] diff --git a/electrum/plugins/digitalbitbox/manifest.json b/electrum/plugins/digitalbitbox/manifest.json new file mode 100644 index 000000000..dc47bb2a9 --- /dev/null +++ b/electrum/plugins/digitalbitbox/manifest.json @@ -0,0 +1,6 @@ +{ + "fullname": "Digital Bitbox", + "description": "Provides support for Digital Bitbox hardware wallet", + "registers_keystore": ["hardware", "digitalbitbox", "Digital Bitbox wallet"], + "available_for": ["qt", "cmdline"] +} diff --git a/electrum/plugins/jade/__init__.py b/electrum/plugins/jade/__init__.py index a09bcd2e1..e69de29bb 100644 --- a/electrum/plugins/jade/__init__.py +++ b/electrum/plugins/jade/__init__.py @@ -1,7 +0,0 @@ -from electrum.i18n import _ - -fullname = 'Blockstream Jade Wallet' -description = 'Provides support for the Blockstream Jade hardware wallet' -#requires = [('', 'github.com/')] -registers_keystore = ('hardware', 'jade', _("Jade wallet")) -available_for = ['qt', 'cmdline'] diff --git a/electrum/plugins/jade/manifest.json b/electrum/plugins/jade/manifest.json new file mode 100644 index 000000000..83de7b0ad --- /dev/null +++ b/electrum/plugins/jade/manifest.json @@ -0,0 +1,6 @@ +{ + "fullname": "Blockstream Jade Wallet", + "description": "Provides support for the Blockstream Jade hardware wallet", + "registers_keystore": ["hardware", "jade", "Jade wallet"], + "available_for": ["qt", "cmdline"] +} diff --git a/electrum/plugins/keepkey/__init__.py b/electrum/plugins/keepkey/__init__.py index 0b54bc4a0..e69de29bb 100644 --- a/electrum/plugins/keepkey/__init__.py +++ b/electrum/plugins/keepkey/__init__.py @@ -1,7 +0,0 @@ -from electrum.i18n import _ - -fullname = 'KeepKey' -description = _('Provides support for KeepKey hardware wallet') -requires = [('keepkeylib','github.com/keepkey/python-keepkey')] -registers_keystore = ('hardware', 'keepkey', _("KeepKey wallet")) -available_for = ['qt', 'cmdline'] diff --git a/electrum/plugins/keepkey/manifest.json b/electrum/plugins/keepkey/manifest.json new file mode 100644 index 000000000..6679bb509 --- /dev/null +++ b/electrum/plugins/keepkey/manifest.json @@ -0,0 +1,7 @@ +{ + "fullname": "KeepKey", + "description": "Provides support for KeepKey hardware wallet", + "requires": [["keepkeylib", "github.com/keepkey/python-keepkey"]], + "registers_keystore": ["hardware", "keepkey", "KeepKey wallet"], + "available_for": ["qt", "cmdline"] +} diff --git a/electrum/plugins/labels/__init__.py b/electrum/plugins/labels/__init__.py index da5e56ac8..09cca4f2c 100644 --- a/electrum/plugins/labels/__init__.py +++ b/electrum/plugins/labels/__init__.py @@ -1,4 +1,3 @@ -from electrum.i18n import _ from electrum.commands import plugin_command from typing import TYPE_CHECKING @@ -6,14 +5,6 @@ if TYPE_CHECKING: from .labels import LabelsPlugin from electrum.commands import Commands - -fullname = _('LabelSync') -description = ' '.join([ - _("Save your wallet labels on a remote server, and synchronize them across multiple devices where you use Electrum."), - _("Labels, transactions IDs and addresses are encrypted before they are sent to the remote server.") -]) -available_for = ['qt', 'qml', 'cmdline'] - plugin_name = "labels" @plugin_command('w', plugin_name) diff --git a/electrum/plugins/labels/manifest.json b/electrum/plugins/labels/manifest.json new file mode 100644 index 000000000..53710dc52 --- /dev/null +++ b/electrum/plugins/labels/manifest.json @@ -0,0 +1,5 @@ +{ + "fullname": "LabelSync", + "description": "Save your wallet labels on a remote server, and synchronize them across multiple devices where you use Electrum. Labels, transactions IDs and addresses are encrypted before they are sent to the remote server.", + "available_for": ["qt", "qml", "cmdline"] +} \ No newline at end of file diff --git a/electrum/plugins/ledger/__init__.py b/electrum/plugins/ledger/__init__.py index 712a6b434..e69de29bb 100644 --- a/electrum/plugins/ledger/__init__.py +++ b/electrum/plugins/ledger/__init__.py @@ -1,7 +0,0 @@ -from electrum.i18n import _ - -fullname = 'Ledger Wallet' -description = 'Provides support for Ledger hardware wallet' -requires = [('ledger_bitcoin', 'github.com/LedgerHQ/app-bitcoin-new')] -registers_keystore = ('hardware', 'ledger', _("Ledger wallet")) -available_for = ['qt', 'cmdline'] diff --git a/electrum/plugins/ledger/manifest.json b/electrum/plugins/ledger/manifest.json new file mode 100644 index 000000000..4a091a39c --- /dev/null +++ b/electrum/plugins/ledger/manifest.json @@ -0,0 +1,7 @@ +{ + "fullname": "Ledger Wallet", + "description": "Provides support for Ledger hardware wallet", + "requires": [["ledger_bitcoin", "github.com/LedgerHQ/app-bitcoin-new"]], + "registers_keystore": ["hardware", "ledger", "Ledger wallet"], + "available_for": ["qt", "cmdline"] +} diff --git a/electrum/plugins/payserver/__init__.py b/electrum/plugins/payserver/__init__.py index 52e3fb61c..e69de29bb 100644 --- a/electrum/plugins/payserver/__init__.py +++ b/electrum/plugins/payserver/__init__.py @@ -1,5 +0,0 @@ -from electrum.i18n import _ - -fullname = _('PayServer') -description = 'run a HTTP server for receiving payments' -available_for = ['cmdline'] diff --git a/electrum/plugins/payserver/manifest.json b/electrum/plugins/payserver/manifest.json new file mode 100644 index 000000000..7d3b55af7 --- /dev/null +++ b/electrum/plugins/payserver/manifest.json @@ -0,0 +1,5 @@ +{ + "fullname": "PayServer", + "description": "run a HTTP server for receiving payments", + "available_for": ["cmdline"] +} diff --git a/electrum/plugins/psbt_nostr/__init__.py b/electrum/plugins/psbt_nostr/__init__.py index d110c13e6..e69de29bb 100644 --- a/electrum/plugins/psbt_nostr/__init__.py +++ b/electrum/plugins/psbt_nostr/__init__.py @@ -1,11 +0,0 @@ -from electrum.i18n import _ -fullname = _('PSBT over Nostr') -description = ' '.join([ - _("This plugin facilitates the use of multi-signatures wallets."), - _("It sends and receives partially signed transactions from/to your cosigner wallet."), - _("PSBTs are sent and retrieved from Nostr relays.") -]) -author = 'The Electrum Developers' -#requires_wallet_type = ['2of2', '2of3'] -available_for = ['qt'] -version = '0.0.1' diff --git a/electrum/plugins/psbt_nostr/manifest.json b/electrum/plugins/psbt_nostr/manifest.json new file mode 100644 index 000000000..e49ba3959 --- /dev/null +++ b/electrum/plugins/psbt_nostr/manifest.json @@ -0,0 +1,7 @@ +{ + "fullname": "PSBT over Nostr", + "description": "This plugin facilitates the use of multi-signatures wallets. It sends and receives partially signed transactions from/to your cosigner wallet. PSBTs are sent and retrieved from Nostr relays.", + "author": "The Electrum Developers", + "available_for": ["qt"], + "version": "0.0.1" +} diff --git a/electrum/plugins/revealer/__init__.py b/electrum/plugins/revealer/__init__.py index d5df9bb15..139597f9c 100644 --- a/electrum/plugins/revealer/__init__.py +++ b/electrum/plugins/revealer/__init__.py @@ -1,9 +1,2 @@ -from electrum.i18n import _ - -fullname = _('Revealer Backup Utility') -description = ''.join(["
", - ""+_("Do you have something to hide ?")+"", '
', '
', - _("This plug-in allows you to create a visually encrypted backup of your wallet seeds, or of custom alphanumeric secrets."), '
']) -available_for = ['qt'] diff --git a/electrum/plugins/revealer/manifest.json b/electrum/plugins/revealer/manifest.json new file mode 100644 index 000000000..f923b6dd5 --- /dev/null +++ b/electrum/plugins/revealer/manifest.json @@ -0,0 +1,5 @@ +{ + "fullname": "Revealer Backup Utility", + "description": "
Do you have something to hide ?

This plug-in allows you to create a visually encrypted backup of your wallet seeds, or of custom alphanumeric secrets.
", + "available_for": ["qt"] +} diff --git a/electrum/plugins/safe_t/__init__.py b/electrum/plugins/safe_t/__init__.py index 9bfb2d9bb..8b1378917 100644 --- a/electrum/plugins/safe_t/__init__.py +++ b/electrum/plugins/safe_t/__init__.py @@ -1,8 +1 @@ -from electrum.i18n import _ - -fullname = 'Safe-T mini Wallet' -description = _('Provides support for Safe-T mini hardware wallet') -requires = [('safetlib','github.com/archos-safe-t/python-safet')] -registers_keystore = ('hardware', 'safe_t', _("Safe-T mini wallet")) -available_for = ['qt', 'cmdline'] diff --git a/electrum/plugins/safe_t/manifest.json b/electrum/plugins/safe_t/manifest.json new file mode 100644 index 000000000..40dd51385 --- /dev/null +++ b/electrum/plugins/safe_t/manifest.json @@ -0,0 +1,7 @@ +{ + "fullname": "Safe-T mini Wallet", + "description": "Provides support for Safe-T mini hardware wallet", + "requires": [["safetlib", "github.com/archos-safe-t/python-safet"]], + "registers_keystore": ["hardware", "safe_t", "Safe-T mini wallet"], + "available_for": ["qt", "cmdline"] +} \ No newline at end of file diff --git a/electrum/plugins/swapserver/__init__.py b/electrum/plugins/swapserver/__init__.py index ff236f6ef..e69de29bb 100644 --- a/electrum/plugins/swapserver/__init__.py +++ b/electrum/plugins/swapserver/__init__.py @@ -1,15 +0,0 @@ -from electrum.i18n import _ - -fullname = _('SwapServer') -description = """ -Submarine swap server for an Electrum daemon. - -Example setup: - - electrum -o setconfig enable_plugin_swapserver True - electrum -o setconfig swapserver_port 5455 - electrum daemon -v - -""" - -available_for = ['cmdline'] diff --git a/electrum/plugins/swapserver/manifest.json b/electrum/plugins/swapserver/manifest.json new file mode 100644 index 000000000..797fcbb64 --- /dev/null +++ b/electrum/plugins/swapserver/manifest.json @@ -0,0 +1,5 @@ +{ + "fullname": "SwapServer", + "description": "Submarine swap server for an Electrum daemon.\n\nExample setup:\n\n electrum -o setconfig enable_plugin_swapserver True\n electrum -o setconfig swapserver_port 5455\n electrum daemon -v\n\n", + "available_for": ["cmdline"] +} diff --git a/electrum/plugins/trezor/__init__.py b/electrum/plugins/trezor/__init__.py index 6aff1e0f4..8b1378917 100644 --- a/electrum/plugins/trezor/__init__.py +++ b/electrum/plugins/trezor/__init__.py @@ -1,8 +1 @@ -from electrum.i18n import _ - -fullname = 'Trezor Wallet' -description = _('Provides support for Trezor hardware wallet') -requires = [('trezorlib','pypi.org/project/trezor/')] -registers_keystore = ('hardware', 'trezor', _("Trezor wallet")) -available_for = ['qt', 'cmdline'] diff --git a/electrum/plugins/trezor/manifest.json b/electrum/plugins/trezor/manifest.json new file mode 100644 index 000000000..0abd780c1 --- /dev/null +++ b/electrum/plugins/trezor/manifest.json @@ -0,0 +1,7 @@ +{ + "fullname": "Trezor Wallet", + "description": "Provides support for Trezor hardware wallet", + "requires": [["trezorlib","pypi.org/project/trezor/"]], + "registers_keystore": ["hardware", "trezor", "Trezor wallet"], + "available_for": ["qt", "cmdline"] +} diff --git a/electrum/plugins/trustedcoin/__init__.py b/electrum/plugins/trustedcoin/__init__.py index ec0b4a87c..e69de29bb 100644 --- a/electrum/plugins/trustedcoin/__init__.py +++ b/electrum/plugins/trustedcoin/__init__.py @@ -1,11 +0,0 @@ -from electrum.i18n import _ - -fullname = _('Two Factor Authentication') -description = ''.join([ - _("This plugin adds two-factor authentication to your wallet."), '
', - _("For more information, visit"), - " https://api.trustedcoin.com/#/electrum-help" -]) -requires_wallet_type = ['2fa'] -registers_wallet_type = '2fa' -available_for = ['qt', 'cmdline', 'qml'] diff --git a/electrum/plugins/trustedcoin/manifest.json b/electrum/plugins/trustedcoin/manifest.json new file mode 100644 index 000000000..f9db5645b --- /dev/null +++ b/electrum/plugins/trustedcoin/manifest.json @@ -0,0 +1,7 @@ +{ + "fullname": "Two Factor Authentication", + "description": "This plugin adds two-factor authentication to your wallet.
For more information, visit https://api.trustedcoin.com/#/electrum-help", + "requires_wallet_type": ["2fa"], + "registers_wallet_type": "2fa", + "available_for": ["qt", "cmdline", "qml"] +} diff --git a/electrum/plugins/watchtower/__init__.py b/electrum/plugins/watchtower/__init__.py index 2619271f4..e69de29bb 100644 --- a/electrum/plugins/watchtower/__init__.py +++ b/electrum/plugins/watchtower/__init__.py @@ -1,23 +0,0 @@ -from electrum.i18n import _ - -fullname = _('Watchtower') -description = """ -A watchtower is a daemon that watches your channels and prevents the other party from stealing funds by broadcasting an old state. - -Example: - -daemon setup: - - electrum -o setconfig enable_plugin_watchtower True - electrum -o setconfig watchtower_user wtuser - electrum -o setconfig watchtower_password wtpassword - electrum -o setconfig watchtower_port 12345 - electrum daemon -v - -client setup: - - electrum -o setconfig watchtower_url http://wtuser:wtpassword@127.0.0.1:12345 - -""" - -available_for = ['cmdline'] diff --git a/electrum/plugins/watchtower/manifest.json b/electrum/plugins/watchtower/manifest.json new file mode 100644 index 000000000..459801856 --- /dev/null +++ b/electrum/plugins/watchtower/manifest.json @@ -0,0 +1,5 @@ +{ + "fullname": "Watchtower", + "description": "A watchtower is a daemon that watches your channels and prevents the other party from stealing funds by broadcasting an old state.\n\nExample:\n\ndaemon setup:\n\n electrum -o setconfig enable_plugin_watchtower True\n electrum -o setconfig watchtower_user wtuser\n electrum -o setconfig watchtower_password wtpassword\n electrum -o setconfig watchtower_port 12345\n electrum daemon -v\n\nclient setup:\n\n electrum -o setconfig watchtower_url http://wtuser:wtpassword@127.0.0.1:12345\n\n", + "available_for": ["cmdline"] +}