Browse Source

take JS out of HTML, fix transactions chart, add apipayments.time.

fee_issues
fiatjaf 5 years ago
parent
commit
463ee21c9f
  1. 1
      .gitignore
  2. 19
      LNbits/__init__.py
  3. 3
      LNbits/data/schema.sql
  4. 16
      LNbits/helpers.py
  5. 349
      LNbits/static/app.js
  6. 5
      LNbits/templates/base.html
  7. 19
      LNbits/templates/index.html
  8. 410
      LNbits/templates/wallet.html

1
.gitignore

@ -24,3 +24,4 @@ venv
database.sqlite3 database.sqlite3
database.sqlite3* database.sqlite3*
.pyre*

19
LNbits/__init__.py

@ -7,17 +7,12 @@ from flask import Flask, jsonify, render_template, request, redirect, url_for
from . import bolt11 from . import bolt11
from .db import Database from .db import Database
from .settings import DATABASE_PATH, LNBITS_PATH, WALLET, DEFAULT_USER_WALLET_NAME from .helpers import megajson
from .settings import LNBITS_PATH, WALLET, DEFAULT_USER_WALLET_NAME
app = Flask(__name__) app = Flask(__name__)
app.jinja_env.filters["megajson"] = megajson
def db_connect(db_path=DATABASE_PATH):
import sqlite3
con = sqlite3.connect(db_path)
return con
@app.before_first_request @app.before_first_request
@ -50,7 +45,7 @@ def deletewallet():
(thewal, theid), (thewal, theid),
) )
next_wallet = db.fetchone("SELECT hash FROM wallets WHERE user = ?", (theid,)) next_wallet = db.fetchone("SELECT id FROM wallets WHERE user = ?", (theid,))
if next_wallet: if next_wallet:
return redirect(url_for("wallet", usr=theid, wal=next_wallet[0])) return redirect(url_for("wallet", usr=theid, wal=next_wallet[0]))
@ -164,16 +159,14 @@ def wallet():
(SELECT balance/1000 FROM balances WHERE wallet = wallets.id), (SELECT balance/1000 FROM balances WHERE wallet = wallets.id),
0 0
) AS balance, ) AS balance,
name, *
adminkey,
inkey
FROM wallets FROM wallets
WHERE user = ? AND id = ? WHERE user = ? AND id = ?
""", """,
(usr, wallet_id), (usr, wallet_id),
) )
transactions = [] transactions = db.fetchall("SELECT * FROM apipayments WHERE wallet = ?", (wallet_id,))
return render_template( return render_template(
"wallet.html", user_wallets=user_wallets, wallet=wallet, user=usr, transactions=transactions, "wallet.html", user_wallets=user_wallets, wallet=wallet, user=usr, transactions=transactions,

3
LNbits/data/schema.sql

@ -18,7 +18,8 @@ CREATE TABLE IF NOT EXISTS apipayments (
fee integer NOT NULL DEFAULT 0, fee integer NOT NULL DEFAULT 0,
wallet text NOT NULL, wallet text NOT NULL,
pending boolean NOT NULL, pending boolean NOT NULL,
memo text memo text,
time timestamp NOT NULL DEFAULT (strftime('%s', 'now'))
); );
CREATE VIEW IF NOT EXISTS balances AS CREATE VIEW IF NOT EXISTS balances AS

16
LNbits/helpers.py

@ -0,0 +1,16 @@
import json
import sqlite3
class MegaEncoder(json.JSONEncoder):
def default(self, o):
if type(o) == sqlite3.Row:
val = {}
for k in o.keys():
val[k] = o[k]
return val
return o
def megajson(o):
return json.dumps(o, cls=MegaEncoder)

349
LNbits/static/app.js

@ -0,0 +1,349 @@
/** @format */
const user = window.user
const user_wallets = window.user_wallets
const wallet = window.wallet
const transactions = window.transactions
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(wallet.balance)) {
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='Create invoice' /></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}),
wallet.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, wallet.inkey, function(datab) {
console.log(JSON.parse(datab).PAID)
if (JSON.parse(datab).PAID == 'TRUE') {
window.location.href = 'wallet?wal=' + wallet.id + '&usr=' + user
}
})
}
)
}
function cancelsend() {
window.location.href = 'wallet?wal=' + wallet.id + '&usr=' + user
}
function sendfunds(invoice) {
var url = '/v1/channels/transactions'
postAjax(
url,
JSON.stringify({payment_request: invoice}),
wallet.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=' + wallet.id + '&usr=' + user
}
}
)
}
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(wallet.balance)) {
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 url = 'deletewallet?wal=' + wallet.id + '&usr=' + user
window.location.href = url
}
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 newwallet() {
walname = document.getElementById('walname').value
window.location.href = 'wallet?usr=' + user + '&nme=' + walname
}
function drawChart(transactions) {
var linechart = []
var transactionsHTML = ''
var balance = 0
for (var i = 0; i < transactions.length; i++) {
var tx = transactions[i]
var datime = convertTimestamp(tx.time)
// make the transactions table
transactionsHTML +=
"<tr><td style='width: 50%'>" +
tx.memo +
'</td><td>' +
datime +
'</td><td>' +
parseFloat(tx.amount / 1000) +
'</td></tr>'
// make the line chart
balance += parseInt(tx.amount / 1000)
linechart.push({y: datime, balance: balance})
}
document.getElementById('transactions').innerHTML = transactionsHTML
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 line = new Morris.Line({
element: 'line-chart',
resize: true,
data: linechart,
xkey: 'y',
ykeys: ['balance'],
labels: ['balance'],
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
}
if (transactions.length) {
drawChart(transactions)
}

5
LNbits/templates/base.html

@ -296,4 +296,9 @@
> >
</footer> </footer>
</body> </body>
<script
src="{{ url_for('static', filename='app.js') }}"
type="text/javascript"
></script>
</html> </html>

19
LNbits/templates/index.html

@ -89,23 +89,4 @@
<!-- /.content --> <!-- /.content -->
</div> </div>
<!-- /.content-wrapper --> <!-- /.content-wrapper -->
<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>
{% endblock %} {% endblock %}

410
LNbits/templates/wallet.html

@ -63,7 +63,6 @@
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<!-- small box --> <!-- small box -->
<a href="#" class="small-box-footer">
<div class="small-box bg-aqua"> <div class="small-box bg-aqua">
<div class="inner"> <div class="inner">
<h3><b>{{ wallet.balance }} sats</b></h3> <h3><b>{{ wallet.balance }} sats</b></h3>
@ -75,8 +74,7 @@
</div> </div>
<!-- ./col --> <!-- ./col -->
><!-- /.row --> <!-- /.row -->
<div class="row"> <div class="row">
<div class="col-sm-3"> <div class="col-sm-3">
<button <button
@ -95,9 +93,11 @@
</button> </button>
</div> </div>
</div> </div>
</div>
<div id="receive"></div> <div id="receive"></div>
<div id="sendfunds"></div> <div id="sendfunds"></div>
</div>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
@ -107,10 +107,7 @@
</div> </div>
<!-- /.box-header --> <!-- /.box-header -->
<div class="box-body no-padding"> <div class="box-body no-padding">
<table <table id="pagnation" class="table table-bordered table-striped">
id="pagnation"
class="table table-bordered table-striped"
>
<tr> <tr>
<th>Memo</th> <th>Memo</th>
<th style="width: 20%">date</th> <th style="width: 20%">date</th>
@ -156,23 +153,18 @@
> >
<div class="box-body" style="word-wrap: break-word;"> <div class="box-body" style="word-wrap: break-word;">
<b>Admin key: </b><i>{{ wallet.adminkey }}</i><br /> <b>Admin key: </b><i>{{ wallet.adminkey }}</i><br />
<b>Invoice/Read key: </b><i>{{ wallet.inkey }}</i <b>Invoice/Read key: </b><i>{{ wallet.inkey }}</i><br />
><br /> Generate an invoice:<br /><code>POST /v1/invoices</code
Generate an invoice:<br /><code
>POST /v1/invoices</code
><br />Header ><br />Header
<code <code
>{"Grpc-Metadata-macaroon": "<i >{"Grpc-Metadata-macaroon": "<i>{{ wallet.inkey }}</i
>{{ wallet.inkey }}</i
>"}</code >"}</code
><br /> ><br />
Body <code>{"value": "200","memo": "beer"} </code Body <code>{"value": "200","memo": "beer"} </code><br />
><br />
Returns Returns
<code>{"pay_req": string,"pay_id": string} </code <code>{"pay_req": string,"pay_id": string} </code><br />
><br /> *payment will not register in the wallet until the "check
*payment will not register in the wallet until the invoice" endpoint is used<br /><br />
"check invoice" endpoint is used<br /><br />
Check invoice:<br /> Check invoice:<br />
Check an invoice:<br /><code Check an invoice:<br /><code
@ -229,379 +221,13 @@
</div> </div>
<!-- /.content --> <!-- /.content -->
</a>
</div>
</div>
</section> </section>
</div>
<script>
var inmacaroon = '{{ wallet.inkey }}'
var adminmacaroon = '{{ wallet.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('{{ wallet.balance }}')) {
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='Create invoice' /></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}),
'{{ wallet.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, '{{ wallet.inkey }}', function(datab) {
console.log(JSON.parse(datab).PAID)
if (JSON.parse(datab).PAID == 'TRUE') {
window.location.href =
'wallet?wal=' + '{{ wallet.id }}' + '&usr=' + '{{ user }}'
}
})
}
)
}
function cancelsend() {
window.location.href =
'wallet?wal=' + '{{ wallet.id }}' + '&usr=' + '{{ user }}'
}
function sendfunds(invoice) {
var url = '/v1/channels/transactions'
postAjax(
url,
JSON.stringify({payment_request: invoice}),
'{{ wallet.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=' + '{{ wallet.id }}' + '&usr=' + '{{ user }}'
}
}
)
}
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('{{ wallet.balance }}')) {
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={{ wallet.id }}&usr={{ user }}'
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=' + '{{ user }}' + '&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>
<script>
window.user = {{ user | megajson | safe }}
window.user_wallets = {{ user_wallets | megajson | safe }}
window.wallet = {{ wallet | megajson | safe }}
window.transactions = {{ transactions | megajson | safe }}
</script>
</div>
{% endblock %} {% endblock %}

Loading…
Cancel
Save