lnbits-legend/LNbits/__init__.py

637 lines
19 KiB
Python
Raw Normal View History

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/<payhash>", 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")