SatSale

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

commit dc844c79c2125d557b42c59748bae9bc998cc574
parent 4eb3da7a2241342647ef77da6d0f4dfe7b27e57c
Author: Nick <nick@nickfarrow.com>
Date:   Mon, 28 Mar 2022 17:09:55 +1100

Add lightning node info page (#57)

* Add lightning node info page

* pr feedback
Diffstat:
Mconfig.py | 1+
Mconfig.toml | 8++++++++
Mnode/clightning.py | 8++++++++
Mnode/lnd.py | 9++++++++-
Msatsale.py | 35++++++++++++++++++++++++++++++++---
Mstatic/style.css | 2+-
Mtemplates/donate.html | 26++++++++++++++++++--------
Mtemplates/index.html | 10+++++++---
Atemplates/node.html | 50++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 133 insertions(+), 16 deletions(-)

diff --git a/config.py b/config.py @@ -62,6 +62,7 @@ tunnel_host = get_opt("tunnel_host", None) tunnel_port = get_opt("tunnel_port", 22) tor_proxy = get_opt("tor_proxy", None) onchain_dust_limit = get_opt("onchain_dust_limit", 0.00000546) +node_info = get_opt("node_info", None) pollrate = get_opt("pollrate", 15) payment_timeout = get_opt("payment_timeout", 60*60) required_confirmations = get_opt("required_confirmations", 2) diff --git a/config.toml b/config.toml @@ -13,6 +13,8 @@ rpcport = "8332" wallet = "" ## LND :: Add "lnd" to payment_methods +# You can display your node connection so users can open channels with you by setting +# node_info="uri" (manually) or true (fetch if macaroon has access to `getinfo`) [lnd] host = "127.0.0.1" lnd_dir = "~/.lnd/" @@ -24,6 +26,8 @@ lnd_macaroon = "invoice.macaroon" ## CLIGHTNING :: Add "clightning" to payment_methods # If remote clightning, make sure `ssh -nNT -L {local_lightning-rpc}:{remote_lightning-rpc} {tunnel_host} -p {tunnel_port}` # creates a lightning-rpc unix domain socket. (use full paths local: /home/install/satsale/lightning-rpc) +# You can display your node connection so users can open channels with you by setting +# node_info="uri" (manually) or true (fetch if macaroon has access to `getinfo`) [clightning] clightning_rpc_file = "/home/user/.lightning/bitcoin/lightning-rpc" @@ -54,6 +58,10 @@ api_key_path = "SatSale_API_key" # below this value. onchain_dust_limit = 0.00000546 +# You can display your node uri so users can open channels with you by setting +# node_info="uri" (manually) or true (use `admin.macaroon` to fetch `getinfo`) +#node_info = "uri" + # Check for payment every xx seconds pollrate = 1 diff --git a/node/clightning.py b/node/clightning.py @@ -72,6 +72,14 @@ class clightning: img.save("static/qr_codes/{}.png".format(uuid)) return + def get_info(self): + return self.clightning.getinfo() + + def get_uri(self): + info = self.get_info() + address = info["address"][0] + return info["id"] + "@" + address["address"] + ":" + str(address["port"]) + # Create lightning invoice def create_clightning_invoice(self, btc_amount, label): # Multiplying by 10^8 to convert to satoshi units diff --git a/node/lnd.py b/node/lnd.py @@ -48,7 +48,7 @@ class lnd: logging.info(inv) else: logging.info("Getting lnd info...") - info = self.lnd.get_info() + info = self.get_info() logging.info(info) logging.info("Successfully contacted lnd.") @@ -149,6 +149,13 @@ class lnd: logging.info(ret) return + def get_info(self): + return json.loads(MessageToJson(self.lnd.get_info())) + + def get_uri(self): + info = self.get_info() + return info["uris"][0] + # Check whether the payment has been paid def check_payment(self, rhash): invoice_status = json.loads( diff --git a/satsale.py b/satsale.py @@ -14,9 +14,11 @@ import uuid import sqlite3 from pprint import pprint import json +import qrcode import logging import config + # Initialise logging before importing other modules logging.basicConfig( format="[%(asctime)s] [%(levelname)s] %(message)s", @@ -61,6 +63,7 @@ database.migrate_database() def index(): params = dict(request.args) params["currency"] = config.base_currency + params["node_info"] = config.node_info headers = {"Content-Type": "text/html"} return make_response(render_template("donate.html", params=params), 200, headers) @@ -71,6 +74,7 @@ def pay(): params = dict(request.args) params["payment_methods"] = enabled_payment_methods params["redirect"] = config.redirect + params["node_info"] = config.node_info # Render payment page with the request arguments (?amount= etc.) headers = {"Content-Type": "text/html"} return make_response(render_template("index.html", params=params), 200, headers) @@ -152,8 +156,12 @@ class create_payment(Resource): if node.is_onchain and btc_value < config.onchain_dust_limit: logging.warning( "Requested onchain payment for {} {} below dust limit ({} < {})".format( - base_amount, currency, btc_amount_format(btc_value), - btc_amount_format(config.onchain_dust_limit))) + base_amount, + currency, + btc_amount_format(btc_value), + btc_amount_format(config.onchain_dust_limit), + ) + ) return {"message": "Amount below dust limit."}, 406 invoice = { @@ -163,7 +171,7 @@ class create_payment(Resource): "method": payment_method, "time": time.time(), "webhook": webhook, - "onchain_dust_limit": config.onchain_dust_limit + "onchain_dust_limit": config.onchain_dust_limit, } # Get an address / invoice, and create a QR code @@ -354,6 +362,27 @@ for method in config.payment_methods: logging.info("Connection to lightning node (clightning) successful.") enabled_payment_methods.append("lightning") +# Add node connection page +if config.node_info is not None: + @app.route("/node/") + def node(): + if config.node_info == True: + uri = lightning_node.get_uri() + else: + uri = config.node_info + img = qrcode.make(uri) + img.save("static/qr_codes/node.png") + headers = {"Content-Type": "text/html"} + return make_response( + render_template("node.html", params={"uri": uri}), 200, headers + ) + +# Add lightning address +if lightning_node.config['lightning_address'] is not None: + from gateways import lightning_address + lightning_address.add_ln_address_decorators(app, api, lightning_node) + +# Add Paynym if config.paynym is not None: paynym.insert_paynym_html(config.paynym) diff --git a/static/style.css b/static/style.css @@ -16,7 +16,7 @@ body { /* Rounded Corners */ border-radius: 25px; - font-size: 16px + font-size: 16px; height: 275px; width:360px; diff --git a/templates/donate.html b/templates/donate.html @@ -28,7 +28,6 @@ <meta property="twitter:description" content="Lightweight Bitcoin payment processor written in easily deployable Python. "> <meta property="twitter:image" content="https://user-images.githubusercontent.com/24557779/109666538-60ee4800-7bc3-11eb-8615-2cb1b239cc11.png"> - </head> @@ -45,18 +44,29 @@ </div> <div id="paymentForm"> - <center> - <form id="pay" action='/pay' style="margin:0;padding0;"> - <h2 style="margin:0;padding0;">Amount: + <form id="pay" action='/pay'> + <div style="display:block;text-align: center;"> + <h2 style="margin:0;">Amount: <input id="amountenter" style="display:inline" size="4" type="float" name="amount" id="amount" placeholder="{{ params.currency }}" required> </h2> <br> <input class="button button1" style="width:40%" type="submit" value="Donate"> - </form> - </center> + </div> + </form> + <div id="paybutton"></div> + </div> + <br> + <div id="row"> + <div id="left"> + {% if params.node_info %} + <small><a id="about" href="/node/" target="_blank">Open a Lightning channel with me!</a></small> + </br> + {% endif %} + </div> + <div id="right" style="text-align:right;"> + <small style="vertical-align:middle"><a id="about" href="https://github.com/nickfarrow/SatSale" target="_blank">SatSale</a></small> + </div> </div> - - <div id="paybutton"></div> </div> </body> </html> diff --git a/templates/index.html b/templates/index.html @@ -25,7 +25,7 @@ <div id="paybox"> <div id="row" height="50px"> <div id="left" style="display:inline-block;" height="75px"> - <h1>Pay Bitcoin</h> + <h1>Pay Bitcoin</h1> </div> <div id="right"> <a id="qrClick" target="_blank"><img class="logo" id="qrImage" width="100px" src="{{ url_for('static', filename='logo.svg') }}"></a> @@ -48,7 +48,7 @@ </br> <div id="row"> - <div id="left" style="text-align: left; padding: 0;"> + <div id="left" style="width:40%; text-align: left; padding: 0;"> <div id="paymentMethodSwitchButton" style="display:none;"> {% 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);"> @@ -65,7 +65,11 @@ </div> </div> - <div id="right" style="text-align: right; padding: 10px 10px;"> + <div id="right" style="width:60%; text-align: right; padding: 10px 10px;"> + {% if params.node_info %} + <small><a id="about" href="/node/" target="_blank">Open a channel with me!</a></small> + </br> + {% endif %} <small style="vertical-align:middle"><a id="about" href="https://github.com/nickfarrow/SatSale" target="_blank">SatSale</a></small> </div> </div> diff --git a/templates/node.html b/templates/node.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>SatSale</title> + <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> + <meta name="viewport" content="width=device-width,initial-scale=1.0"> + + <script src="{{ url_for('static', filename='jquery-3.6.0.min.js') }}"></script> + <script src="{{ url_for('static', filename='socket.io.min.js') }}"></script> + <script src="{{ url_for('static', filename='satsale.js') }}"></script> + + <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> +</head> + + +<body> + <div id="paybox"> + <div id="row" height="50px"> + <div id="left" style="display:inline-block;" height="75px"> + <h1>Open a channel:</h1> + </div> + <div id="right"> + <p><img class="qr" style="display:block; margin-left: auto; margin-right: auto;" width="100px" src="{{ url_for('static', filename='qr_codes/node.png') }}"></p> + </div> + </div> + <pre id="nodeInfo" style="padding:10px;background-color:black;color:white;border-radius:15px;white-space:pre-wrap;word-wrap:break-word;"> + <span id="node_url"></span> + </pre> + + </br> + + <div id="row"> + <div id="left" style="text-align: left; padding: 0;"> + </div> + + <div id="right" style="text-align: right; padding: 10px 10px;"> + <small style="vertical-align:middle"><a id="about" href="https://github.com/nickfarrow/SatSale" target="_blank">SatSale</a></small> + </div> + </div> + </div> + + <script type="text/javascript"> + node_info = {{ params|tojson }}; + console.log(node_info); + document.getElementById("node_url").innerHTML = node_info.uri; + + </script> + +</body> +</html>