From d36b753cfededc5c124c4e0c43e60250518e9086 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 25 Nov 2025 11:38:10 +0100 Subject: [PATCH] remove plugin payserver (moved to spesmilo/electrum-payserver) --- .gitmodules | 3 - electrum/plugins/payserver/__init__.py | 5 - electrum/plugins/payserver/cmdline.py | 31 ---- electrum/plugins/payserver/manifest.json | 6 - electrum/plugins/payserver/payserver.py | 187 ----------------------- electrum/plugins/payserver/www | 1 - 6 files changed, 233 deletions(-) delete mode 100644 electrum/plugins/payserver/__init__.py delete mode 100644 electrum/plugins/payserver/cmdline.py delete mode 100644 electrum/plugins/payserver/manifest.json delete mode 100644 electrum/plugins/payserver/payserver.py delete mode 160000 electrum/plugins/payserver/www diff --git a/.gitmodules b/.gitmodules index 5d001cd4a..7bc6f6627 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "electrum/locale"] path = electrum/locale url = https://github.com/spesmilo/electrum-locale -[submodule "electrum/www"] - path = electrum/plugins/payserver/www - url = https://github.com/spesmilo/electrum-http.git [submodule "electrum/plugins/keepkey/keepkeylib"] path = electrum/plugins/keepkey/keepkeylib url = https://github.com/spesmilo/electrum-keepkeylib.git diff --git a/electrum/plugins/payserver/__init__.py b/electrum/plugins/payserver/__init__.py deleted file mode 100644 index 019f4e579..000000000 --- a/electrum/plugins/payserver/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from electrum.simple_config import ConfigVar, SimpleConfig - -SimpleConfig.PAYSERVER_PORT = ConfigVar('plugins.payserver.port', default=8080, type_=int, plugin=__name__) -SimpleConfig.PAYSERVER_ROOT = ConfigVar('plugins.payserver.root', default='/r', type_=str, plugin=__name__) -SimpleConfig.PAYSERVER_ALLOW_CREATE_INVOICE = ConfigVar('plugins.payserver.allow_create_invoice', default=False, type_=bool, plugin=__name__) diff --git a/electrum/plugins/payserver/cmdline.py b/electrum/plugins/payserver/cmdline.py deleted file mode 100644 index c2d8945b2..000000000 --- a/electrum/plugins/payserver/cmdline.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python -# -# Electrum - Lightweight Bitcoin Client -# Copyright (C) 2022 The Electrum Developers -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - - -from .payserver import PayServerPlugin - -class Plugin(PayServerPlugin): - pass - diff --git a/electrum/plugins/payserver/manifest.json b/electrum/plugins/payserver/manifest.json deleted file mode 100644 index fd47bb92c..000000000 --- a/electrum/plugins/payserver/manifest.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "payserver", - "fullname": "PayServer", - "description": "run a HTTP server for receiving payments", - "available_for": ["cmdline"] -} diff --git a/electrum/plugins/payserver/payserver.py b/electrum/plugins/payserver/payserver.py deleted file mode 100644 index 00b1f6706..000000000 --- a/electrum/plugins/payserver/payserver.py +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python -# -# Electrum - Lightweight Bitcoin Client -# Copyright (C) 2022 The Electrum Developers -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import os -import asyncio -from collections import defaultdict -from typing import TYPE_CHECKING, Optional - -from aiohttp import web - -from electrum import util -from electrum.util import log_exceptions, ignore_exceptions -from electrum.plugin import BasePlugin, hook -from electrum.logging import Logger -from electrum.util import EventListener, event_listener -from electrum.invoices import PR_PAID, PR_EXPIRED - -if TYPE_CHECKING: - from electrum.simple_config import SimpleConfig - from electrum.daemon import Daemon - from electrum.wallet import Abstract_Wallet - - -class PayServerPlugin(BasePlugin): - - def __init__(self, parent, config: 'SimpleConfig', name): - BasePlugin.__init__(self, parent, config, name) - self.config = config - self.server = None - - def view_url(self, key) -> Optional[str]: - if not self.server: - return None - return self.server.base_url + self.server.root + '/pay?id=' + key - - @hook - def daemon_wallet_loaded(self, daemon: 'Daemon', wallet: 'Abstract_Wallet'): - # we use the first wallet loaded - if self.server is not None: - return - if self.config.NETWORK_OFFLINE: - return - self.server = PayServer(self.config, wallet) - asyncio.run_coroutine_threadsafe(daemon.taskgroup.spawn(self.server.run()), daemon.asyncio_loop) - - @hook - def wallet_export_request(self, d, key): - if view_url := self.view_url(key): - d['view_url'] = view_url - -class PayServer(Logger, EventListener): - - WWW_DIR = os.path.join(os.path.dirname(__file__), 'www') - - def __init__(self, config: 'SimpleConfig', wallet: 'Abstract_Wallet'): - Logger.__init__(self) - assert self.has_www_dir(), self.WWW_DIR - self.config = config - self.wallet = wallet - self.port = self.config.PAYSERVER_PORT - self.pending = defaultdict(asyncio.Event) - self.register_callbacks() - - @classmethod - def has_www_dir(cls) -> bool: - index_html = os.path.join(cls.WWW_DIR, "index.html") - return os.path.exists(index_html) - - @property - def base_url(self): - return 'http://localhost:%d'%self.port - - @property - def root(self): - return self.config.PAYSERVER_ROOT - - @event_listener - async def on_event_request_status(self, wallet, key, status): - if status == PR_PAID: - self.pending[key].set() - - @ignore_exceptions - @log_exceptions - async def run(self): - app = web.Application() - app.add_routes([web.get('/api/get_invoice', self.get_request)]) - app.add_routes([web.get('/api/get_status', self.get_status)]) - app.add_routes([web.get('/bip70/{key}.bip70', self.get_bip70_request)]) - # 'follow_symlinks=True' allows symlinks to traverse out the parent directory. - # This was requested by distro packagers for vendored libs, and we restrict it to only those - # to minimise attack surface. note: "add_routes" call order matters (inner path goes first) - app.add_routes([web.static(f"{self.root}/vendor", os.path.join(self.WWW_DIR, 'vendor'), follow_symlinks=True)]) - app.add_routes([web.static(self.root, self.WWW_DIR)]) - if self.config.PAYSERVER_ALLOW_CREATE_INVOICE: - app.add_routes([web.post('/api/create_invoice', self.create_request)]) - runner = web.AppRunner(app) - await runner.setup() - site = web.TCPSite(runner, host='localhost', port=self.port) - await site.start() - self.logger.info(f"running and listening on port {self.port}") - - async def create_request(self, request): - params = await request.post() - wallet = self.wallet - if 'amount_sat' not in params or not params['amount_sat'].isdigit(): - raise web.HTTPBadRequest(reason='No amount provided') - if 'onchain' in params: - address = wallet.get_unused_address() - if not address: - raise web.HTTPBadRequest(reason='wallet does not have any unused address') - else: - if not wallet.has_lightning(): - raise web.HTTPBadRequest(reason='wallet does not support lightning') - address = None - amount = int(params['amount_sat']) - message = params['message'] or "donation" - key = wallet.create_request( - amount_sat=amount, - message=message, - exp_delay=3600, - address=address) - raise web.HTTPFound(self.root + '/pay?id=' + key) - - async def get_request(self, r): - key = r.query_string - request = self.wallet.get_formatted_request(key) - return web.json_response(request) - - async def get_bip70_request(self, r): - from electrum.paymentrequest import make_request - key = r.match_info['key'] - request = self.wallet.get_request(key) - if not request: - return web.HTTPNotFound() - pr = make_request(self.config, request) - return web.Response(body=pr.SerializeToString(), content_type='application/bitcoin-paymentrequest') - - async def get_status(self, request): - ws = web.WebSocketResponse() - await ws.prepare(request) - key = request.query_string - info = self.wallet.get_formatted_request(key) - if not info: - await ws.send_str('unknown invoice') - await ws.close() - return ws - if info.get('status') == PR_PAID: - await ws.send_str(f'paid') - await ws.close() - return ws - if info.get('status') == PR_EXPIRED: - await ws.send_str(f'expired') - await ws.close() - return ws - while True: - try: - await util.wait_for2(self.pending[key].wait(), 1) - break - except asyncio.TimeoutError: - # send data on the websocket, to keep it alive - await ws.send_str('waiting') - await ws.send_str('paid') - await ws.close() - return ws - diff --git a/electrum/plugins/payserver/www b/electrum/plugins/payserver/www deleted file mode 160000 index bcb6d9ecf..000000000 --- a/electrum/plugins/payserver/www +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bcb6d9ecf75b6785451402068651cfa785b709fa