SatSale

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

commit 7ecc903350e6e95e2387f681bf9991b63590b771
parent b4bb30b92805e45b9ac2ea6a1ad45f250b331f01
Author: Kristaps Kaupe <kristaps@blogiem.lv>
Date:   Thu,  3 Mar 2022 09:51:01 +0200

Add configurable dust limit for onchain payments (#46)

* Fix BTC amount formatting for amounts below 0.0001

* Add configurable dust limit for onchain payments
Diffstat:
Mconfig.py | 1+
Mconfig.toml | 4++++
Mnode/bitcoind.py | 2++
Mnode/clightning.py | 2++
Mnode/lnd.py | 2++
Msatsale.py | 12+++++++++++-
Mstatic/satsale.js | 18++++++++++++++----
Mtemplates/index.html | 8+++++++-
8 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/config.py b/config.py @@ -30,6 +30,7 @@ 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") diff --git a/config.toml b/config.toml @@ -36,6 +36,10 @@ api_key_path = "SatSale_API_key" #### Payment method #### pay_method = "bitcoind" +# 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" diff --git a/node/bitcoind.py b/node/bitcoind.py @@ -32,6 +32,8 @@ class btcd: def __init__(self): from bitcoinrpc.authproxy import AuthServiceProxy + 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() diff --git a/node/clightning.py b/node/clightning.py @@ -23,6 +23,8 @@ class clightning: def __init__(self): from pyln.client import LightningRpc + self.is_onchain = False + for i in range(config.connection_attempts): try: logging.info("Attempting to connect to clightning...") diff --git a/node/lnd.py b/node/lnd.py @@ -18,6 +18,8 @@ class lnd: def __init__(self): from lndgrpc import LNDClient + self.is_onchain = False + # Copy admin macaroon and tls cert to local machine self.copy_certs() diff --git a/satsale.py b/satsale.py @@ -122,6 +122,7 @@ status_model = api.model( class create_payment(Resource): @api.response(200, "Success", invoice_model) @api.response(400, "Invalid payment method") + @api.response(406, "Amount below dust limit") def get(self): "Create Payment" """Initiate a new payment with an `amount` in `config.base_currecy`.""" @@ -144,13 +145,22 @@ class create_payment(Resource): logging.warning("Invalid payment method {}".format(payment_method)) return {"message": "Invalid payment method."}, 400 + btc_value = get_btc_value(base_amount, currency) + 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))) + return {"message": "Amount below dust limit."}, 406 + invoice = { "uuid": str(uuid.uuid4().hex), "fiat_value": base_amount, - "btc_value": btc_amount_format(get_btc_value(base_amount, currency)), + "btc_value": btc_amount_format(btc_value), "method": payment_method, "time": time.time(), "webhook": webhook, + "onchain_dust_limit": config.onchain_dust_limit } # Get an address / invoice, and create a QR code diff --git a/static/satsale.js b/static/satsale.js @@ -17,14 +17,24 @@ function payment(payment_data) { $('#amount').text(invoice.btc_value).html(); $('#amount_sats').text(Math.round(invoice.btc_value * 10**8)).html(); $('#timer').text(Math.round(invoice.time_left)).html(); + $('#paymentDetails').show(); + + if (invoice.btc_value >= invoice.onchain_dust_limit) { + $('#paymentMethodSwitchButton').show(); + } return payment_uuid + }, function(data) { + $('#error').show(); + return ""; }).then(function(payment_uuid) { - load_qr(payment_uuid); - document.getElementById('timerContainer').style.visibility = "visible"; + if (payment_uuid != "") { + load_qr(payment_uuid); + document.getElementById('timerContainer').style.visibility = "visible"; - // Pass payment uuid and the interval process to check_payment - var checkinterval = setInterval(function() {check_payment(payment_uuid, checkinterval, payment_data);}, 1000); + // Pass payment uuid and the interval process to check_payment + var checkinterval = setInterval(function() {check_payment(payment_uuid, checkinterval, payment_data);}, 1000); + } }) }); } diff --git a/templates/index.html b/templates/index.html @@ -33,7 +33,7 @@ </div> - <div id="paymentDetails" style="display:block; padding: 0;"> + <div id="paymentDetails" style="display:none; padding: 0;"> <p style="padding:0;">Send: <b><span id="amount_sats"></span></b> sats</p> <p style="padding:0;">&nbsp&nbsp&nbsp&nbsp&nbsp(<b><span id="amount"></span></b> BTC)</p> <p style="padding:0;">To: </p><b><p id="address" onclick="copyTextFromElement('address')"></p></b> @@ -41,10 +41,15 @@ <p id="timerContainer" style="padding:0;visibility:hidden;"><span id="timer"></span> seconds remaining.</p> </div> + <div id="error" style="display:none;"> + <p style="padding:0;">Error generating invoice! Amount too small?</p> + </div> + </br> <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"%} @@ -60,6 +65,7 @@ <button class="button button1" onclick="replaceUrlParam(window.location, 'method', 'clightning');">Lightning Payment</button> {% endif %} {% endif %} + </div> </div> <div id="right" style="text-align: right; padding: 10px 10px;">