Add files via upload
This commit is contained in:
parent
5f3030401d
commit
750dd7dfbf
BIN
LNbits/__pycache__/lnurlreq.cpython-37.pyc
Normal file
BIN
LNbits/__pycache__/lnurlreq.cpython-37.pyc
Normal file
Binary file not shown.
BIN
LNbits/database.sqlite3
Normal file
BIN
LNbits/database.sqlite3
Normal file
Binary file not shown.
511
LNbits/server.py
Normal file
511
LNbits/server.py
Normal file
|
@ -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/<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')
|
199
LNbits/templates/deletewallet.html
Normal file
199
LNbits/templates/deletewallet.html
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>LNBits Wallet</title>
|
||||||
|
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
||||||
|
<!-- Bootstrap 3.3.2 -->
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
|
||||||
|
<!-- FontAwesome 4.3.0 -->
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- Ionicons 2.0.0 -->
|
||||||
|
<link href="http://code.ionicframework.com/ionicons/2.0.0/css/ionicons.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
|
||||||
|
<!-- Theme style -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='dist/css/AdminLTE.min.css') }}">
|
||||||
|
<!-- AdminLTE Skins. Choose a skin from the css/skins
|
||||||
|
folder instead of downloading all of them to reduce the load. -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='dist/css/skins/_all-skins.min.css') }}">
|
||||||
|
<!-- iCheck -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/iCheck/flat/blue.css') }}">
|
||||||
|
<!-- Morris chart -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/morris/morris.css') }}">
|
||||||
|
<!-- jvectormap -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-1.2.2.css') }}">
|
||||||
|
<!-- Date Picker -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/datepicker/datepicker3.css') }}">
|
||||||
|
<!-- Daterange picker -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/daterangepicker/daterangepicker-bs3.css') }}">
|
||||||
|
<!-- bootstrap wysihtml5 - text editor -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css') }}">
|
||||||
|
|
||||||
|
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.small-box>.small-box-footer {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="skin-blue">
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<header class="main-header">
|
||||||
|
<!-- Logo -->
|
||||||
|
<a href="index2.html" class="logo"><b>LN</b>bits</a></a>
|
||||||
|
<!-- Header Navbar: style can be found in header.less -->
|
||||||
|
<nav class="navbar navbar-static-top" role="navigation">
|
||||||
|
<!-- Sidebar toggle button-->
|
||||||
|
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
|
||||||
|
<span class="sr-only">Toggle navigation</span>
|
||||||
|
</a>
|
||||||
|
<div class="navbar-custom-menu">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<!-- Messages: style can be found in dropdown.less-->
|
||||||
|
<li class="dropdown messages-menu">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<!-- Left side column. contains the logo and sidebar -->
|
||||||
|
<aside class="main-sidebar">
|
||||||
|
<!-- sidebar: style can be found in sidebar.less -->
|
||||||
|
<section class="sidebar">
|
||||||
|
<!-- Sidebar user panel -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- /.search form -->
|
||||||
|
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||||
|
<ul class="sidebar-menu">
|
||||||
|
<li class="header">MAIN NAVIGATION</li>
|
||||||
|
<li class="active treeview">
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-th"></i> <span>Wallets</span>
|
||||||
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
|
</a>
|
||||||
|
<ul class="treeview-menu">
|
||||||
|
<li class="active"><a href="wallet?wal={{thewal}}" >
|
||||||
|
<i class="fa fa-circle-o"></i> {{ walnme }}</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- /.sidebar -->
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Right side column. Contains the navbar and content of the page -->
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<!-- Content Header (Page header) -->
|
||||||
|
<section class="content-header">
|
||||||
|
<h1>
|
||||||
|
Wallet
|
||||||
|
<small>Control panel</small>
|
||||||
|
</h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#"><i class="fa fa-dashboard"></i> Home</a></li>
|
||||||
|
<li class="active">Wallets</li>
|
||||||
|
<li href="wallet?wal={{thewal}}" class="active">{{ walnme }}</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<section class="content">
|
||||||
|
<h1>Wallet Deleted!
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div><!-- /.content-wrapper -->
|
||||||
|
<footer class="main-footer">
|
||||||
|
<div class="pull-right hidden-xs">
|
||||||
|
<b>BETA</b>
|
||||||
|
</div>
|
||||||
|
<strong>Learn more about FOSSAW <a href="https://github.com/arcbtc/FOSSAW">https://github.com/arcbtc/FOSSAW</a>.</strong>
|
||||||
|
</footer>
|
||||||
|
</div><!-- ./wrapper -->
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css') }}">
|
||||||
|
|
||||||
|
<!-- jQuery 2.1.3 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jQuery/jQuery-2.1.3.min.js') }}"></script>
|
||||||
|
<!-- jQuery UI 1.11.2 -->
|
||||||
|
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.min.js" type="text/javascript"></script>
|
||||||
|
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
|
||||||
|
<script>
|
||||||
|
$.widget.bridge('uibutton', $.ui.button);
|
||||||
|
</script>
|
||||||
|
<!-- Bootstrap 3.3.2 JS -->
|
||||||
|
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Morris.js charts -->
|
||||||
|
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/morris/morris.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Sparkline -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/sparkline/jquery.sparkline.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- jvectormap -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-1.2.2.min.js') }}" type="text/javascript"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-world-mill-en.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- jQuery Knob Chart -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/knob/jquery.knob.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- daterangepicker -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/daterangepicker/daterangepicker.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- datepicker -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/datepicker/bootstrap-datepicker.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Bootstrap WYSIHTML5 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- iCheck -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/iCheck/icheck.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Slimscroll -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/slimScroll/jquery.slimscroll.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- FastClick -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/fastclick/fastclick.min.js') }}"></script>
|
||||||
|
<!-- AdminLTE App -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/app.min.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<!-- AdminLTE dashboard demo (This is only for demo purposes) -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/pages/dashboard.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<!-- AdminLTE for demo purposes -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/demo.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
window.location.href = "wallet?usr={{ theid }}&wal={{ thewal }}"; //will redirect to your blog page (an ex: blog.html)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
249
LNbits/templates/index.html
Normal file
249
LNbits/templates/index.html
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>LNBits Wallet</title>
|
||||||
|
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
||||||
|
<!-- Bootstrap 3.3.2 -->
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
|
||||||
|
<!-- FontAwesome 4.3.0 -->
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- Ionicons 2.0.0 -->
|
||||||
|
<link href="http://code.ionicframework.com/ionicons/2.0.0/css/ionicons.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
|
||||||
|
<!-- Theme style -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='dist/css/AdminLTE.min.css') }}">
|
||||||
|
<!-- AdminLTE Skins. Choose a skin from the css/skins
|
||||||
|
folder instead of downloading all of them to reduce the load. -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='dist/css/skins/_all-skins.min.css') }}">
|
||||||
|
<!-- iCheck -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/iCheck/flat/blue.css') }}">
|
||||||
|
<!-- Morris chart -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/morris/morris.css') }}">
|
||||||
|
<!-- jvectormap -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-1.2.2.css') }}">
|
||||||
|
<!-- Date Picker -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/datepicker/datepicker3.css') }}">
|
||||||
|
<!-- Daterange picker -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/daterangepicker/daterangepicker-bs3.css') }}">
|
||||||
|
<!-- bootstrap wysihtml5 - text editor -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css') }}">
|
||||||
|
|
||||||
|
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.small-box>.small-box-footer {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="skin-blue">
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<header class="main-header">
|
||||||
|
<!-- Logo -->
|
||||||
|
<a href="index.html" class="logo"><b>LN</b>bits</a>
|
||||||
|
<!-- Header Navbar: style can be found in header.less -->
|
||||||
|
<nav class="navbar navbar-static-top" role="navigation">
|
||||||
|
<!-- Sidebar toggle button-->
|
||||||
|
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
|
||||||
|
<span class="sr-only">Toggle navigation</span>
|
||||||
|
</a>
|
||||||
|
<div class="navbar-custom-menu">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<!-- Messages: style can be found in dropdown.less-->
|
||||||
|
<li class="dropdown messages-menu">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<!-- Left side column. contains the logo and sidebar -->
|
||||||
|
<aside class="main-sidebar">
|
||||||
|
<!-- sidebar: style can be found in sidebar.less -->
|
||||||
|
<section class="sidebar">
|
||||||
|
<!-- Sidebar user panel -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- /.search form -->
|
||||||
|
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||||
|
<ul class="sidebar-menu">
|
||||||
|
<li class="header">MAIN NAVIGATION</li>
|
||||||
|
|
||||||
|
<li><a href="../documentation/index.html"><i class="fa fa-book"></i> Home</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- /.sidebar -->
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Right side column. Contains the navbar and content of the page -->
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<!-- Content Header (Page header) -->
|
||||||
|
<section class="content-header">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="/index.html"><i class="fa fa-dashboard"></i> Home</a></li>
|
||||||
|
</ol><br/><br/>
|
||||||
|
<div class="alert alert-danger alert-dismissable">
|
||||||
|
|
||||||
|
<h4>Warning - Wallet is still in BETA and very, very #reckless, please be careful with your funds!</h4>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<section class="content">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<!-- Default box -->
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header">
|
||||||
|
<h1>
|
||||||
|
<a href="index.html" class="logo"><b>LN</b>bits</a>
|
||||||
|
<small>free and open-source lightning wallet</small>
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
<br/><br/>
|
||||||
|
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.
|
||||||
|
<br/><br/>
|
||||||
|
The wallet can run on top of LND, lntxbot, paywall, opennode
|
||||||
|
<br/><br/>
|
||||||
|
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!
|
||||||
|
<br/> <a href="https://github.com/arcbtc/FOSSAW">https://github.com/arcbtc/lnbits</a> </p>
|
||||||
|
</div><!-- /.box-body -->
|
||||||
|
|
||||||
|
</div><!-- /.box -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<!-- Default box -->
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header">
|
||||||
|
<h1>
|
||||||
|
|
||||||
|
<small>Make a wallet</small>
|
||||||
|
</h1>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" id="walname" placeholder="Name your LNBits wallet" required>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-primary" onclick="newwallet()">Submit</button>
|
||||||
|
</div><!-- /.box-body -->
|
||||||
|
|
||||||
|
</div><!-- /.box -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</section><!-- /.content -->
|
||||||
|
|
||||||
|
</div><!-- /.content-wrapper -->
|
||||||
|
|
||||||
|
<footer class="main-footer">
|
||||||
|
<div class="pull-right hidden-xs">
|
||||||
|
<b>BETA</b>
|
||||||
|
</div>
|
||||||
|
<strong>Learn more about LNbits <a href="https://github.com/arcbtc/FOSSAW">https://github.com/arcbtc/lnbits</a></strong>
|
||||||
|
</footer>
|
||||||
|
</div><!-- ./wrapper -->
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css') }}">
|
||||||
|
|
||||||
|
<!-- jQuery 2.1.3 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jQuery/jQuery-2.1.3.min.js') }}"></script>
|
||||||
|
<!-- jQuery UI 1.11.2 -->
|
||||||
|
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.min.js" type="text/javascript"></script>
|
||||||
|
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
|
||||||
|
<script>
|
||||||
|
$.widget.bridge('uibutton', $.ui.button);
|
||||||
|
</script>
|
||||||
|
<!-- Bootstrap 3.3.2 JS -->
|
||||||
|
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Morris.js charts -->
|
||||||
|
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/morris/morris.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Sparkline -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/sparkline/jquery.sparkline.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- jvectormap -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-1.2.2.min.js') }}" type="text/javascript"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-world-mill-en.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- jQuery Knob Chart -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/knob/jquery.knob.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- daterangepicker -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/daterangepicker/daterangepicker.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- datepicker -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/datepicker/bootstrap-datepicker.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Bootstrap WYSIHTML5 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- iCheck -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/iCheck/icheck.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Slimscroll -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/slimScroll/jquery.slimscroll.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- FastClick -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/fastclick/fastclick.min.js') }}"></script>
|
||||||
|
<!-- AdminLTE App -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/app.min.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<!-- AdminLTE dashboard demo (This is only for demo purposes) -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/pages/dashboard.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<!-- AdminLTE for demo purposes -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/demo.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function makeid(length) {
|
||||||
|
var result = '';
|
||||||
|
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
var charactersLength = characters.length;
|
||||||
|
for ( var i = 0; i < length; i++ ) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newwallet() {
|
||||||
|
walname = document.getElementById("walname").value;
|
||||||
|
window.location.href = "wallet?usr=" + makeid(40) + "&wal=" + makeid(40) + "&nme=" + walname;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
701
LNbits/templates/lnurlwallet.html
Normal file
701
LNbits/templates/lnurlwallet.html
Normal file
|
@ -0,0 +1,701 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>LNBits Wallet</title>
|
||||||
|
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
||||||
|
<!-- Bootstrap 3.3.2 -->
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
|
||||||
|
<!-- FontAwesome 4.3.0 -->
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- Ionicons 2.0.0 -->
|
||||||
|
<link href="http://code.ionicframework.com/ionicons/2.0.0/css/ionicons.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
|
||||||
|
<!-- Theme style -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='dist/css/AdminLTE.min.css') }}">
|
||||||
|
<!-- AdminLTE Skins. Choose a skin from the css/skins
|
||||||
|
folder instead of downloading all of them to reduce the load. -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='dist/css/skins/_all-skins.min.css') }}">
|
||||||
|
<!-- iCheck -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/iCheck/flat/blue.css') }}">
|
||||||
|
<!-- Morris chart -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/morris/morris.css') }}">
|
||||||
|
<!-- jvectormap -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-1.2.2.css') }}">
|
||||||
|
<!-- Date Picker -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/datepicker/datepicker3.css') }}">
|
||||||
|
<!-- Daterange picker -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/daterangepicker/daterangepicker-bs3.css') }}">
|
||||||
|
<!-- bootstrap wysihtml5 - text editor -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css') }}">
|
||||||
|
|
||||||
|
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.small-box>.small-box-footer {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#loadingMessage {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#output {
|
||||||
|
margin-top: 20px;
|
||||||
|
background: #eee;
|
||||||
|
padding: 10px;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#output div {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#noQRFound {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="skin-blue">
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<header class="main-header">
|
||||||
|
<!-- Logo -->
|
||||||
|
<a href="/" class="logo"><b>LN</b>bits</a></a>
|
||||||
|
<!-- Header Navbar: style can be found in header.less -->
|
||||||
|
<nav class="navbar navbar-static-top" role="navigation">
|
||||||
|
<!-- Sidebar toggle button-->
|
||||||
|
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
|
||||||
|
<span class="sr-only">Toggle navigation</span>
|
||||||
|
</a>
|
||||||
|
<div class="navbar-custom-menu">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<!-- Messages: style can be found in dropdown.less-->
|
||||||
|
<li class="dropdown messages-menu">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<!-- Left side column. contains the logo and sidebar -->
|
||||||
|
<aside class="main-sidebar">
|
||||||
|
<!-- sidebar: style can be found in sidebar.less -->
|
||||||
|
<section class="sidebar">
|
||||||
|
<!-- Sidebar user panel -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- /.search form -->
|
||||||
|
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||||
|
<ul class="sidebar-menu">
|
||||||
|
<li class="header">MAIN NAVIGATIONs</li>
|
||||||
|
<li class="active treeview">
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-bitcoin"></i> <span>Wallets</span>
|
||||||
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
|
</a>
|
||||||
|
<ul class="treeview-menu">
|
||||||
|
|
||||||
|
|
||||||
|
{% if len > 1 %}
|
||||||
|
{%for i in range(0, len)%}
|
||||||
|
<li><a href="wallet?wal={{ thearr[i][0] }}&usr={{ thearr[i][4] }}" ><i class="fa fa-bolt"></i> {{ thearr[i][3] }}</a></li>
|
||||||
|
{%endfor%}
|
||||||
|
{% else %}
|
||||||
|
<li><a href="wallet?wal={{ thewal }}&usr={{ theid }}" ><i class="fa fa-bolt"></i> {{ walnme }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<li ><a onclick="sidebarmake()">Add a wallet +</a></li>
|
||||||
|
<div id="sidebarmake"></div>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="treeview">
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-th"></i> <span>Extensions</span> <small class="label pull-right bg-green">coming soon</small>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- /.sidebar -->
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Right side column. Contains the navbar and content of the page -->
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<!-- Content Header (Page header) -->
|
||||||
|
<section class="content-header">
|
||||||
|
<h1>
|
||||||
|
Wallet
|
||||||
|
<small>Control panel <div id="wonga"></div></small>
|
||||||
|
</h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#"><i class="fa fa-dashboard"></i> Home</a></li>
|
||||||
|
<li class="active">Wallets</li>
|
||||||
|
<li href="wallet?wal={{thewal}}" class="active">{{ walnme }}</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<section class="content">
|
||||||
|
<!-- Small boxes (Stat box) -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<!-- small box -->
|
||||||
|
<a href="#" class="small-box-footer">
|
||||||
|
<div class="small-box bg-aqua">
|
||||||
|
<div class="inner">
|
||||||
|
<h3><b>{{ walbal }} sats</b></h3>
|
||||||
|
<h3>{{ walnme }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="icon">
|
||||||
|
<i class="ion ion-flash"></i>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div><!-- ./col -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div><!-- /.row -->
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3"> <button onclick="sendfundsinput()" class="btn btn-block btn-primary btn-lg">Send</button></div>
|
||||||
|
<div class="col-sm-3"> <button onclick="receive()" class="btn btn-block btn-primary btn-lg">Receive</button></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="receive"></div>
|
||||||
|
<div id="sendfunds"></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header">
|
||||||
|
<h3 class="box-title">Transactions <b id="demo"></b></h3>
|
||||||
|
|
||||||
|
</div><!-- /.box-header -->
|
||||||
|
<div class="box-body no-padding">
|
||||||
|
<table id="pagnation" class="table table-bordered table-striped">
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Memo</th>
|
||||||
|
<th style='width: 20%'>date</th>
|
||||||
|
<th style='width: 20%'>amount</th>
|
||||||
|
</tr>
|
||||||
|
<tbody id="transactions">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</tbody></table>
|
||||||
|
</div><!-- /.box-body -->
|
||||||
|
</div><!-- /.box -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="satschart"></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="box box-solid">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
|
||||||
|
</div><!-- /.box-header -->
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="box-group" id="accordion">
|
||||||
|
<!-- we are adding the .panel class so bootstrap.js collapse plugin detects it -->
|
||||||
|
<div class="panel box box-primary">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h4 class="box-title">
|
||||||
|
<a data-toggle="collapse" data-parent="#accordion" href="#collapseThree" class="collapsed" aria-expanded="false">
|
||||||
|
Wallet "{{ walnme }}" API info
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div id="collapseThree" class="panel-collapse collapse" aria-expanded="false">
|
||||||
|
<div class="box-body" style='word-wrap: break-word;'>
|
||||||
|
<b>Admin key: </b><i>{{ adminkey }}</i><br/>
|
||||||
|
<b>Invoice/Read key: </b><i>{{ inkey }}</i><br/>
|
||||||
|
Generate an invoice:<br/><code>POST /v1/invoices</code><br/>Header <code>{"Grpc-Metadata-macaroon": "<i>{{ inkey }}</i>"}</code><br/>
|
||||||
|
Body <code>{"value": "200","memo": "beer"} </code><br/>
|
||||||
|
Returns <code>{"pay_req": string,"pay_id": string} </code><br/>
|
||||||
|
*payment will not register in the wallet until the "check invoice" endpoint is used<br/><br/>
|
||||||
|
|
||||||
|
Check invoice:<br/>
|
||||||
|
Check an invoice:<br/><code>GET /v1/invoice/*payment_hash*</code><br/>Header <code>{"Grpc-Metadata-macaroon": "<i>{{ inkey }}</i>"}</code><br/>
|
||||||
|
|
||||||
|
Returns <code>{"PAID": "TRUE"}/{"PAID": "FALSE"} </code><br/>
|
||||||
|
*if using LNTXBOT return will hang until paid<br/><br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="panel box box-danger">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h4 class="box-title">
|
||||||
|
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" class="collapsed" aria-expanded="false">
|
||||||
|
Delete wallet
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div id="collapseTwo" class="panel-collapse collapse" aria-expanded="false">
|
||||||
|
<div class="box-body">
|
||||||
|
|
||||||
|
This whole wallet will be deleted, the funds will be UNRECOVERABLE <br/><br/><button class="btn btn-danger" onclick="deletewallet()">Delete wallet</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div><!-- /.box-body -->
|
||||||
|
</div><!-- /.box -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section><!-- /.content -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div><!-- /.content-wrapper -->
|
||||||
|
<footer class="main-footer">
|
||||||
|
<div class="pull-right hidden-xs">
|
||||||
|
<b>BETA</b>
|
||||||
|
</div>
|
||||||
|
<strong>Learn more about LNbits <a href="https://github.com/arcbtc/FOSSAW">https://github.com/arcbtc/lnbits</a>.</strong>
|
||||||
|
</footer>
|
||||||
|
</div><!-- ./wrapper -->
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css') }}">
|
||||||
|
|
||||||
|
<!-- jQuery 2.1.3 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jQuery/jQuery-2.1.3.min.js') }}"></script>
|
||||||
|
<!-- jQuery UI 1.11.2 -->
|
||||||
|
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.min.js" type="text/javascript"></script>
|
||||||
|
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
|
||||||
|
<script>
|
||||||
|
$.widget.bridge('uibutton', $.ui.button);
|
||||||
|
</script>
|
||||||
|
<!-- Bootstrap 3.3.2 JS -->
|
||||||
|
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Morris.js charts -->
|
||||||
|
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/morris/morris.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Sparkline -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/sparkline/jquery.sparkline.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- jvectormap -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-1.2.2.min.js') }}" type="text/javascript"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-world-mill-en.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- jQuery Knob Chart -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/knob/jquery.knob.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- daterangepicker -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/daterangepicker/daterangepicker.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- datepicker -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/datepicker/bootstrap-datepicker.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Bootstrap WYSIHTML5 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- iCheck -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/iCheck/icheck.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Slimscroll -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/slimScroll/jquery.slimscroll.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- FastClick -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/fastclick/fastclick.min.js') }}"></script>
|
||||||
|
<!-- AdminLTE App -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/app.min.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<!-- AdminLTE dashboard demo (This is only for demo purposes) -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/pages/dashboard.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<!-- AdminLTE for demo purposes -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/demo.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='plugins/datatables/jquery.dataTables.js') }}" type="text/javascript"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/datatables/dataTables.bootstrap.js') }}" type="text/javascript"></script>
|
||||||
|
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jscam/JS.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jscam/qrcode.min.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='plugins/bolt11/decoder.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='plugins/bolt11/utils.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
window.location.href = "wallet?wal=" + "{{thewal}}" + "&usr=" + "{{theid}}";
|
||||||
|
|
||||||
|
|
||||||
|
var inmacaroon = "{{ inkey }}";
|
||||||
|
var adminmacaroon = "{{ inkey }}";
|
||||||
|
var thehash = "";
|
||||||
|
var theinvoice = "";
|
||||||
|
var outamount = "";
|
||||||
|
var outmemo = "";
|
||||||
|
|
||||||
|
|
||||||
|
//API CALLS
|
||||||
|
|
||||||
|
function postAjax(url, data, thekey, success) {
|
||||||
|
var params = typeof data == 'string' ? data : Object.keys(data).map(
|
||||||
|
function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) }).join('&');
|
||||||
|
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
xhr.open('POST', url);
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState>3 && xhr.status==200) { success(xhr.responseText); }
|
||||||
|
};
|
||||||
|
xhr.setRequestHeader('Grpc-Metadata-macaroon', thekey);
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
xhr.send(params);
|
||||||
|
return xhr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function getAjax(url, thekey,success) {
|
||||||
|
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
xhr.open('GET', url, true);
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState>3 && xhr.status==200) { success(xhr.responseText); }
|
||||||
|
};
|
||||||
|
xhr.setRequestHeader('Grpc-Metadata-macaroon', thekey);
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
xhr.send();
|
||||||
|
return xhr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendfundsinput(){
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<br/><br/><div class='row'><div class='col-md-4'>" +
|
||||||
|
"<textarea id='pasteinvoice' class='form-control' rows='3' placeholder='Paste an invoice'></textarea></div></div>" +
|
||||||
|
"<br/><div class='row'><div class='col-md-4'><button type='submit' onclick='sendfundspaste()' class='btn btn-primary'>" +
|
||||||
|
"Submit</button><button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='scanQRsend()'>" +
|
||||||
|
"Use camera to scan an invoice</button></div></div><br/><br/>";
|
||||||
|
document.getElementById("receive").innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendfundspaste(){
|
||||||
|
invoice = document.getElementById("pasteinvoice").value;
|
||||||
|
theinvoice = decode(invoice);
|
||||||
|
outmemo = theinvoice.data.tags[1].value;
|
||||||
|
outamount = Number(theinvoice.human_readable_part.amount) /1000;
|
||||||
|
if (outamount > Number("{{ walbal }}")){
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<div class='row'><div class='col-md-6'>"+
|
||||||
|
"<h3><b style='color:red;'>Not enough funds!</b></h3>" +
|
||||||
|
"<button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='cancelsend()'>Continue</button>"+
|
||||||
|
"</br/></br/></div></div>";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<div class='row'><div class='col-md-6'>"+
|
||||||
|
"<h3><b>Invoice details</b></br/>Amount: " + outamount + "<br/>Memo: " + outmemo + "</h3>" +
|
||||||
|
"<h4 style='word-wrap: break-word;'>" + invoice + "</h4>"+
|
||||||
|
"<button type='submit' class='btn btn-primary' onclick='sendfunds(" + JSON.stringify(invoice) + ")'>Send funds</button>"+
|
||||||
|
"<button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='cancelsend()'>Cancel payment</button>"+
|
||||||
|
"</br/></br/></div></div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function receive() {
|
||||||
|
document.getElementById("receive").innerHTML = "<br/><div class='row'><div id='QRCODE'>" +
|
||||||
|
"<div class='col-sm-2'><input type='number' class='form-control' id='amount' placeholder='Amount' max='1000000' required></div>" +
|
||||||
|
"<div class='col-sm-2'><input type='text' class='form-control' id='memo' placeholder='Memo' required></div>" +
|
||||||
|
"<div class='col-sm-2'><input type='button' id='getinvoice' onclick='received()' class='btn btn-primary' value='Send Ajax request' /></div>" +
|
||||||
|
"</div></div><br/>";
|
||||||
|
document.getElementById("sendfunds").innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function received(){
|
||||||
|
memo = document.getElementById("memo").value;
|
||||||
|
amount = document.getElementById("amount").value;
|
||||||
|
postAjax('/v1/invoices', JSON.stringify({'value' : amount, 'memo' : memo}), '{{ inkey }}', function(data){
|
||||||
|
theinvoice = JSON.parse(data).pay_req;
|
||||||
|
thehash = JSON.parse(data).payment_hash;
|
||||||
|
document.getElementById("QRCODE").innerHTML = "<div class='col-md-4'><div class='box'><div class='box-header'>" +
|
||||||
|
"<center><a href='lightning:" + theinvoice + "'><div id='qrcode'></div></a>" +
|
||||||
|
"<p style='word-wrap: break-word;'>" + theinvoice + "</p></div></div></div></center>";
|
||||||
|
|
||||||
|
new QRCode(document.getElementById("qrcode"), {
|
||||||
|
text: theinvoice,
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
colorDark : "#000000",
|
||||||
|
colorLight : "#ffffff",
|
||||||
|
correctLevel : QRCode.CorrectLevel.M
|
||||||
|
});
|
||||||
|
getAjax('/v1/invoice/'+ thehash, '{{ inkey }}', function(datab){
|
||||||
|
console.log(JSON.parse(datab).PAID);
|
||||||
|
if (JSON.parse(datab).PAID == 'TRUE'){
|
||||||
|
window.location.href = "wallet?wal=" + "{{thewal}}" + "&usr=" + "{{theid}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function cancelsend(){
|
||||||
|
window.location.href = "wallet?wal=" + "{{thewal}}" + "&usr=" + "{{theid}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendfunds(invoice){
|
||||||
|
var url = '/v1/channels/transactions';
|
||||||
|
postAjax(url, JSON.stringify({'payment_request' : invoice}), '{{ adminkey }}', function(data){
|
||||||
|
thehash = JSON.parse(data).payment_hash;
|
||||||
|
console.log(JSON.parse(data));
|
||||||
|
if (JSON.parse(data).PAID == 'TRUE'){
|
||||||
|
window.location.href = "wallet?wal=" + "{{thewal}}" + "&usr=" + "{{theid}}";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function scanQRsend(){
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<br/><br/><div class='row'><div class='col-md-4'>" +
|
||||||
|
"<div id='loadingMessage'>🎥 Unable to access video stream (please make sure you have a webcam enabled)</div>" +
|
||||||
|
"<canvas id='canvas' hidden></canvas><div id='output' hidden><div id='outputMessage'></div>" +
|
||||||
|
"<br/><span id='outputData'></span></div></div></div><button type='submit' class='btn btn-primary' onclick='cancelsend()'>Cancel</button><br/><br/>";
|
||||||
|
var video = document.createElement("video");
|
||||||
|
var canvasElement = document.getElementById("canvas");
|
||||||
|
var canvas = canvasElement.getContext("2d");
|
||||||
|
var loadingMessage = document.getElementById("loadingMessage");
|
||||||
|
var outputContainer = document.getElementById("output");
|
||||||
|
var outputMessage = document.getElementById("outputMessage");
|
||||||
|
var outputData = document.getElementById("outputData");
|
||||||
|
function drawLine(begin, end, color) {
|
||||||
|
canvas.beginPath();
|
||||||
|
canvas.moveTo(begin.x, begin.y);
|
||||||
|
canvas.lineTo(end.x, end.y);
|
||||||
|
canvas.lineWidth = 4;
|
||||||
|
canvas.strokeStyle = color;
|
||||||
|
canvas.stroke();
|
||||||
|
}
|
||||||
|
// Use facingMode: environment to attemt to get the front camera on phones
|
||||||
|
navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
|
||||||
|
video.srcObject = stream;
|
||||||
|
video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
|
||||||
|
video.play();
|
||||||
|
requestAnimationFrame(tick);
|
||||||
|
});
|
||||||
|
function tick() {
|
||||||
|
loadingMessage.innerText = "⌛ Loading video..."
|
||||||
|
if (video.readyState === video.HAVE_ENOUGH_DATA) {
|
||||||
|
loadingMessage.hidden = true;
|
||||||
|
canvasElement.hidden = false;
|
||||||
|
outputContainer.hidden = false;
|
||||||
|
canvasElement.height = video.videoHeight;
|
||||||
|
canvasElement.width = video.videoWidth;
|
||||||
|
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
|
||||||
|
var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
|
||||||
|
var code = jsQR(imageData.data, imageData.width, imageData.height, {
|
||||||
|
inversionAttempts: "dontInvert",
|
||||||
|
});
|
||||||
|
if (code) {
|
||||||
|
drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
|
||||||
|
drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
|
||||||
|
drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
|
||||||
|
drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
|
||||||
|
outputMessage.hidden = true;
|
||||||
|
outputData.parentElement.hidden = false;
|
||||||
|
outputData.innerText = JSON.stringify(code.data);
|
||||||
|
theinvoice = decode(code.data);
|
||||||
|
outmemo = theinvoice.data.tags[1].value;
|
||||||
|
outamount = Number(theinvoice.human_readable_part.amount) /1000;
|
||||||
|
if (outamount > Number("{{ walbal }}")){
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<div class='row'><div class='col-md-6'>"+
|
||||||
|
"<h3><b style='color:red;'>Not enough funds!</b></h3>" +
|
||||||
|
"<button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='cancelsend()'>Continue</button>"+
|
||||||
|
"</br/></br/></div></div>";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<div class='row'><div class='col-md-6'>"+
|
||||||
|
"<h3><b>Invoice details</b></br/>Amount: " + outamount + "<br/>Memo: " + outmemo + "</h3>" +
|
||||||
|
"<h4 style='word-wrap: break-word;'>" + JSON.stringify(code.data) + "</h4>"+
|
||||||
|
"<button type='submit' class='btn btn-primary' onclick='sendfunds(" + JSON.stringify(code.data) + ")'>Send funds</button>"+
|
||||||
|
"<button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='cancelsend()'>Cancel payment</button>"+
|
||||||
|
"</br/></br/></div></div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outputMessage.hidden = false;
|
||||||
|
outputData.parentElement.hidden = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestAnimationFrame(tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function deletewallet(){
|
||||||
|
var urll = "deletewallet?wal={{ thewal }}&usr={{ theid }}";
|
||||||
|
window.location.href = urll;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function sidebarmake(){
|
||||||
|
document.getElementById("sidebarmake").innerHTML = "<li><div class='form-group'>"+
|
||||||
|
"<input style='width:70%;float:left;' type='text' class='form-control' id='walname' placeholder='Name wallet' required>" +
|
||||||
|
"<button style='width:30%;float:left;' type='button' class='btn btn-primary' onclick='newwallet()'>Submit</button>" +
|
||||||
|
"</div></li><br/><br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeid(length) {
|
||||||
|
var result = '';
|
||||||
|
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
var charactersLength = characters.length;
|
||||||
|
for ( var i = 0; i < length; i++ ) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newwallet() {
|
||||||
|
walname = document.getElementById("walname").value;
|
||||||
|
window.location.href = "wallet?usr=" + "{{ theid }}" + "&wal=" + makeid(40) + "&nme=" + walname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var trans = "{{ transactions }}";
|
||||||
|
var transac = trans.substr(1);
|
||||||
|
|
||||||
|
|
||||||
|
//console.log(trans);
|
||||||
|
|
||||||
|
if(transac != ""){
|
||||||
|
var transactions = "";
|
||||||
|
var linechart = [];
|
||||||
|
var tran = transac.split("!");
|
||||||
|
tran.shift();
|
||||||
|
console.log(tran);
|
||||||
|
for (var i = 0; i < tran.length; i++) {
|
||||||
|
rects = tran[i].split(",");
|
||||||
|
rectstime = String(rects[1]).split(".");
|
||||||
|
var datime = convertTimestamp(rectstime[0])
|
||||||
|
|
||||||
|
//Make the transactions table
|
||||||
|
|
||||||
|
transactions += "<tr><td style='width: 50%'>" + rects[0] + "</td><td>" + datime + "</td><td>" + rects[2] + "</td></tr>";
|
||||||
|
|
||||||
|
//Make the line chart
|
||||||
|
|
||||||
|
if (i == 0){
|
||||||
|
linechart.push({y: datime, item1: rects[2]});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
linechart.push({y: datime, item1: rects[3]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById("transactions").innerHTML = transactions;
|
||||||
|
if(linechart[0] != ""){
|
||||||
|
document.getElementById("satschart").innerHTML = "<div class='row'><div class='col-md-6'><div class='box box-info'><div class='box-header'>" +
|
||||||
|
"<h3 class='box-title'>Spending</h3></div><div class='box-body chart-responsive'>" +
|
||||||
|
"<div class='chart' id='line-chart' style='height: 300px;'></div></div></div></div></div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(linechart);
|
||||||
|
var data = linechart
|
||||||
|
var line = new Morris.Line({
|
||||||
|
element: 'line-chart',
|
||||||
|
resize: true,
|
||||||
|
data,
|
||||||
|
xkey: 'y',
|
||||||
|
ykeys: ['item1'],
|
||||||
|
labels: ['Item 1'],
|
||||||
|
lineColors: ['#3c8dbc'],
|
||||||
|
hideHover: 'auto'
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function convertTimestamp(timestamp) {
|
||||||
|
var d = new Date(timestamp * 1000),
|
||||||
|
yyyy = d.getFullYear(),
|
||||||
|
mm = ('0' + (d.getMonth() + 1)).slice(-2),
|
||||||
|
dd = ('0' + d.getDate()).slice(-2),
|
||||||
|
hh = d.getHours(),
|
||||||
|
h = hh,
|
||||||
|
min = ('0' + d.getMinutes()).slice(-2),
|
||||||
|
ampm = 'AM',
|
||||||
|
time;
|
||||||
|
time = yyyy + '-' + mm + '-' + dd + ' ' + h + ':' + min;
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
717
LNbits/templates/wallet.html
Normal file
717
LNbits/templates/wallet.html
Normal file
|
@ -0,0 +1,717 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>LNBits Wallet</title>
|
||||||
|
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
||||||
|
<!-- Bootstrap 3.3.2 -->
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
|
||||||
|
<!-- FontAwesome 4.3.0 -->
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- Ionicons 2.0.0 -->
|
||||||
|
<link href="http://code.ionicframework.com/ionicons/2.0.0/css/ionicons.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
|
||||||
|
<!-- Theme style -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='dist/css/AdminLTE.min.css') }}">
|
||||||
|
<!-- AdminLTE Skins. Choose a skin from the css/skins
|
||||||
|
folder instead of downloading all of them to reduce the load. -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='dist/css/skins/_all-skins.min.css') }}">
|
||||||
|
<!-- iCheck -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/iCheck/flat/blue.css') }}">
|
||||||
|
<!-- Morris chart -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/morris/morris.css') }}">
|
||||||
|
<!-- jvectormap -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-1.2.2.css') }}">
|
||||||
|
<!-- Date Picker -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/datepicker/datepicker3.css') }}">
|
||||||
|
<!-- Daterange picker -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/daterangepicker/daterangepicker-bs3.css') }}">
|
||||||
|
<!-- bootstrap wysihtml5 - text editor -->
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css') }}">
|
||||||
|
|
||||||
|
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.small-box>.small-box-footer {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#loadingMessage {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#output {
|
||||||
|
margin-top: 20px;
|
||||||
|
background: #eee;
|
||||||
|
padding: 10px;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#output div {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#noQRFound {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="skin-blue">
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<header class="main-header">
|
||||||
|
<!-- Logo -->
|
||||||
|
<a href="/" class="logo"><b>LN</b>bits</a></a>
|
||||||
|
<!-- Header Navbar: style can be found in header.less -->
|
||||||
|
<nav class="navbar navbar-static-top" role="navigation">
|
||||||
|
<!-- Sidebar toggle button-->
|
||||||
|
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
|
||||||
|
<span class="sr-only">Toggle navigation</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="navbar-custom-menu">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<!-- Messages: style can be found in dropdown.less-->
|
||||||
|
<!-- Notifications: style can be found in dropdown.less -->
|
||||||
|
<li class="dropdown notifications-menu">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<i class="fa fa-bell-o"></i>
|
||||||
|
<span class="label label-danger">!</span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li class="header"><b>Instant wallet, bookmark to save</b></li>
|
||||||
|
<li>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="navbar-custom-menu">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<!-- Messages: style can be found in dropdown.less-->
|
||||||
|
<li class="dropdown messages-menu">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<!-- Left side column. contains the logo and sidebar -->
|
||||||
|
<aside class="main-sidebar">
|
||||||
|
<!-- sidebar: style can be found in sidebar.less -->
|
||||||
|
<section class="sidebar">
|
||||||
|
<!-- Sidebar user panel -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- /.search form -->
|
||||||
|
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||||
|
<ul class="sidebar-menu">
|
||||||
|
<li class="header">MAIN NAVIGATIONs</li>
|
||||||
|
<li class="active treeview">
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-bitcoin"></i> <span>Wallets</span>
|
||||||
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
|
</a>
|
||||||
|
<ul class="treeview-menu">
|
||||||
|
|
||||||
|
|
||||||
|
{% if len > 1 %}
|
||||||
|
{%for i in range(0, len)%}
|
||||||
|
<li><a href="wallet?wal={{ thearr[i][0] }}&usr={{ thearr[i][4] }}" ><i class="fa fa-bolt"></i> {{ thearr[i][3] }}</a></li>
|
||||||
|
{%endfor%}
|
||||||
|
{% else %}
|
||||||
|
<li><a href="wallet?wal={{ thewal }}&usr={{ theid }}" ><i class="fa fa-bolt"></i> {{ walnme }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<li ><a onclick="sidebarmake()">Add a wallet +</a></li>
|
||||||
|
<div id="sidebarmake"></div>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="treeview">
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-th"></i> <span>Extensions</span> <small class="label pull-right bg-green">coming soon</small>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- /.sidebar -->
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Right side column. Contains the navbar and content of the page -->
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<!-- Content Header (Page header) -->
|
||||||
|
<section class="content-header">
|
||||||
|
<h1>
|
||||||
|
Wallet
|
||||||
|
<small>Control panel <div id="wonga"></div></small>
|
||||||
|
</h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="#"><i class="fa fa-dashboard"></i> Home</a></li>
|
||||||
|
<li class="active">Wallets</li>
|
||||||
|
<li href="wallet?wal={{thewal}}" class="active">{{ walnme }}</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<section class="content">
|
||||||
|
<!-- Small boxes (Stat box) -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<!-- small box -->
|
||||||
|
<a href="#" class="small-box-footer">
|
||||||
|
<div class="small-box bg-aqua">
|
||||||
|
<div class="inner">
|
||||||
|
<h3><b>{{ walbal }} sats</b></h3>
|
||||||
|
<h3>{{ walnme }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="icon">
|
||||||
|
<i class="ion ion-flash"></i>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div><!-- ./col -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div><!-- /.row -->
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3"> <button onclick="sendfundsinput()" class="btn btn-block btn-primary btn-lg">Send</button></div>
|
||||||
|
<div class="col-sm-3"> <button onclick="receive()" class="btn btn-block btn-primary btn-lg">Receive</button></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="receive"></div>
|
||||||
|
<div id="sendfunds"></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header">
|
||||||
|
<h3 class="box-title">Transactions <b id="demo"></b></h3>
|
||||||
|
|
||||||
|
</div><!-- /.box-header -->
|
||||||
|
<div class="box-body no-padding">
|
||||||
|
<table id="pagnation" class="table table-bordered table-striped">
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Memo</th>
|
||||||
|
<th style='width: 20%'>date</th>
|
||||||
|
<th style='width: 20%'>amount</th>
|
||||||
|
</tr>
|
||||||
|
<tbody id="transactions">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</tbody></table>
|
||||||
|
</div><!-- /.box-body -->
|
||||||
|
</div><!-- /.box -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="satschart"></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="box box-solid">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
|
||||||
|
</div><!-- /.box-header -->
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="box-group" id="accordion">
|
||||||
|
<!-- we are adding the .panel class so bootstrap.js collapse plugin detects it -->
|
||||||
|
<div class="panel box box-primary">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h4 class="box-title">
|
||||||
|
<a data-toggle="collapse" data-parent="#accordion" href="#collapseThree" class="collapsed" aria-expanded="false">
|
||||||
|
Wallet "{{ walnme }}" API info
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div id="collapseThree" class="panel-collapse collapse" aria-expanded="false">
|
||||||
|
<div class="box-body" style='word-wrap: break-word;'>
|
||||||
|
<b>Admin key: </b><i>{{ adminkey }}</i><br/>
|
||||||
|
<b>Invoice/Read key: </b><i>{{ inkey }}</i><br/>
|
||||||
|
Generate an invoice:<br/><code>POST /v1/invoices</code><br/>Header <code>{"Grpc-Metadata-macaroon": "<i>{{ inkey }}</i>"}</code><br/>
|
||||||
|
Body <code>{"value": "200","memo": "beer"} </code><br/>
|
||||||
|
Returns <code>{"pay_req": string,"pay_id": string} </code><br/>
|
||||||
|
*payment will not register in the wallet until the "check invoice" endpoint is used<br/><br/>
|
||||||
|
|
||||||
|
Check invoice:<br/>
|
||||||
|
Check an invoice:<br/><code>GET /v1/invoice/*payment_hash*</code><br/>Header <code>{"Grpc-Metadata-macaroon": "<i>{{ inkey }}</i>"}</code><br/>
|
||||||
|
|
||||||
|
Returns <code>{"PAID": "TRUE"}/{"PAID": "FALSE"} </code><br/>
|
||||||
|
*if using LNTXBOT return will hang until paid<br/><br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="panel box box-danger">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h4 class="box-title">
|
||||||
|
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" class="collapsed" aria-expanded="false">
|
||||||
|
Delete wallet
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div id="collapseTwo" class="panel-collapse collapse" aria-expanded="false">
|
||||||
|
<div class="box-body">
|
||||||
|
|
||||||
|
This whole wallet will be deleted, the funds will be UNRECOVERABLE <br/><br/><button class="btn btn-danger" onclick="deletewallet()">Delete wallet</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div><!-- /.box-body -->
|
||||||
|
</div><!-- /.box -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section><!-- /.content -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div><!-- /.content-wrapper -->
|
||||||
|
<footer class="main-footer">
|
||||||
|
<div class="pull-right hidden-xs">
|
||||||
|
<b>BETA</b>
|
||||||
|
</div>
|
||||||
|
<strong><i style="color:red;">WARNING - LNbits is still in BETA! </i>Learn more about LNbits <a href="https://github.com/arcbtc/FOSSAW">https://github.com/arcbtc/lnbits</a>. </strong>
|
||||||
|
</footer>
|
||||||
|
</div><!-- ./wrapper -->
|
||||||
|
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css') }}">
|
||||||
|
|
||||||
|
<!-- jQuery 2.1.3 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jQuery/jQuery-2.1.3.min.js') }}"></script>
|
||||||
|
<!-- jQuery UI 1.11.2 -->
|
||||||
|
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.min.js" type="text/javascript"></script>
|
||||||
|
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
|
||||||
|
<script>
|
||||||
|
$.widget.bridge('uibutton', $.ui.button);
|
||||||
|
</script>
|
||||||
|
<!-- Bootstrap 3.3.2 JS -->
|
||||||
|
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Morris.js charts -->
|
||||||
|
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/morris/morris.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Sparkline -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/sparkline/jquery.sparkline.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- jvectormap -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-1.2.2.min.js') }}" type="text/javascript"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jvectormap/jquery-jvectormap-world-mill-en.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- jQuery Knob Chart -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/knob/jquery.knob.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- daterangepicker -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/daterangepicker/daterangepicker.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- datepicker -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/datepicker/bootstrap-datepicker.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Bootstrap WYSIHTML5 -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- iCheck -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/iCheck/icheck.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- Slimscroll -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/slimScroll/jquery.slimscroll.min.js') }}" type="text/javascript"></script>
|
||||||
|
<!-- FastClick -->
|
||||||
|
<script src="{{ url_for('static', filename='plugins/fastclick/fastclick.min.js') }}"></script>
|
||||||
|
<!-- AdminLTE App -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/app.min.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<!-- AdminLTE dashboard demo (This is only for demo purposes) -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/pages/dashboard.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<!-- AdminLTE for demo purposes -->
|
||||||
|
<script src="{{ url_for('static', filename='dist/js/demo.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='plugins/datatables/jquery.dataTables.js') }}" type="text/javascript"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/datatables/dataTables.bootstrap.js') }}" type="text/javascript"></script>
|
||||||
|
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jscam/JS.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='plugins/jscam/qrcode.min.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='plugins/bolt11/decoder.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='plugins/bolt11/utils.js') }}" type="text/javascript"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var inmacaroon = "{{ inkey }}";
|
||||||
|
var adminmacaroon = "{{ inkey }}";
|
||||||
|
var thehash = "";
|
||||||
|
var theinvoice = "";
|
||||||
|
var outamount = "";
|
||||||
|
var outmemo = "";
|
||||||
|
|
||||||
|
|
||||||
|
//API CALLS
|
||||||
|
|
||||||
|
function postAjax(url, data, thekey, success) {
|
||||||
|
var params = typeof data == 'string' ? data : Object.keys(data).map(
|
||||||
|
function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) }).join('&');
|
||||||
|
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
xhr.open('POST', url);
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState>3 && xhr.status==200) { success(xhr.responseText); }
|
||||||
|
};
|
||||||
|
xhr.setRequestHeader('Grpc-Metadata-macaroon', thekey);
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
xhr.send(params);
|
||||||
|
return xhr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function getAjax(url, thekey,success) {
|
||||||
|
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
xhr.open('GET', url, true);
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState>3 && xhr.status==200) { success(xhr.responseText); }
|
||||||
|
};
|
||||||
|
xhr.setRequestHeader('Grpc-Metadata-macaroon', thekey);
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
xhr.send();
|
||||||
|
return xhr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendfundsinput(){
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<br/><br/><div class='row'><div class='col-md-4'>" +
|
||||||
|
"<textarea id='pasteinvoice' class='form-control' rows='3' placeholder='Paste an invoice'></textarea></div></div>" +
|
||||||
|
"<br/><div class='row'><div class='col-md-4'><button type='submit' onclick='sendfundspaste()' class='btn btn-primary'>" +
|
||||||
|
"Submit</button><button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='scanQRsend()'>" +
|
||||||
|
"Use camera to scan an invoice</button></div></div><br/><br/>";
|
||||||
|
document.getElementById("receive").innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendfundspaste(){
|
||||||
|
invoice = document.getElementById("pasteinvoice").value;
|
||||||
|
theinvoice = decode(invoice);
|
||||||
|
outmemo = theinvoice.data.tags[1].value;
|
||||||
|
outamount = Number(theinvoice.human_readable_part.amount) /1000;
|
||||||
|
if (outamount > Number("{{ walbal }}")){
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<div class='row'><div class='col-md-6'>"+
|
||||||
|
"<h3><b style='color:red;'>Not enough funds!</b></h3>" +
|
||||||
|
"<button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='cancelsend()'>Continue</button>"+
|
||||||
|
"</br/></br/></div></div>";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<div class='row'><div class='col-md-6'>"+
|
||||||
|
"<h3><b>Invoice details</b></br/>Amount: " + outamount + "<br/>Memo: " + outmemo + "</h3>" +
|
||||||
|
"<h4 style='word-wrap: break-word;'>" + invoice + "</h4>"+
|
||||||
|
"<button type='submit' class='btn btn-primary' onclick='sendfunds(" + JSON.stringify(invoice) + ")'>Send funds</button>"+
|
||||||
|
"<button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='cancelsend()'>Cancel payment</button>"+
|
||||||
|
"</br/></br/></div></div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function receive() {
|
||||||
|
document.getElementById("receive").innerHTML = "<br/><div class='row'><div id='QRCODE'>" +
|
||||||
|
"<div class='col-sm-2'><input type='number' class='form-control' id='amount' placeholder='Amount' max='1000000' required></div>" +
|
||||||
|
"<div class='col-sm-2'><input type='text' class='form-control' id='memo' placeholder='Memo' required></div>" +
|
||||||
|
"<div class='col-sm-2'><input type='button' id='getinvoice' onclick='received()' class='btn btn-primary' value='Send Ajax request' /></div>" +
|
||||||
|
"</div></div><br/>";
|
||||||
|
document.getElementById("sendfunds").innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function received(){
|
||||||
|
memo = document.getElementById("memo").value;
|
||||||
|
amount = document.getElementById("amount").value;
|
||||||
|
postAjax('/v1/invoices', JSON.stringify({'value' : amount, 'memo' : memo}), '{{ inkey }}', function(data){
|
||||||
|
theinvoice = JSON.parse(data).pay_req;
|
||||||
|
thehash = JSON.parse(data).payment_hash;
|
||||||
|
document.getElementById("QRCODE").innerHTML = "<div class='col-md-4'><div class='box'><div class='box-header'>" +
|
||||||
|
"<center><a href='lightning:" + theinvoice + "'><div id='qrcode'></div></a>" +
|
||||||
|
"<p style='word-wrap: break-word;'>" + theinvoice + "</p></div></div></div></center>";
|
||||||
|
|
||||||
|
new QRCode(document.getElementById("qrcode"), {
|
||||||
|
text: theinvoice,
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
colorDark : "#000000",
|
||||||
|
colorLight : "#ffffff",
|
||||||
|
correctLevel : QRCode.CorrectLevel.M
|
||||||
|
});
|
||||||
|
getAjax('/v1/invoice/'+ thehash, '{{ inkey }}', function(datab){
|
||||||
|
console.log(JSON.parse(datab).PAID);
|
||||||
|
if (JSON.parse(datab).PAID == 'TRUE'){
|
||||||
|
window.location.href = "wallet?wal=" + "{{thewal}}" + "&usr=" + "{{theid}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function cancelsend(){
|
||||||
|
window.location.href = "wallet?wal=" + "{{thewal}}" + "&usr=" + "{{theid}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendfunds(invoice){
|
||||||
|
var url = '/v1/channels/transactions';
|
||||||
|
postAjax(url, JSON.stringify({'payment_request' : invoice}), '{{ adminkey }}', function(data){
|
||||||
|
thehash = JSON.parse(data).payment_hash;
|
||||||
|
console.log(JSON.parse(data));
|
||||||
|
if (JSON.parse(data).PAID == 'TRUE'){
|
||||||
|
window.location.href = "wallet?wal=" + "{{thewal}}" + "&usr=" + "{{theid}}";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function scanQRsend(){
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<br/><br/><div class='row'><div class='col-md-4'>" +
|
||||||
|
"<div id='loadingMessage'>🎥 Unable to access video stream (please make sure you have a webcam enabled)</div>" +
|
||||||
|
"<canvas id='canvas' hidden></canvas><div id='output' hidden><div id='outputMessage'></div>" +
|
||||||
|
"<br/><span id='outputData'></span></div></div></div><button type='submit' class='btn btn-primary' onclick='cancelsend()'>Cancel</button><br/><br/>";
|
||||||
|
var video = document.createElement("video");
|
||||||
|
var canvasElement = document.getElementById("canvas");
|
||||||
|
var canvas = canvasElement.getContext("2d");
|
||||||
|
var loadingMessage = document.getElementById("loadingMessage");
|
||||||
|
var outputContainer = document.getElementById("output");
|
||||||
|
var outputMessage = document.getElementById("outputMessage");
|
||||||
|
var outputData = document.getElementById("outputData");
|
||||||
|
function drawLine(begin, end, color) {
|
||||||
|
canvas.beginPath();
|
||||||
|
canvas.moveTo(begin.x, begin.y);
|
||||||
|
canvas.lineTo(end.x, end.y);
|
||||||
|
canvas.lineWidth = 4;
|
||||||
|
canvas.strokeStyle = color;
|
||||||
|
canvas.stroke();
|
||||||
|
}
|
||||||
|
// Use facingMode: environment to attemt to get the front camera on phones
|
||||||
|
navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
|
||||||
|
video.srcObject = stream;
|
||||||
|
video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
|
||||||
|
video.play();
|
||||||
|
requestAnimationFrame(tick);
|
||||||
|
});
|
||||||
|
function tick() {
|
||||||
|
loadingMessage.innerText = "⌛ Loading video..."
|
||||||
|
if (video.readyState === video.HAVE_ENOUGH_DATA) {
|
||||||
|
loadingMessage.hidden = true;
|
||||||
|
canvasElement.hidden = false;
|
||||||
|
outputContainer.hidden = false;
|
||||||
|
canvasElement.height = video.videoHeight;
|
||||||
|
canvasElement.width = video.videoWidth;
|
||||||
|
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
|
||||||
|
var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
|
||||||
|
var code = jsQR(imageData.data, imageData.width, imageData.height, {
|
||||||
|
inversionAttempts: "dontInvert",
|
||||||
|
});
|
||||||
|
if (code) {
|
||||||
|
drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
|
||||||
|
drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
|
||||||
|
drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
|
||||||
|
drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
|
||||||
|
outputMessage.hidden = true;
|
||||||
|
outputData.parentElement.hidden = false;
|
||||||
|
outputData.innerText = JSON.stringify(code.data);
|
||||||
|
theinvoice = decode(code.data);
|
||||||
|
outmemo = theinvoice.data.tags[1].value;
|
||||||
|
outamount = Number(theinvoice.human_readable_part.amount) /1000;
|
||||||
|
if (outamount > Number("{{ walbal }}")){
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<div class='row'><div class='col-md-6'>"+
|
||||||
|
"<h3><b style='color:red;'>Not enough funds!</b></h3>" +
|
||||||
|
"<button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='cancelsend()'>Continue</button>"+
|
||||||
|
"</br/></br/></div></div>";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("sendfunds").innerHTML = "<div class='row'><div class='col-md-6'>"+
|
||||||
|
"<h3><b>Invoice details</b></br/>Amount: " + outamount + "<br/>Memo: " + outmemo + "</h3>" +
|
||||||
|
"<h4 style='word-wrap: break-word;'>" + JSON.stringify(code.data) + "</h4>"+
|
||||||
|
"<button type='submit' class='btn btn-primary' onclick='sendfunds(" + JSON.stringify(code.data) + ")'>Send funds</button>"+
|
||||||
|
"<button style='margin-left:20px;' type='submit' class='btn btn-primary' onclick='cancelsend()'>Cancel payment</button>"+
|
||||||
|
"</br/></br/></div></div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outputMessage.hidden = false;
|
||||||
|
outputData.parentElement.hidden = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestAnimationFrame(tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function deletewallet(){
|
||||||
|
var urll = "deletewallet?wal={{ thewal }}&usr={{ theid }}";
|
||||||
|
window.location.href = urll;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function sidebarmake(){
|
||||||
|
document.getElementById("sidebarmake").innerHTML = "<li><div class='form-group'>"+
|
||||||
|
"<input style='width:70%;float:left;' type='text' class='form-control' id='walname' placeholder='Name wallet' required>" +
|
||||||
|
"<button style='width:30%;float:left;' type='button' class='btn btn-primary' onclick='newwallet()'>Submit</button>" +
|
||||||
|
"</div></li><br/><br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeid(length) {
|
||||||
|
var result = '';
|
||||||
|
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
var charactersLength = characters.length;
|
||||||
|
for ( var i = 0; i < length; i++ ) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newwallet() {
|
||||||
|
walname = document.getElementById("walname").value;
|
||||||
|
window.location.href = "wallet?usr=" + "{{ theid }}" + "&wal=" + makeid(40) + "&nme=" + walname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var trans = "{{ transactions }}";
|
||||||
|
var transac = trans.substr(1);
|
||||||
|
|
||||||
|
|
||||||
|
//console.log(trans);
|
||||||
|
|
||||||
|
if(transac != ""){
|
||||||
|
var transactions = "";
|
||||||
|
var linechart = [];
|
||||||
|
var tran = transac.split("!");
|
||||||
|
tran.shift();
|
||||||
|
console.log(tran);
|
||||||
|
for (var i = 0; i < tran.length; i++) {
|
||||||
|
rects = tran[i].split(",");
|
||||||
|
rectstime = String(rects[1]).split(".");
|
||||||
|
var datime = convertTimestamp(rectstime[0])
|
||||||
|
|
||||||
|
//Make the transactions table
|
||||||
|
|
||||||
|
transactions += "<tr><td style='width: 50%'>" + rects[0] + "</td><td>" + datime + "</td><td>" + rects[2] + "</td></tr>";
|
||||||
|
|
||||||
|
//Make the line chart
|
||||||
|
|
||||||
|
if (i == 0){
|
||||||
|
linechart.push({y: datime, item1: rects[2]});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
linechart.push({y: datime, item1: rects[3]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById("transactions").innerHTML = transactions;
|
||||||
|
if(linechart[0] != ""){
|
||||||
|
document.getElementById("satschart").innerHTML = "<div class='row'><div class='col-md-6'><div class='box box-info'><div class='box-header'>" +
|
||||||
|
"<h3 class='box-title'>Spending</h3></div><div class='box-body chart-responsive'>" +
|
||||||
|
"<div class='chart' id='line-chart' style='height: 300px;'></div></div></div></div></div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(linechart);
|
||||||
|
var data = linechart
|
||||||
|
var line = new Morris.Line({
|
||||||
|
element: 'line-chart',
|
||||||
|
resize: true,
|
||||||
|
data,
|
||||||
|
xkey: 'y',
|
||||||
|
ykeys: ['item1'],
|
||||||
|
labels: ['Item 1'],
|
||||||
|
lineColors: ['#3c8dbc'],
|
||||||
|
hideHover: 'auto'
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function convertTimestamp(timestamp) {
|
||||||
|
var d = new Date(timestamp * 1000),
|
||||||
|
yyyy = d.getFullYear(),
|
||||||
|
mm = ('0' + (d.getMonth() + 1)).slice(-2),
|
||||||
|
dd = ('0' + d.getDate()).slice(-2),
|
||||||
|
hh = d.getHours(),
|
||||||
|
h = hh,
|
||||||
|
min = ('0' + d.getMinutes()).slice(-2),
|
||||||
|
ampm = 'AM',
|
||||||
|
time;
|
||||||
|
time = yyyy + '-' + mm + '-' + dd + ' ' + h + ':' + min;
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user