diff --git a/.gitignore b/.gitignore
index 4e36db9..ac8c265 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,5 @@ venv
.pyre*
__bundle__
+
+node_modules
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..224c6ee
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,12 @@
+{
+ "semi": false,
+ "arrowParens": "avoid",
+ "insertPragma": false,
+ "printWidth": 80,
+ "proseWrap": "preserve",
+ "singleQuote": true,
+ "trailingComma": "none",
+ "useTabs": false,
+ "jsxBracketSameLine": false,
+ "bracketSpacing": false
+}
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..be5e342
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,2 @@
+prettier:
+ ./node_modules/.bin/prettier --write lnbits/static/js/** lnbits/core/static/js/** lnbits/extensions/*/templates/**
diff --git a/lnbits/core/static/js/extensions.js b/lnbits/core/static/js/extensions.js
index 1ec818b..85ace77 100644
--- a/lnbits/core/static/js/extensions.js
+++ b/lnbits/core/static/js/extensions.js
@@ -1,4 +1,4 @@
new Vue({
el: '#vue',
mixins: [windowMixin]
-});
+})
diff --git a/lnbits/core/static/js/index.js b/lnbits/core/static/js/index.js
index 1f1d96d..0a930e1 100644
--- a/lnbits/core/static/js/index.js
+++ b/lnbits/core/static/js/index.js
@@ -3,23 +3,23 @@ new Vue({
mixins: [windowMixin],
data: function () {
return {
- disclaimerDialog: {
+ disclaimerDialog: {
show: false,
data: {}
- },
+ },
walletName: ''
- };
+ }
},
methods: {
createWallet: function () {
- LNbits.href.createWallet(this.walletName);
+ LNbits.href.createWallet(this.walletName)
},
processing: function () {
this.$q.notify({
timeout: 0,
message: 'Processing...',
icon: null
- });
+ })
}
}
-});
+})
diff --git a/lnbits/core/static/js/wallet.js b/lnbits/core/static/js/wallet.js
index 8a3c742..20e7778 100644
--- a/lnbits/core/static/js/wallet.js
+++ b/lnbits/core/static/js/wallet.js
@@ -1,39 +1,49 @@
-Vue.component(VueQrcode.name, VueQrcode);
-Vue.use(VueQrcodeReader);
-
+Vue.component(VueQrcode.name, VueQrcode)
+Vue.use(VueQrcodeReader)
function generateChart(canvas, payments) {
- var txs = [];
- var n = 0;
+ var txs = []
+ var n = 0
var data = {
labels: [],
income: [],
outcome: [],
cumulative: []
- };
+ }
- _.each(payments.slice(0).sort(function (a, b) {
- return a.time - b.time;
- }), function (tx) {
- txs.push({
- hour: Quasar.utils.date.formatDate(tx.date, 'YYYY-MM-DDTHH:00'),
- sat: tx.sat,
- });
- });
+ _.each(
+ payments.slice(0).sort(function (a, b) {
+ return a.time - b.time
+ }),
+ function (tx) {
+ txs.push({
+ hour: Quasar.utils.date.formatDate(tx.date, 'YYYY-MM-DDTHH:00'),
+ sat: tx.sat
+ })
+ }
+ )
_.each(_.groupBy(txs, 'hour'), function (value, day) {
- var income = _.reduce(value, function(memo, tx) {
- return (tx.sat >= 0) ? memo + tx.sat : memo;
- }, 0);
- var outcome = _.reduce(value, function(memo, tx) {
- return (tx.sat < 0) ? memo + Math.abs(tx.sat) : memo;
- }, 0);
- n = n + income - outcome;
- data.labels.push(day);
- data.income.push(income);
- data.outcome.push(outcome);
- data.cumulative.push(n);
- });
+ var income = _.reduce(
+ value,
+ function (memo, tx) {
+ return tx.sat >= 0 ? memo + tx.sat : memo
+ },
+ 0
+ )
+ var outcome = _.reduce(
+ value,
+ function (memo, tx) {
+ return tx.sat < 0 ? memo + Math.abs(tx.sat) : memo
+ },
+ 0
+ )
+ n = n + income - outcome
+ data.labels.push(day)
+ data.income.push(income)
+ data.outcome.push(outcome)
+ data.cumulative.push(n)
+ })
new Chart(canvas.getContext('2d'), {
type: 'bar',
@@ -44,7 +54,7 @@ function generateChart(canvas, payments) {
data: data.cumulative,
type: 'line',
label: 'balance',
- backgroundColor: '#673ab7', // deep-purple
+ backgroundColor: '#673ab7', // deep-purple
borderColor: '#673ab7',
borderWidth: 4,
pointRadius: 3,
@@ -55,14 +65,14 @@ function generateChart(canvas, payments) {
type: 'bar',
label: 'in',
barPercentage: 0.75,
- backgroundColor: window.Color('rgb(76,175,80)').alpha(0.5).rgbString() // green
+ backgroundColor: window.Color('rgb(76,175,80)').alpha(0.5).rgbString() // green
},
{
data: data.outcome,
type: 'bar',
label: 'out',
barPercentage: 0.75,
- backgroundColor: window.Color('rgb(233,30,99)').alpha(0.5).rgbString() // pink
+ backgroundColor: window.Color('rgb(233,30,99)').alpha(0.5).rgbString() // pink
}
]
},
@@ -72,18 +82,20 @@ function generateChart(canvas, payments) {
},
tooltips: {
mode: 'index',
- intersect:false
+ intersect: false
},
scales: {
- xAxes: [{
- type: 'time',
- display: true,
- offset: true,
- time: {
- minUnit: 'hour',
- stepSize: 3
+ xAxes: [
+ {
+ type: 'time',
+ display: true,
+ offset: true,
+ time: {
+ minUnit: 'hour',
+ stepSize: 3
+ }
}
- }],
+ ]
},
// performance tweaks
animation: {
@@ -95,10 +107,9 @@ function generateChart(canvas, payments) {
}
}
}
- });
+ })
}
-
new Vue({
el: '#vue',
mixins: [windowMixin],
@@ -128,8 +139,20 @@ new Vue({
paymentsTable: {
columns: [
{name: 'memo', align: 'left', label: 'Memo', field: 'memo'},
- {name: 'date', align: 'left', label: 'Date', field: 'date', sortable: true},
- {name: 'sat', align: 'right', label: 'Amount (sat)', field: 'sat', sortable: true}
+ {
+ name: 'date',
+ align: 'left',
+ label: 'Date',
+ field: 'date',
+ sortable: true
+ },
+ {
+ name: 'sat',
+ align: 'right',
+ label: 'Amount (sat)',
+ field: 'sat',
+ sortable: true
+ }
],
pagination: {
rowsPerPage: 10
@@ -143,46 +166,50 @@ new Vue({
show: false,
location: window.location
}
- };
+ }
},
computed: {
filteredPayments: function () {
- var q = this.paymentsTable.filter;
- if (!q || q == '') return this.payments;
+ var q = this.paymentsTable.filter
+ if (!q || q == '') return this.payments
- return LNbits.utils.search(this.payments, q);
+ return LNbits.utils.search(this.payments, q)
},
balance: function () {
if (this.payments.length) {
- return _.pluck(this.payments, 'amount').reduce(function (a, b) { return a + b; }, 0) / 1000;
+ return (
+ _.pluck(this.payments, 'amount').reduce(function (a, b) {
+ return a + b
+ }, 0) / 1000
+ )
}
- return this.g.wallet.sat;
+ return this.g.wallet.sat
},
fbalance: function () {
return LNbits.utils.formatSat(this.balance)
},
canPay: function () {
- if (!this.send.invoice) return false;
- return this.send.invoice.sat <= this.balance;
+ if (!this.send.invoice) return false
+ return this.send.invoice.sat <= this.balance
},
pendingPaymentsExist: function () {
- return (this.payments)
+ return this.payments
? _.where(this.payments, {pending: 1}).length > 0
- : false;
+ : false
}
},
methods: {
closeCamera: function () {
- this.sendCamera.show = false;
+ this.sendCamera.show = false
},
showCamera: function () {
- this.sendCamera.show = true;
+ this.sendCamera.show = true
},
showChart: function () {
- this.paymentsChart.show = true;
+ this.paymentsChart.show = true
this.$nextTick(function () {
- generateChart(this.$refs.canvas, this.payments);
- });
+ generateChart(this.$refs.canvas, this.payments)
+ })
},
showReceiveDialog: function () {
this.receive = {
@@ -194,7 +221,7 @@ new Vue({
memo: ''
},
paymentChecker: null
- };
+ }
},
showSendDialog: function () {
this.send = {
@@ -204,57 +231,64 @@ new Vue({
bolt11: ''
},
paymentChecker: null
- };
+ }
},
closeReceiveDialog: function () {
- var checker = this.receive.paymentChecker;
+ var checker = this.receive.paymentChecker
setTimeout(function () {
- clearInterval(checker);
- }, 10000);
+ clearInterval(checker)
+ }, 10000)
},
closeSendDialog: function () {
- this.sendCamera.show = false;
- var checker = this.send.paymentChecker;
+ this.sendCamera.show = false
+ var checker = this.send.paymentChecker
setTimeout(function () {
- clearInterval(checker);
- }, 1000);
+ clearInterval(checker)
+ }, 1000)
},
createInvoice: function () {
- var self = this;
- this.receive.status = 'loading';
- LNbits.api.createInvoice(this.g.wallet, this.receive.data.amount, this.receive.data.memo)
+ var self = this
+ this.receive.status = 'loading'
+ LNbits.api
+ .createInvoice(
+ this.g.wallet,
+ this.receive.data.amount,
+ this.receive.data.memo
+ )
.then(function (response) {
- self.receive.status = 'success';
- self.receive.paymentReq = response.data.payment_request;
+ self.receive.status = 'success'
+ self.receive.paymentReq = response.data.payment_request
self.receive.paymentChecker = setInterval(function () {
- LNbits.api.getPayment(self.g.wallet, response.data.checking_id).then(function (response) {
- if (response.data.paid) {
- self.fetchPayments();
- self.receive.show = false;
- clearInterval(self.receive.paymentChecker);
- }
- });
- }, 2000);
-
- }).catch(function (error) {
- LNbits.utils.notifyApiError(error);
- self.receive.status = 'pending';
- });
+ LNbits.api
+ .getPayment(self.g.wallet, response.data.checking_id)
+ .then(function (response) {
+ if (response.data.paid) {
+ self.fetchPayments()
+ self.receive.show = false
+ clearInterval(self.receive.paymentChecker)
+ }
+ })
+ }, 2000)
+ })
+ .catch(function (error) {
+ LNbits.utils.notifyApiError(error)
+ self.receive.status = 'pending'
+ })
},
decodeQR: function (res) {
- this.send.data.bolt11 = res;
- this.decodeInvoice();
- this.sendCamera.show = false;
+ this.send.data.bolt11 = res
+ this.decodeInvoice()
+ this.sendCamera.show = false
},
decodeInvoice: function () {
if (this.send.data.bolt11.startsWith('lightning:')) {
- this.send.data.bolt11 = this.send.data.bolt11.slice(10);
+ this.send.data.bolt11 = this.send.data.bolt11.slice(10)
}
- let invoice;
+ let invoice
try {
- invoice = decode(this.send.data.bolt11);
+ invoice = decode(this.send.data.bolt11)
} catch (error) {
this.$q.notify({
timeout: 3000,
@@ -262,101 +296,120 @@ new Vue({
message: error + '.',
caption: '400 BAD REQUEST',
icon: null
- });
- return;
+ })
+ return
}
let cleanInvoice = {
msat: invoice.human_readable_part.amount,
sat: invoice.human_readable_part.amount / 1000,
fsat: LNbits.utils.formatSat(invoice.human_readable_part.amount / 1000)
- };
+ }
_.each(invoice.data.tags, function (tag) {
if (_.isObject(tag) && _.has(tag, 'description')) {
- if (tag.description == 'payment_hash') { cleanInvoice.hash = tag.value; }
- else if (tag.description == 'description') { cleanInvoice.description = tag.value; }
- else if (tag.description == 'expiry') {
- var expireDate = new Date((invoice.data.time_stamp + tag.value) * 1000);
- cleanInvoice.expireDate = Quasar.utils.date.formatDate(expireDate, 'YYYY-MM-DDTHH:mm:ss.SSSZ');
- cleanInvoice.expired = false; // TODO
+ if (tag.description == 'payment_hash') {
+ cleanInvoice.hash = tag.value
+ } else if (tag.description == 'description') {
+ cleanInvoice.description = tag.value
+ } else if (tag.description == 'expiry') {
+ var expireDate = new Date(
+ (invoice.data.time_stamp + tag.value) * 1000
+ )
+ cleanInvoice.expireDate = Quasar.utils.date.formatDate(
+ expireDate,
+ 'YYYY-MM-DDTHH:mm:ss.SSSZ'
+ )
+ cleanInvoice.expired = false // TODO
}
}
- });
+ })
- this.send.invoice = Object.freeze(cleanInvoice);
+ this.send.invoice = Object.freeze(cleanInvoice)
},
payInvoice: function () {
- var self = this;
+ var self = this
dismissPaymentMsg = this.$q.notify({
timeout: 0,
message: 'Processing payment...',
icon: null
- });
+ })
- LNbits.api.payInvoice(this.g.wallet, this.send.data.bolt11).then(function (response) {
- self.send.paymentChecker = setInterval(function () {
- LNbits.api.getPayment(self.g.wallet, response.data.checking_id).then(function (res) {
- if (res.data.paid) {
- self.send.show = false;
- clearInterval(self.send.paymentChecker);
- dismissPaymentMsg();
- self.fetchPayments();
- }
- });
- }, 2000);
- }).catch(function (error) {
- dismissPaymentMsg();
- LNbits.utils.notifyApiError(error);
- });
+ LNbits.api
+ .payInvoice(this.g.wallet, this.send.data.bolt11)
+ .then(function (response) {
+ self.send.paymentChecker = setInterval(function () {
+ LNbits.api
+ .getPayment(self.g.wallet, response.data.checking_id)
+ .then(function (res) {
+ if (res.data.paid) {
+ self.send.show = false
+ clearInterval(self.send.paymentChecker)
+ dismissPaymentMsg()
+ self.fetchPayments()
+ }
+ })
+ }, 2000)
+ })
+ .catch(function (error) {
+ dismissPaymentMsg()
+ LNbits.utils.notifyApiError(error)
+ })
},
deleteWallet: function (walletId, user) {
- LNbits.utils.confirmDialog(
- 'Are you sure you want to delete this wallet?'
- ).onOk(function () {
- LNbits.href.deleteWallet(walletId, user);
- });
+ LNbits.utils
+ .confirmDialog('Are you sure you want to delete this wallet?')
+ .onOk(function () {
+ LNbits.href.deleteWallet(walletId, user)
+ })
},
fetchPayments: function (checkPending) {
- var self = this;
+ var self = this
- return LNbits.api.getPayments(this.g.wallet, checkPending).then(function (response) {
- self.payments = response.data.map(function (obj) {
- return LNbits.map.payment(obj);
- }).sort(function (a, b) {
- return b.time - a.time;
- });
- });
+ return LNbits.api
+ .getPayments(this.g.wallet, checkPending)
+ .then(function (response) {
+ self.payments = response.data
+ .map(function (obj) {
+ return LNbits.map.payment(obj)
+ })
+ .sort(function (a, b) {
+ return b.time - a.time
+ })
+ })
},
checkPendingPayments: function () {
var dismissMsg = this.$q.notify({
timeout: 0,
message: 'Checking pending transactions...',
icon: null
- });
+ })
this.fetchPayments(true).then(function () {
- dismissMsg();
- });
+ dismissMsg()
+ })
},
exportCSV: function () {
- LNbits.utils.exportCSV(this.paymentsTable.columns, this.payments);
+ LNbits.utils.exportCSV(this.paymentsTable.columns, this.payments)
}
},
watch: {
- 'payments': function () {
- EventHub.$emit('update-wallet-balance', [this.g.wallet.id, this.balance]);
+ payments: function () {
+ EventHub.$emit('update-wallet-balance', [this.g.wallet.id, this.balance])
}
},
created: function () {
- this.fetchPayments();
- setTimeout(this.checkPendingPayments(), 1200);
+ this.fetchPayments()
+ setTimeout(this.checkPendingPayments(), 1200)
},
mounted: function () {
- if (this.$refs.disclaimer && !this.$q.localStorage.getItem('lnbits.disclaimerShown')) {
- this.disclaimerDialog.show = true;
- this.$q.localStorage.set('lnbits.disclaimerShown', true);
+ if (
+ this.$refs.disclaimer &&
+ !this.$q.localStorage.getItem('lnbits.disclaimerShown')
+ ) {
+ this.disclaimerDialog.show = true
+ this.$q.localStorage.set('lnbits.disclaimerShown', true)
}
}
-});
+})
diff --git a/lnbits/extensions/amilk/templates/amilk/_api_docs.html b/lnbits/extensions/amilk/templates/amilk/_api_docs.html
index bd2c42a..f1c27a1 100644
--- a/lnbits/extensions/amilk/templates/amilk/_api_docs.html
+++ b/lnbits/extensions/amilk/templates/amilk/_api_docs.html
@@ -1,16 +1,24 @@
-
- Milking faucets with software, known as "assmilking", seems at first to be black-hat, although in fact there might be some unexplored use cases. An LNURL withdraw gives someone the right to pull funds, which can be done over time. An LNURL withdraw could be used outside of just faucets, to provide money streaming and repeat payments.
+ Milking faucets with software, known as "assmilking", seems at first to
+ be black-hat, although in fact there might be some unexplored use cases.
+ An LNURL withdraw gives someone the right to pull funds, which can be
+ done over time. An LNURL withdraw could be used outside of just faucets,
+ to provide money streaming and repeat payments.Assistant Faucet Milker
-
Paste or scan an LNURL withdraw, enter the amount for the AMilk to pull and the frequency for it to be pulled.
- Created by, Ben ArcAssistant Faucet Milker
+
Paste or scan an
+ LNURL withdraw, enter the amount for the AMilk to pull and the frequency
+ for it to be pulled.
+
+ Created by, Ben Arc
+
Make a list of products to sell, point your list of products at a public indexer. Buyers browse your products on the indexer, and pay you directly. Ratings are managed by the indexer. Your stall can be listed in multiple indexers, even over TOR, if you wish to be anonymous.
- More information on the Diagon Alley Protocol
- Created by, Ben Arc
+ Make a list of products to sell, point your list of products at a public
+ indexer. Buyers browse your products on the indexer, and pay you
+ directly. Ratings are managed by the indexer. Your stall can be listed
+ in multiple indexers, even over TOR, if you wish to be anonymous.
+ More information on the
+ Diagon Alley Protocol
+
+ Created by, Ben Arc
+
GET /api/v1/diagonalley/stall/products/<indexer_id>
+ GET
+ /api/v1/diagonalley/stall/products/<indexer_id>
Product JSON list
curl -X GET {{ request.url_root }}diagonalley/api/v1/diagonalley/stall/products/<indexer_id>
+ curl -X GET {{ request.url_root
+ }}diagonalley/api/v1/diagonalley/stall/products/<indexer_id>
POST /api/v1/diagonalley/stall/order/<indexer_id>
+ POST
+ /api/v1/diagonalley/stall/order/<indexer_id>
{"id": <string>, "address": <string>, "shippingzone": <integer>, "email": <string>, "quantity": <integer>}
- {"checking_id": <string>,"payment_request": <string>}
+ {"id": <string>, "address": <string>, "shippingzone":
+ <integer>, "email": <string>, "quantity":
+ <integer>}
+ {"checking_id": <string>,"payment_request":
+ <string>}
curl -X POST {{ request.url_root }}diagonalley/api/v1/diagonalley/stall/order/<indexer_id> -d '{"id": <product_id&>, "email": <customer_email>, "address": <customer_address>, "quantity": 2, "shippingzone": 1}' -H "Content-type: application/json"
-
+ curl -X POST {{ request.url_root
+ }}diagonalley/api/v1/diagonalley/stall/order/<indexer_id> -d
+ '{"id": <product_id&>, "email": <customer_email>,
+ "address": <customer_address>, "quantity": 2, "shippingzone":
+ 1}' -H "Content-type: application/json"
+
GET /diagonalley/api/v1/diagonalley/stall/checkshipped/<checking_id>
+ GET
+ /diagonalley/api/v1/diagonalley/stall/checkshipped/<checking_id>
{"shipped": <boolean>}
curl -X GET {{ request.url_root }}diagonalley/api/v1/diagonalley/stall/checkshipped/<checking_id> -H "Content-type: application/json"
+ curl -X GET {{ request.url_root
+ }}diagonalley/api/v1/diagonalley/stall/checkshipped/<checking_id>
+ -H "Content-type: application/json"