diff --git a/LNbits/__pycache__/lnurlreq.cpython-37.pyc b/LNbits/__pycache__/lnurlreq.cpython-37.pyc new file mode 100644 index 00000000..760e879b Binary files /dev/null and b/LNbits/__pycache__/lnurlreq.cpython-37.pyc differ diff --git a/LNbits/database.sqlite3 b/LNbits/database.sqlite3 new file mode 100644 index 00000000..12bc1151 Binary files /dev/null and b/LNbits/database.sqlite3 differ diff --git a/LNbits/server.py b/LNbits/server.py new file mode 100644 index 00000000..5a115669 --- /dev/null +++ b/LNbits/server.py @@ -0,0 +1,511 @@ +from flask import Flask, render_template +from flask import Flask, redirect +from flask import request +from flask import jsonify +from flask import Flask, g +from random import seed +from random import random +from flask import json +import re +import os +import sqlite3 +import base64 +import lnurl +import requests +import hashlib +import time +import json +import bech32 + +#DATABASE = 'database.db' + +INVOICE_KEY = "YOUR-LNTXBOT-INVOICE-KEY" #In the lntxbot bot on telegram type "/api" +ADMIN_KEY = "YOUR-LNTXBOT-ADMIN-KEY" +API_ENDPOINT = "YOUR-LNTXBOT-API-BASE-URL" + +app = Flask(__name__) + + +DEFAULT_PATH = "database.sqlite3" + + +def db_connect(db_path=DEFAULT_PATH): + con = sqlite3.connect(db_path) + return con + +def encrypt_string(hash_string): + sha_signature = \ + hashlib.sha256(hash_string.encode()).hexdigest() + return sha_signature + + +@app.route('/') +def home(): + + return render_template('index.html') + +@app.route('/deletewallet') +def deletewallet(): + + thewal = request.args.get('wal'); + + con = db_connect() + cur = con.cursor() + print(thewal) + cur.execute("select * from wallets WHERE hash = '" + str(thewal) + "'") + rowss = cur.fetchall() + + if len(rowss) > 0: + + cur.close() + print(rowss) + + con = db_connect() + cur = con.cursor() + + cur.execute("UPDATE wallets SET user = '" + "del" + rowss[0][4] + "' WHERE hash = '" + rowss[0][0] + "'") + + con.commit() + cur.close() + + con = db_connect() + cur = con.cursor() + + cur.execute("UPDATE wallets SET adminkey = '" + "del" + rowss[0][5] + "' WHERE hash = '" + rowss[0][0] + "'") + + con.commit() + cur.close() + + + con = db_connect() + cur = con.cursor() + + cur.execute("UPDATE wallets SET inkey = '" + "del" + rowss[0][6] + "' WHERE hash = '" + rowss[0][0] + "'") + + con.commit() + cur.close() + + con = db_connect() + cur = con.cursor() + print(thewal) + cur.execute("select * from wallets WHERE user = '" + rowss[0][4] + "'") + rowsss = cur.fetchall() + + if len(rowsss) > 0: + cur.close() + return render_template('deletewallet.html', theid = rowsss[0][4], thewal = rowsss[0][0]) + else: + return render_template('index.html') + + else: + return render_template('index.html') + + + +@app.route('/lnurlwallet') +def lnurlwallet(): + + #put in a function + thestr = request.args.get('lightning'); + lnurll = lnurl.decode(thestr) + r = requests.get(url = lnurll) + + data = r.json() + + + callback = data['callback'] + maxwithdraw = data['maxWithdrawable'] + withdraw = int(maxwithdraw/1000) + k1 = data['k1'] + + + #get invoice + dataj = {'amt': str(withdraw)} + headers = {'Authorization': 'Basic %s' % INVOICE_KEY} + rr = requests.post(url = API_ENDPOINT + "/addinvoice", json = dataj, headers = headers) + + dataa = rr.json() + + #get callback + + pay_req = dataa['pay_req'] + payment_hash = dataa['payment_hash'] + + invurl = callback + '&k1=' + k1 + '&pr=' + pay_req + + rrr = requests.get(url = invurl) + dataaa = rrr.json() + + print(dataaa) + print("poo") + + if dataaa['status'] == "OK": + + data = "" + while data == "": + r = requests.post(url = API_ENDPOINT + "/invoicestatus/" + str(payment_hash), headers = headers) + data = r.json() + print(r.json()) + + adminkey = encrypt_string(payment_hash)[0:20] + inkey = encrypt_string(adminkey)[0:20] + thewal = encrypt_string(inkey)[0:20] + theid = encrypt_string(thewal)[0:20] + thenme = "Bitcoin LN Wallet" + + + con = db_connect() + cur = con.cursor() + + cur.execute("INSERT INTO accounts (userhash) VALUES ('" + theid + "')") + con.commit() + cur.close() + + con = db_connect() + cur = con.cursor() + + adminkey = encrypt_string(theid) + inkey = encrypt_string(adminkey) + + cur.execute("INSERT INTO wallets (hash, balance, transactions, name, user, adminkey, inkey) VALUES ('" + thewal + "',',0," + str(withdraw) + "','0','" + thenme + "','" + theid + "','" + adminkey + "','" + inkey + "')") + con.commit() + cur.close() + + con = db_connect() + cur = con.cursor() + print(thewal) + cur.execute("select * from wallets WHERE user = '" + str(theid) + "'") + rows = cur.fetchall() + con.commit() + cur.close() + return render_template('lnurlwallet.html', len = len("1"), walnme = thenme, walbal = str(withdraw), theid = theid, thewal = thewal, adminkey = adminkey, inkey = inkey) + else: + return render_template('index.html') + + +@app.route('/wallet') +def wallet(): + + theid = request.args.get('usr'); + thewal = request.args.get('wal'); + theamt = request.args.get('amt'); + thenme = request.args.get('nme'); + + if not thewal: + return render_template('index.html') + else: + #Checks if the user exists in "accounts" + con = db_connect() + cur = con.cursor() + print(thewal) + cur.execute("select * from accounts WHERE userhash = '" + str(theid) + "'") + rows = cur.fetchall() + + if len(rows) > 0: + cur.close() + + #Yes, check the user has a wallet + con = db_connect() + cur = con.cursor() + print(thewal) + cur.execute("select * from wallets WHERE user = '" + str(theid) + "'") + rowss = cur.fetchall() + + if len(rowss) > 0: + cur.close() + + #Checks if the current wallet exists + con = db_connect() + cur = con.cursor() + print(thewal) + cur.execute("select * from wallets WHERE hash = '" + str(thewal) + "'") + rowsss = cur.fetchall() + + if len(rowsss) > 0: + cur.close() + walb = rowsss[0][1].split(",")[-1] + return render_template('wallet.html', thearr = rowss, len = len(rowss), walnme = rowsss[0][3], user = theid, walbal = walb, theid = theid, thewal = thewal, transactions = rowsss[0][2], adminkey = rowsss[0][5], inkey = rowsss[0][6]) + else: + cur.close() + + con = db_connect() + cur = con.cursor() + + adminkey = encrypt_string(thewal) + inkey = encrypt_string(adminkey) + + cur.execute("INSERT INTO wallets (hash, balance, transactions, name, user, adminkey, inkey) VALUES ('" + thewal + "',',0','0','" + thenme + "','" + theid + "','" + adminkey + "','" + inkey + "')") + con.commit() + cur.close() + + + con = db_connect() + cur = con.cursor() + print(thewal) + cur.execute("select * from wallets WHERE user = '" + str(theid) + "'") + rowss = cur.fetchall() + cur.close() + + return render_template('wallet.html', thearr = rowss, len = len(rowss), walnme = thenme, walbal = '0', theid = theid, thewal = thewal, adminkey = adminkey, inkey = inkey) + else: + cur.close() + + con = db_connect() + cur = con.cursor() + + adminkey = encrypt_string(theid) + inkey = encrypt_string(adminkey) + + cur.execute("INSERT INTO wallets (hash, balance, transactions, name, user, adminkey, inkey) VALUES ('" + thewal + "',',0','0','" + thenme + "','" + theid + "','" + adminkey + "','" + inkey + "')") + con.commit() + cur.close() + + return render_template('wallet.html', len = len("1"), walnme = thenme, walbal = '0', theid = theid, thewal = thewal, adminkey = adminkey, inkey = inkey) + + else: + cur.close() + con = db_connect() + cur = con.cursor() + + cur.execute("INSERT INTO accounts (userhash) VALUES ('" + theid + "')") + con.commit() + cur.close() + + con = db_connect() + cur = con.cursor() + + adminkey = encrypt_string(theid) + inkey = encrypt_string(adminkey) + + cur.execute("INSERT INTO wallets (hash, balance, transactions, name, user, adminkey, inkey) VALUES ('" + thewal + "',',0','0','" + thenme + "','" + theid + "','" + adminkey + "','" + inkey + "')") + con.commit() + cur.close() + + con = db_connect() + cur = con.cursor() + print(thewal) + cur.execute("select * from wallets WHERE user = '" + str(theid) + "'") + rows = cur.fetchall() + con.commit() + cur.close() + + return render_template('wallet.html', len = len("1"), walnme = thenme, walbal = '0', theid = theid, thewal = thewal, adminkey = adminkey, inkey = inkey) + + + +#API requests +@app.route('/v1/invoices', methods=['GET', 'POST']) +def api_invoices(): + if request.headers['Content-Type'] == 'application/json': + + postedjson = request.json + print(postedjson) + + if "value" in postedjson: + if postedjson["value"].isdigit() == True: + if "memo" in postedjson: + con = db_connect() + cur = con.cursor() + + cur.execute("select * from wallets WHERE inkey = '" + request.headers['Grpc-Metadata-macaroon']+ "'") + rows = cur.fetchall() + + if len(rows) > 0: + cur.close() + + dataj = {'amt': postedjson["value"], 'memo': postedjson["memo"]} + headers = {'Authorization': 'Basic %s' % INVOICE_KEY} + r = requests.post(url = API_ENDPOINT + "/addinvoice", json = dataj, headers = headers) + + data = r.json() + + pay_req = data['pay_req'] + payment_hash = data['payment_hash'] + + con = db_connect() + cur = con.cursor() + + cur.execute("INSERT INTO apipayments (payhash, amount, wallet, paid, inkey, memo) VALUES ('" + payment_hash + "','" + postedjson["value"] + "','" + rows[0][0] + "','0','" + request.headers['Grpc-Metadata-macaroon'] + "','" + postedjson["memo"] + "')") + con.commit() + cur.close() + + return jsonify({"pay_req": pay_req, "payment_hash": payment_hash}), 200 + + else: + return jsonify({"ERROR": "NO KEY"}), 200 + else: + return jsonify({"ERROR": "NO MEMO"}), 200 + else: + return jsonify({"ERROR": "VALUE MUST BE A NUMMBER"}), 200 + else: + return jsonify({"ERROR": "NO VALUE"}), 200 + else: + return jsonify({"ERROR": "MUST BE JSON"}), 200 + + +#API requests +@app.route('/v1/channels/transactions', methods=['GET', 'POST']) +def api_transactions(): + if request.headers['Content-Type'] == 'application/json': + postedjson = request.json + print(postedjson) + print(postedjson["payment_request"]) + + if "payment_request" in postedjson: + con = db_connect() + cur = con.cursor() + print(request.headers['Grpc-Metadata-macaroon']) + print() + cur.execute("select * from wallets WHERE adminkey = '" + request.headers['Grpc-Metadata-macaroon']+ "'") + rows = cur.fetchall() + if len(rows) > 0: + cur.close() + + + + s = postedjson["payment_request"] + result = re.search('lnbc(.*)1p', s) + tempp = result.group(1) + + alpha = "" + num = "" + + for i in range(len(tempp)): + if (tempp[i].isdigit()): + num = num+ tempp[i] + else: + alpha += tempp[i] + sats = "" + if alpha == "n": + sats = int(num)/10 + elif alpha == "u": + sats = int(num)*100 + elif alpha == "m": + sats = int(num)*100000 + + print(sats) + print(alpha) + print(num) + + dataj = {'invoice': postedjson["payment_request"]} + headers = {'Authorization': 'Basic %s' % ADMIN_KEY} + r = requests.post(url = API_ENDPOINT + "/payinvoice", json = dataj, headers = headers) + data = r.json() + print(data); + + + con = db_connect() + cur = con.cursor() + + cur.execute("INSERT INTO apipayments (payhash, amount, wallet, paid, adminkey, memo) VALUES ('" + data["decoded"]["payment_hash"] + "','" + str(-int(data["decoded"]["num_satoshis"])) + "','" + rows[0][0] + "','1','" + request.headers['Grpc-Metadata-macaroon'] + "','" + data["decoded"]["description"] + "')") + con.commit() + cur.close() + + + con = db_connect() + cur = con.cursor() + cur.execute("select * from apipayments WHERE payhash = '" + data["decoded"]["payment_hash"] + "'") + rowss = cur.fetchall() + cur.close() + + + + data["decoded"]["num_satoshis"] + + + lastamt = rows[0][1].split(",") + newamt = int(lastamt[-1]) - int(data["decoded"]["num_satoshis"]) + updamt = rows[0][1] + "," + str(newamt) + thetime = time.time() + transactions = rows[0][2] + "!" + rowss[0][5] + "," + str(thetime) + "," + str(rowss[0][1]) + "," + str(newamt) + + con = db_connect() + cur = con.cursor() + + + cur.execute("UPDATE wallets SET balance = '" + updamt + "', transactions = '" + transactions + "' WHERE hash = '" + rows[0][0] + "'") + con.commit() + cur.close() + + + + return jsonify({"PAID": "TRUE"}), 200 + else: + return jsonify({"ERROR": "BAD AUTH"}), 200 + return jsonify({"ERROR": "NO PAY REQ"}), 200 + + return jsonify({"ERROR": "MUST BE JSON"}), 200 + + + +@app.route('/v1/invoice/', methods=['GET']) +def api_checkinvoice(payhash): + + if request.headers['Content-Type'] == 'application/json': + + print(request.headers["Grpc-Metadata-macaroon"]) + con = db_connect() + cur = con.cursor() + cur.execute("select * from apipayments WHERE payhash = '" + payhash + "'") + rows = cur.fetchall() + cur.close() + print(payhash) + if request.headers["Grpc-Metadata-macaroon"] == rows[0][4]: + + if rows[0][3] == "0": + print(rows[0][3]) + print("did it work?") + headers = {'Authorization': 'Basic %s' % INVOICE_KEY} + r = requests.post(url = API_ENDPOINT + "/invoicestatus/" + payhash, headers = headers) + data = r.json() + print(r.json()) + print("no") + if data == "": + return jsonify({"PAID": "FALSE"}), 400 + else: + con = db_connect() + cur = con.cursor() + + cur.execute("select * from wallets WHERE hash = '" + rows[0][2] + "'") + + rowsss = cur.fetchall() + con.commit() + cur.close() + + lastamt = rowsss[0][1].split(",") + newamt = int(lastamt[-1]) + int(rows[0][1]) + updamt = rowsss[0][1] + "," + str(newamt) + + thetime = time.time() + transactions = rowsss[0][2] + "!" + rows[0][5] + "," + str(thetime) + "," + str(rows[0][1]) + "," + str(newamt) + + con = db_connect() + cur = con.cursor() + + cur.execute("UPDATE wallets SET balance = '" + updamt + "', transactions = '" + transactions + "' WHERE hash = '" + rows[0][2] + "'") + + con.commit() + cur.close() + + con = db_connect() + cur = con.cursor() + + cur.execute("UPDATE apipayments SET paid = '1' WHERE payhash = '" + payhash + "'") + + con.commit() + cur.close() + return jsonify({"PAID": "TRUE"}), 200 + else: + return jsonify({"PAID": "TRUE"}), 200 + else: + return jsonify({"ERROR": "WRONG KEY"}), 400 + + else: + return jsonify({"ERROR": "NEEDS TO BE JSON"}), 400 + + + + + +if __name__ == '__main__': + app.run(debug=True, host= '0.0.0.0') \ No newline at end of file diff --git a/LNbits/templates/deletewallet.html b/LNbits/templates/deletewallet.html new file mode 100644 index 00000000..058ef540 --- /dev/null +++ b/LNbits/templates/deletewallet.html @@ -0,0 +1,199 @@ + + + + + LNBits Wallet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + + +
+ +
+

+ Wallet + Control panel +

+ +
+ + +
+

Wallet Deleted! + + +

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LNbits/templates/index.html b/LNbits/templates/index.html new file mode 100644 index 00000000..5867cbfe --- /dev/null +++ b/LNbits/templates/index.html @@ -0,0 +1,249 @@ + + + + + LNBits Wallet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + + +
+ +
+ + + +

+
+ +

Warning - Wallet is still in BETA and very, very #reckless, please be careful with your funds!

+ +
+
+ + +
+ +
+
+ +
+
+

+ + free and open-source lightning wallet +

+

+ LNbits is a simple, free and open-source lightning-network wallet for bits and bobs. You can run it on your own server, or use this one. +

+The wallet can be used in a variety of ways, an instant wallet for LN demonstrations, a fallback wallet for the LNURL scheme, an accounts system to mitigate the risk of exposing applications to your full balance. +

+The wallet can run on top of LND, lntxbot, paywall, opennode +

+Please note that although one of the aims of this wallet is to mitigate exposure of all your funds, it’s still very BETA and may in fact do the opposite! +
https://github.com/arcbtc/lnbits

+
+ +
+ +
+ + + +
+ +
+
+

+ + Make a wallet +

+
+ +
+ +
+ +
+ +
+ + + +
+ + + + + + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LNbits/templates/lnurlwallet.html b/LNbits/templates/lnurlwallet.html new file mode 100644 index 00000000..194f6964 --- /dev/null +++ b/LNbits/templates/lnurlwallet.html @@ -0,0 +1,701 @@ + + + + + LNBits Wallet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + + +
+ +
+

+ Wallet + Control panel
+

+ +
+ + +
+ + + +
+
+
+
+ + + +
+
+ + + + +
+
+
+
+

Transactions

+ +
+
+ + + + + + + + + + + +
Memodateamount
+
+
+
+
+ +
+ + + +
+
+
+
+ +
+
+
+ +
+ + +
+ + +
+ + + +
+ +
+
+
+
+
+ +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LNbits/templates/wallet.html b/LNbits/templates/wallet.html new file mode 100644 index 00000000..bfb0b19a --- /dev/null +++ b/LNbits/templates/wallet.html @@ -0,0 +1,717 @@ + + + + + LNBits Wallet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + + +
+ +
+

+ Wallet + Control panel
+

+ + + + +
+ + +
+ + + +
+
+
+
+ + + +
+
+ + + + +
+
+
+
+

Transactions

+ +
+
+ + + + + + + + + + + +
Memodateamount
+
+
+
+
+ +
+ + + +
+
+
+
+ +
+
+
+ +
+ + +
+ + +
+ + + +
+ +
+
+
+
+
+ +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file