SatSale

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 52b9eb7e0afa250fff5353b41200c95a29b8bdc8
parent 3b5ef40b112909d4b98241f961c4f16eaf0f7f83
Author: nickfarrow <nick@nickfarrow.com>
Date:   Mon,  7 Mar 2022 23:54:15 +1100

Modular payment methods with revamped config
* Custom choice of payment_methods with lightning/onchain dropdown
* toml table configuration for payment methods

* update docs

* fix clightning ssh tunnel leftover file

Diffstat:
MREADME.md | 10++++++----
Mconfig.py | 58+++++++++++++++++++++++++++++++++++++++++++---------------
Mconfig.toml | 80+++++++++++++++++++++++++++++++++++--------------------------------------------
Mdocs/lightning.md | 19++++++++++---------
Mgateways/lightning_address.py | 24+++++++++++-------------
Mgateways/ssh_tunnel.py | 29+++++++++++++++--------------
Mnode/bitcoind.py | 68+++++++++++++++++++++++++++++++++-----------------------------------
Mnode/clightning.py | 5+++--
Mnode/lnd.py | 19++++++++++---------
Msatsale.py | 51++++++++++++++++++++++++++-------------------------
Mtemplates/index.html | 25+++++++++++--------------
11 files changed, 203 insertions(+), 185 deletions(-)

diff --git a/README.md b/README.md @@ -60,11 +60,13 @@ pip3 install -r requirements.txt ``` ### Connect to your Bitcoin Node Edit the `config.toml` configuration and point to your Bitcoin node: -```python +```toml +[bitcoind] host = "127.0.0.1" +username = "bitcoinrpc" +password = "rpcpassword" rpcport = "8332" -username = "RPCUSERNAME" -password = "RPCPASSWORD" +wallet = "" ``` (You can find these in `~/.bitcoin/bitcoin.conf`). When connecting to a remote node, also edit either the SSH `tunnel_host` to a node like `"pi@IP"`, ensuring you have SSH keys in `~/.ssh/authorized_keys` and `ufw allow 8332` the appropriate ports to connect to your node. Or alternatively, see [tor hidden service](/docs/tor.md). @@ -100,7 +102,7 @@ Changing `YOUR_SERVER_IP` to the IP address of the machine you're running SatSal Point a domain to your VPS. You can run SatSale or use NGINX/apache to point to the service. See [HTTPS instructions](docs/HTTPS.md). Embedded iframes are easy if your site only uses HTTP. But if your site uses HTTPS, then you can see your donation button at `http://YOUR_SERVER_IP:8000/` but will not be able to in an embedded iframe. See [HTTPS instructions](docs/HTTPS.md). ### Lightning Address -Once you have an HTTPS domain pointed at SatSale, in the configuration you can specify a lightning address: +Once you have an HTTPS domain pointed at SatSale, in the configuration under a lightning node you can specify a lightning address: ``` # Lightning Address e.g. name@you.satsale.domain (think this requires https url) lightning_address = name@ur.domain.com diff --git a/config.py b/config.py @@ -14,27 +14,53 @@ with open(conf_path, "r") as config_file: config = toml.load(config_file) def get_opt(name, default): - if name in config: - return config[name] + if name in config['satsale']: + return config['satsale'][name] else: return default +def check_set_node_conf(name, default, node_conf): + if name not in node_conf: + if default is not None and default != "": + print("using default {}: {}".format(name, default)) + node_conf[name] = default + return + + +payment_methods = [] +for method_name in config['payment_methods']: + method_config = config[method_name] + if method_name == "bitcoind": + method_config['name'] = "bitcoind" + check_set_node_conf("rpcport", "8332", method_config) + check_set_node_conf("username", "bitcoinrpc", method_config) + check_set_node_conf("password", "rpcpassword", method_config) + check_set_node_conf("rpc_cookie_file", "", method_config) + check_set_node_conf("wallet", "", method_config) + check_set_node_conf("tor_bitcoinrpc_host", None, method_config) + + elif method_name == "lnd": + method_config['name'] = "lnd" + check_set_node_conf("lnd_dir", "~/.lnd/", method_config) + check_set_node_conf("lnd_rpcport", "10009", method_config) + check_set_node_conf("lnd_macaroon", "invoice.macaroon", method_config) + check_set_node_conf("lightning_address", None, method_config) + check_set_node_conf("lightning_address_comment", None, method_config) + + elif method_name == "clightning": + method_config['name'] = "clightning" + check_set_node_conf("clightning_rpc_file", None, method_config) + + else: + Exception("Unknown payment method: {}".format(method_name)) + + payment_methods.append(method_config) + host = get_opt("host", "127.0.0.1") -rpcport = get_opt("rpcport", "8332") -username = get_opt("username", "bitcoinrpc") -password = get_opt("password", "rpcpassword") -rpc_cookie_file = get_opt("rpc_cookie_file", "") -wallet = get_opt("wallet", "") api_key_path = get_opt("api_key_path", "SatSale_API_key") tunnel_host = get_opt("tunnel_host", None) -tor_bitcoinrpc_host = get_opt("tor_bitcoinrpc_host", None) tor_proxy = get_opt("tor_proxy", None) -pay_method = get_opt("pay_method", "bitcoind") onchain_dust_limit = get_opt("onchain_dust_limit", 0.00000546) -lnd_dir = get_opt("lnd_dir", "~/.lnd/") -lnd_rpcport = get_opt("lnd_rpcport", "10009") -lnd_macaroon = get_opt("lnd_macaroon", "admin.macaroon") -clightning_rpc_file = get_opt("clightning_rpc_file", None) pollrate = get_opt("pollrate", 15) payment_timeout = get_opt("payment_timeout", 60*60) required_confirmations = get_opt("required_confirmations", 2) @@ -42,9 +68,10 @@ connection_attempts = get_opt("connection_attempts", 3) redirect = get_opt("redirect", "https://github.com/nickfarrow/satsale") base_currency = get_opt("base_currency", "USD") currency_provider = get_opt("currency_provider", "COINGECKO") -lightning_address = get_opt("lightning_address", None) -lightning_address_comment = get_opt("lightning_address_comment", None) liquid_address = get_opt("liquid_address", None) paynym = get_opt("paynym", None) free_mode = get_opt("free_mode", False) loglevel = get_opt("loglevel", "DEBUG") + +print(config) +print(tunnel_host) +\ No newline at end of file diff --git a/config.toml b/config.toml @@ -1,64 +1,58 @@ -# SatSale needs to connect to your bitcoin/lnd node, -# with the correct RPC port(s) as set in this config. +# SatSale Config :: Configure payment nodes and SatSale settings +payment_methods = ["bitcoind"] -# Connecting through local host (see below if connecting to remote node): +## BITCOIND :: Add "bitcoind" to payment_methods and from ~/.bitcoin/bitcoin.conf +# use either username / password pair or rpc_cookie_file +# wallet (empty "" if your bitcoind node has a single wallet, OR wallet name/path as shown in `bitcoin-cli listwallets`) +[bitcoind] host = "127.0.0.1" -rpcport = "8332" - -# From ~/.bitcoin/bitcoin.conf -# Use either username / password pair or rpc_cookie_file username = "bitcoinrpc" password = "rpcpassword" +rpcport = "8332" #rpc_cookie_file = - -# Wallet (empty "" if your node has a single wallet, OR wallet name/path as shown in `biitcoin-cli listwallets`) wallet = "" -# File in which API key will be stored -api_key_path = "SatSale_API_key" +## LND :: Add "lnd" to payment_methods +[lnd] +host = "127.0.0.1" +lnd_dir = "~/.lnd/" +lnd_rpcport = "10009" +lnd_macaroon = "invoice.macaroon" +#lightning_address = None #e.g name@your.satsale.domain (think this requires https url) +#lightning_address_comment = None # Defaults to: "Thank you for your support <3" +## CLIGHTNING :: Add "clightning" to payment_methods +# If remote clightning, make sure `ssh -nNT -L {local_lightning-rpc}:{remote_lightning-rpc} {tunnel_host}` +# creates a lightning-rpc unix domain socket. (use full paths local: /home/install/satsale/lightning-rpc) +[clightning] +clightning_rpc_file = "/home/user/.lightning/bitcoin/lightning-rpc" +[satsale] #### Connect To Remote Node #### -# Can use SSH or TOR -# to tunnel/relay ports required to talk to the node via RPC (gRPC for lightning) +# Either SSH or TOR should be used to +# to tunnel/relay communications to the remote node -# SSH tunnel to node +# SSH tunnel to node (recommended) # Make sure this command works `ssh HOST@IP -q -N -L 8332:localhost:8332` -# Combined with host = "127.0.0.1" and you will be able to see your node on 8332 -#tunnel_host = "HOST@IP" +# Leave host="127.0.0.1" and you will be able to see your node as if it were local +#tunnel_host = None # Format: "HOST@IP" -# or tor hidden service for RPC (see docs for how to set up), need onion: -#tor_bitcoinrpc_host = None # e.g. "http://if...dwr.onion" - -# and a tor proxy, default 127.0.0.1:9050 (for Tor Browser use "127.0.0.1:9150") +# TOR hidden service to node (see docs for how to set up), +# Currently only works for bitcoind. +# Set `tor_bitcoinrpc_host="http://if...dwr.onion"` in bitcoind section above: +# A tor proxy, default 127.0.0.1:9050 (for Tor Browser use "127.0.0.1:9150") #tor_proxy = None -#### Payment method #### -pay_method = "bitcoind" +## !! Once up to here, you should now test your node configuration !! + + +# SatSale API key will be stored in this file +api_key_path = "SatSale_API_key" # Dust limit for onchain payments in BTC. Don't generate onchain invoices # below this value. onchain_dust_limit = 0.00000546 -## Lightning -# Switch payment_method to lnd if you want to use lightning payments instead. And uncomment lnd_dir. -#pay_method = "lnd" - -# To find (or copy from remote nodes) the macaroon and TLS certs -#lnd_dir = "~/.lnd/" - -# lnd RPC port and lnd macaroon (uncomment) -#lnd_rpcport = "10009" -#lnd_macaroon = "invoice.macaroon" - -# Or clightning -#pay_method = "clightning" - -# If remote clightning, make sure `ssh -nNT -L {local_lightning-rpc}:{remote_lightning-rpc} {tunnel_host}` -# creates a lightning-rpc unix domain socket. (use full paths local: /home/install/satsale/lightning-rpc) -#clightning_rpc_file = "/home/user/.lightning/lightning-rpc" -####################### - # Check for payment every xx seconds pollrate = 1 @@ -81,10 +75,6 @@ redirect = "https://github.com/nickfarrow/satsale" base_currency = "USD" currency_provider = "COINGECKO" # Supported: COINDESK | COINGECKO -# Lightning Address e.g. name@you.satsale.domain (think this requires https url) -#lightning_address = None -#lightning_address_comment = None # Defaults to: "Thank you for your support <3" - # Weak Hands Mode - Automatically swap LN-BTC -> L-USDT using sideshift.ai # https://blockstream.com/liquid/ # Change lnd_macaroon='admin.macaroon', as you will also need to be able to spend with your lnd certificates. diff --git a/docs/lightning.md b/docs/lightning.md @@ -6,22 +6,23 @@ If installing the python library lndgrpc requirement failed, see this [solution] ## LND -To use lightning, you need to change your `pay_method` in `config.toml`, and set your lightning directory on your node. -```python -pay_method = "lnd" +To connect to a LND node, you need to set `payment_methods = ["lnd", "bitcoind"]` in `config.toml`, and set your lightning directory on your node. +```toml +[lnd] +host = "127.0.0.1" lnd_dir = "~/.lnd/" lnd_rpcport = "10009" +lnd_macaroon = "invoice.macaroon" ``` ## clightning -To use lightning, you need to change your `pay_method` in `config.toml`, and set your lightning directory on your node. -```python -pay_method = "clightning" -# If remote clightning, make sure `ssh -nNT -L lightning-rpc:{clightning_rpc_file} {tunnel_host}` -clightning_rpc_file = "/home/user/.lightning/lightning-rpc" +To use clightning, you need to set `payment_methods = ["clightning", "bitcoind"]` in `config.toml`, and +```toml +[clightning] +clightning_rpc_file = "/home/user/.lightning/bitcoin/lightning-rpc" ``` - +If remote clightning, make sure `ssh -nNT -L {local_lightning-rpc}:{remote_lightning-rpc} {tunnel_host}` creates a lightning-rpc unix domain socket. (use full paths local: /home/install/satsale/lightning-rpc). ## Notes Your lnd directory is used to find your `.tls` and `.macaroon` files that are required to talk to your lightning node. They are copied over SSH into your SatSale folder. If this copy fails, perhaps copy them manually and they will be identified on start up. diff --git a/gateways/lightning_address.py b/gateways/lightning_address.py @@ -3,34 +3,32 @@ from flask_restplus import Resource, Api, Namespace, fields import hashlib import logging -import config - min_sats = 10 ** 2 max_sats = 10 ** 6 # Following https://github.com/andrerfneves/lightning-address/blob/master/DIY.md -description = config.lightning_address_comment -if description is None: - description = "Thank you for your support <3" - -metadata = '[["text/plain", "{}"], ["text/identifier", "{}"]]'.format( - description, config.lightning_address.split("@")[0] -) +def add_ln_address_decorators(app, api, node): + description = node.config['lightning_address_comment'] + address = node.config['lightning_address'] + if description is None: + description = "Thank you for your support <3" + metadata = '[["text/plain", "{}"], ["text/identifier", "{}"]]'.format( + description, address.split("@")[0] + ) -def add_ln_address_decorators(app, api, node): class get_ln_address(Resource): def get(self): try: logging.info( "Someone requested our ln address: {}!".format( - config.lightning_address + address ) ) resp = { "callback": "https://{}/lnaddr".format( - config.lightning_address.split("@")[1] + address.split("@")[1] ), "maxSendable": max_sats * 10 ** 3, "minSendable": min_sats * 10 ** 3, @@ -76,7 +74,7 @@ def add_ln_address_decorators(app, api, node): api.add_resource( get_ln_address, - "/.well-known/lnurlp/{}".format(config.lightning_address.split("@")[0]), + "/.well-known/lnurlp/{}".format(address.split("@")[0]), ) api.add_resource(init_ln_addr_payment, "/lnaddr") return diff --git a/gateways/ssh_tunnel.py b/gateways/ssh_tunnel.py @@ -27,7 +27,7 @@ def open_tunnel(host, port): return None -def clightning_unix_domain_socket_ssh(rpc_store_dir=None): +def clightning_unix_domain_socket_ssh(rpc_file, rpc_store_dir=None): if rpc_store_dir is None: rpc_store_dir = os.getcwd() @@ -39,7 +39,7 @@ def clightning_unix_domain_socket_ssh(rpc_store_dir=None): "ssh", "-nNT", "-L", - "{}:{}".format(local_file, config.clightning_rpc_file), + "{}:{}".format(local_file, rpc_file), "{}".format(config.tunnel_host), ] print("Opening tunnel to {}.".format(" ".join(command))) @@ -67,24 +67,26 @@ def close_tunnels(ssh_processes): except Exception as e: continue - if config.clightning_rpc_file is not None: - rm_lightning_rpc_file() + if "clightning" in config.payment_methods: + rm_lightning_rpc_file() return # Open tunnel def open_tunnels(): - # global ssh_tunnel_processes ssh_tunnel_processes = [] if config.tunnel_host is not None: - ssh_tunnel_processes.append(open_tunnel(config.tunnel_host, config.rpcport)) + for method in config.payment_methods: + if method['name'] == "bitcoind": + ssh_tunnel_processes.append(open_tunnel(config.tunnel_host, method['rpcport'])) - # Also for lnd if enabled - if config.lnd_rpcport is not None: - ssh_tunnel_processes.append(open_tunnel(config.tunnel_host, config.lnd_rpcport)) + # Also for lnd if enabled + if method['name'] == "lnd": + ssh_tunnel_processes.append(open_tunnel(config.tunnel_host, method['lnd_rpcport'])) - # And if clightning is enabled - if config.clightning_rpc_file is not None: - ssh_tunnel_processes.append(clightning_unix_domain_socket_ssh()) + # And if clightning is enabled + if method['name'] == "clightning": + rm_lightning_rpc_file() + ssh_tunnel_processes.append(clightning_unix_domain_socket_ssh(method['clightning_rpc_file'])) - return [proc for proc in ssh_tunnel_processes if proc is not None] -\ No newline at end of file + return [proc for proc in ssh_tunnel_processes if proc is not None] diff --git a/node/bitcoind.py b/node/bitcoind.py @@ -9,74 +9,59 @@ import config from payments.price_feed import get_btc_value from utils import btc_amount_format - -if config.tor_bitcoinrpc_host is not None: - from gateways.tor import session - - -def call_tor_bitcoin_rpc(method, params): - url = "{}:{}".format(config.tor_bitcoinrpc_host, config.rpcport) - payload = json.dumps({"method": method, "params": params}) - headers = {"content-type": "application/json", "cache-control": "no-cache"} - response = session.request( - "POST", - url, - data=payload, - headers=headers, - auth=(config.username, config.password), - ) - return json.loads(response.text) - - class btcd: - def __init__(self): + def __init__(self, node_config): from bitcoinrpc.authproxy import AuthServiceProxy + self.config = node_config + if self.config['tor_bitcoinrpc_host'] is not None: + from gateways.tor import session + self.session = session self.is_onchain = True - if config.rpc_cookie_file: - if os.path.isfile(config.rpc_cookie_file): - rpc_credentials_str = open(config.rpc_cookie_file, "r").read() + if self.config['rpc_cookie_file']: + if os.path.isfile(self.config['rpc_cookie_file']): + rpc_credentials_str = open(self.config['rpc_cookie_file'], "r").read() (username, password) = rpc_credentials_str.split(":") else: raise Exception( - "rpc_cookie_file {} not found".format(config.rpc_cookie_file) + "rpc_cookie_file {} not found".format(self.config['rpc_cookie_file']) ) else: - username = config.username - password = config.password + username = self.config['username'] + password = self.config['password'] for i in range(config.connection_attempts): - if config.tor_bitcoinrpc_host is None: + if self.config['tor_bitcoinrpc_host'] is None: self.tor = False connection_str = "http://{}:{}@{}:{}/wallet/{}".format( username, password, config.host, - config.rpcport, - config.wallet, + self.config['rpcport'], + self.config['wallet'], ) logging.info( "Attempting to connect to Bitcoin node RPC with user {}.".format( - config.username + self.config['username'] ) ) else: self.tor = True logging.info( "Attempting to contact bitcoind rpc tor hidden service: {}:{}".format( - config.tor_bitcoinrpc_host, config.rpcport + self.config['tor_bitcoinrpc_host'], self.config['rpcport'] ) ) try: # Normal Connection - if config.tor_bitcoinrpc_host is None: + if self.config['tor_bitcoinrpc_host'] is None: self.rpc = AuthServiceProxy(connection_str) info = self.rpc.getblockchaininfo() # Tor Connection else: - info = call_tor_bitcoin_rpc("getblockchaininfo", None) + info = self.call_tor_bitcoin_rpc("getblockchaininfo", None) logging.info(info) logging.info("Successfully contacted bitcoind.") @@ -96,6 +81,19 @@ class btcd: Check your RPC / port tunneling settings and try again." ) + def call_tor_bitcoin_rpc(self, method, params): + url = "{}:{}".format(self.config['tor_bitcoinrpc_host'], config.rpcport) + payload = json.dumps({"method": method, "params": params}) + headers = {"content-type": "application/json", "cache-control": "no-cache"} + response = self.session.request( + "POST", + url, + data=payload, + headers=headers, + auth=(config.username, config.password), + ) + return json.loads(response.text) + def create_qr(self, uuid, address, value): qr_str = "bitcoin:{}?amount={}&label={}".format( address, btc_amount_format(value), uuid @@ -109,7 +107,7 @@ class btcd: if not self.tor: transactions = self.rpc.listtransactions(uuid) else: - transactions = call_tor_bitcoin_rpc("listtransactions", [uuid])["result"] + transactions = self.call_tor_bitcoin_rpc("listtransactions", [uuid])["result"] conf_paid = 0 unconf_paid = 0 @@ -127,7 +125,7 @@ class btcd: if not self.tor: address = self.rpc.getnewaddress(label) else: - address = call_tor_bitcoin_rpc("getnewaddress", [label])["result"] + address = self.call_tor_bitcoin_rpc("getnewaddress", [label])["result"] return address, None diff --git a/node/clightning.py b/node/clightning.py @@ -20,15 +20,16 @@ import config class clightning: - def __init__(self): + def __init__(self, node_config): from pyln.client import LightningRpc + self.config = node_config self.is_onchain = False for i in range(config.connection_attempts): try: if config.tunnel_host is None: - rpc_file = config.clightning_rpc_file + rpc_file = self.config['clightning_rpc_file'] else: rpc_file = "lightning-rpc" diff --git a/node/lnd.py b/node/lnd.py @@ -15,16 +15,17 @@ import config class lnd: - def __init__(self): + def __init__(self, node_config): from lndgrpc import LNDClient + self.config = node_config self.is_onchain = False # Copy admin macaroon and tls cert to local machine self.copy_certs() # Conect to lightning node - connection_str = "{}:{}".format(config.host, config.lnd_rpcport) + connection_str = "{}:{}".format(config.host, self.config['lnd_rpcport']) logging.info( "Attempting to connect to lightning node {}. This may take a few seconds...".format( connection_str @@ -36,7 +37,7 @@ class lnd: logging.info("Attempting to initialise lnd rpc client...") time.sleep(3) self.lnd = LNDClient( - "{}:{}".format(config.host, config.lnd_rpcport), + "{}:{}".format(config.host, self.config['lnd_rpcport']), macaroon_filepath=self.certs["macaroon"], cert_filepath=self.certs["tls"], ) @@ -77,16 +78,16 @@ class lnd: # Copy tls and macaroon certs from remote machine. def copy_certs(self): - self.certs = {"tls": "tls.cert", "macaroon": config.lnd_macaroon} + self.certs = {"tls": "tls.cert", "macaroon": self.config['lnd_macaroon']} if (not os.path.isfile("tls.cert")) or ( - not os.path.isfile(config.lnd_macaroon) + not os.path.isfile(self.config['lnd_macaroon']) ): try: - tls_file = os.path.join(config.lnd_dir, "tls.cert") + tls_file = os.path.join(self.config['lnd_dir'], "tls.cert") macaroon_file = os.path.join( - config.lnd_dir, - "data/chain/bitcoin/mainnet/{}".format(config.lnd_macaroon), + self.config['lnd_dir'], + "data/chain/bitcoin/mainnet/{}".format(self.config['lnd_macaroon']), ) # SSH copy @@ -94,7 +95,7 @@ class lnd: logging.warning( "Could not find tls.cert or {} in SatSale folder. \ Attempting to download from remote lnd directory.".format( - config.lnd_macaroon + self.config['lnd_macaroon'] ) ) diff --git a/satsale.py b/satsale.py @@ -69,8 +69,7 @@ def index(): @app.route("/pay") def pay(): params = dict(request.args) - params["lnd_enabled"] = config.pay_method == "lnd" - params["cln_enabled"] = config.pay_method == "clightning" + params["payment_methods"] = enabled_payment_methods params["redirect"] = config.redirect # Render payment page with the request arguments (?amount= etc.) headers = {"Content-Type": "text/html"} @@ -135,7 +134,7 @@ class create_payment(Resource): label = "" # request.args.get('label') payment_method = request.args.get("method") if payment_method is None: - payment_method = config.pay_method + payment_method = enabled_payment_methods[0] webhook = request.args.get("w_url") if webhook is None: webhook = None @@ -284,9 +283,9 @@ def check_payment_status(uuid): # If payment has not expired, then we're going to check for any transactions if status["time_left"] > 0: node = get_node(invoice["method"]) - if invoice["method"] == "lnd": + if node.config['name'] == "lnd": conf_paid, unconf_paid = node.check_payment(invoice["rhash"]) - else: + elif (node.config['name'] == "bitcoind") or (node.config['name'] == "clightning"): # Lookup bitcoind / clightning invoice based on label (uuid) conf_paid, unconf_paid = node.check_payment(invoice["uuid"]) @@ -319,11 +318,9 @@ def check_payment_status(uuid): def get_node(payment_method): - if payment_method == "bitcoind": + if payment_method == "onchain": node = bitcoin_node - elif payment_method == "lnd": - node = lightning_node - elif payment_method == "clightning": + elif payment_method == "lightning": node = lightning_node else: node = None @@ -335,23 +332,27 @@ api.add_resource(create_payment, "/api/createpayment") api.add_resource(check_payment, "/api/checkpayment") api.add_resource(complete_payment, "/api/completepayment") - # Test connections on startup: -logging.info("Connecting to node...") -bitcoin_node = bitcoind.btcd() -logging.info("Connection to bitcoin node successful.") -if config.pay_method == "lnd": - lightning_node = lnd.lnd() - logging.info("Connection to lightning node (lnd) successful.") -elif config.pay_method == "clightning": - lightning_node = clightning.clightning() - logging.info("Connection to lightning node (clightning) successful.") - - -if config.lightning_address is not None: - from gateways import lightning_address - - lightning_address.add_ln_address_decorators(app, api, lightning_node) +enabled_payment_methods = [] +for method in config.payment_methods: + print(method) + if method['name'] == "bitcoind": + bitcoin_node = bitcoind.btcd(method) + logging.info("Connection to bitcoin node successful.") + enabled_payment_methods.append("onchain") + + elif method['name'] == "lnd": + lightning_node = lnd.lnd(method) + logging.info("Connection to lightning node (lnd) successful.") + if lightning_node.config['lightning_address'] is not None: + from gateways import lightning_address + lightning_address.add_ln_address_decorators(app, api, lightning_node) + enabled_payment_methods.append("lightning") + + elif method['name'] == "clightning": + lightning_node = clightning.clightning(method) + logging.info("Connection to lightning node (clightning) successful.") + enabled_payment_methods.append("lightning") if config.paynym is not None: paynym.insert_paynym_html(config.paynym) diff --git a/templates/index.html b/templates/index.html @@ -50,20 +50,17 @@ <div id="row"> <div id="left" style="text-align: left; padding: 0;"> <div id="paymentMethodSwitchButton" style="display:none;"> - <!-- Alternate between offering lightning or on chain payment switch --> - {% if params.lnd_enabled %} - {% if params.method != "bitcoind"%} - <button class="button button1" onclick="replaceUrlParam(window.location, 'method', 'bitcoind');">Onchain Payment</button> - {% else %} - <button class="button button1" onclick="replaceUrlParam(window.location, 'method', 'lnd');">Lightning Payment</button> - {% endif %} - {% endif %} - {% if params.cln_enabled %} - {% if params.method != "bitcoind"%} - <button class="button button1" onclick="replaceUrlParam(window.location, 'method', 'bitcoind');">Onchain Payment</button> - {% else %} - <button class="button button1" onclick="replaceUrlParam(window.location, 'method', 'clightning');">Lightning Payment</button> - {% endif %} + {% if params.payment_methods|length > 1 %} + <select class="button" name="method" id="payment_method_select" onchange="replaceUrlParam(window.location, 'method', document.getElementById('payment_method_select').value);"> + {% if params.method %} + <option value="{{ params.method }}">{{ params.method }}</option> + {% endif %} + {% for method in params.payment_methods %} + {% if params.method != method %} + <option value="{{ method }}">{{ method }}</option> + {% endif %} + {% endfor %} + </select> {% endif %} </div> </div>