Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2904afaf26 | ||
|
|
2cd9a19d67 | ||
|
|
765eeed9c9 | ||
|
|
bc5841d07d | ||
|
|
5b8ab18a59 | ||
|
|
7e1d4a3110 | ||
|
|
5100252ea5 | ||
|
|
b8bc4dd0cd | ||
|
|
a7294cbbbd | ||
|
|
950900b136 | ||
|
|
4ad56aaebe | ||
|
|
f4b35e4895 | ||
|
|
9e70f123a6 |
@@ -35,6 +35,7 @@ export class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadByAuthorization(authorization) {
|
async loadByAuthorization(authorization) {
|
||||||
|
if (!authorization) return false;
|
||||||
let access_token = authorization.replace('Bearer ', '');
|
let access_token = authorization.replace('Bearer ', '');
|
||||||
let userid = await this._redis.get('userid_for_' + access_token);
|
let userid = await this._redis.get('userid_for_' + access_token);
|
||||||
|
|
||||||
@@ -186,9 +187,18 @@ export class User {
|
|||||||
// attempting to lookup invoice
|
// attempting to lookup invoice
|
||||||
let lookup_info = await this.lookupInvoice(invoice.payment_hash);
|
let lookup_info = await this.lookupInvoice(invoice.payment_hash);
|
||||||
invoice.ispaid = lookup_info.settled;
|
invoice.ispaid = lookup_info.settled;
|
||||||
|
if (invoice.ispaid) {
|
||||||
|
// so invoice was paid after all
|
||||||
|
await this.setPaymentHashPaid(invoice.payment_hash);
|
||||||
|
await this.saveBalance((await this.getBalance()) + decoded.satoshis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invoice.amt = decoded.satoshis;
|
invoice.amt = decoded.satoshis;
|
||||||
|
invoice.expire_time = 3600;
|
||||||
|
// ^^^default; will keep for now. if we want to un-hardcode it - it should be among tags (`expire_time`)
|
||||||
|
invoice.timestamp = decoded.timestamp;
|
||||||
|
invoice.type = 'user_invoice';
|
||||||
result.push(invoice);
|
result.push(invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,10 +231,18 @@ export class User {
|
|||||||
for (let invoice of range) {
|
for (let invoice of range) {
|
||||||
invoice = JSON.parse(invoice);
|
invoice = JSON.parse(invoice);
|
||||||
invoice.type = 'paid_invoice';
|
invoice.type = 'paid_invoice';
|
||||||
invoice.fee = +invoice.payment_route.total_fees;
|
|
||||||
invoice.value = +invoice.payment_route.total_fees + +invoice.payment_route.total_amt;
|
// for internal invoices it might not have properties `payment_route` and `decoded`...
|
||||||
invoice.timestamp = invoice.decoded.timestamp;
|
if (invoice.payment_route) {
|
||||||
invoice.memo = invoice.decoded.description;
|
invoice.fee = +invoice.payment_route.total_fees;
|
||||||
|
invoice.value = +invoice.payment_route.total_fees + +invoice.payment_route.total_amt;
|
||||||
|
} else {
|
||||||
|
invoice.fee = 0;
|
||||||
|
}
|
||||||
|
if (invoice.decoded) {
|
||||||
|
invoice.timestamp = invoice.decoded.timestamp;
|
||||||
|
invoice.memo = invoice.decoded.description;
|
||||||
|
}
|
||||||
result.push(invoice);
|
result.push(invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,12 +106,19 @@ router.post('/payinvoice', async function(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!req.body.invoice) return errorBadArguments(res);
|
if (!req.body.invoice) return errorBadArguments(res);
|
||||||
|
let freeAmount = false;
|
||||||
|
if (req.body.amount) freeAmount = parseInt(req.body.amount);
|
||||||
|
|
||||||
let userBalance = await u.getBalance();
|
let userBalance = await u.getBalance();
|
||||||
|
|
||||||
lightning.decodePayReq({ pay_req: req.body.invoice }, async function(err, info) {
|
lightning.decodePayReq({ pay_req: req.body.invoice }, async function(err, info) {
|
||||||
if (err) return errorNotAValidInvoice(res);
|
if (err) return errorNotAValidInvoice(res);
|
||||||
|
|
||||||
|
if (+info.num_satoshis === 0) {
|
||||||
|
// 'tip' invoices
|
||||||
|
info.num_satoshis = freeAmount;
|
||||||
|
}
|
||||||
|
|
||||||
if (userBalance >= info.num_satoshis) {
|
if (userBalance >= info.num_satoshis) {
|
||||||
// got enough balance
|
// got enough balance
|
||||||
|
|
||||||
@@ -130,8 +137,15 @@ router.post('/payinvoice', async function(req, res) {
|
|||||||
// sender spent his balance:
|
// sender spent his balance:
|
||||||
userBalance -= info.num_satoshis * 1;
|
userBalance -= info.num_satoshis * 1;
|
||||||
await u.saveBalance(userBalance);
|
await u.saveBalance(userBalance);
|
||||||
|
await u.savePaidLndInvoice({
|
||||||
|
timestamp: parseInt(+new Date() / 1000),
|
||||||
|
type: 'paid_invoice',
|
||||||
|
value: info.num_satoshis * 1,
|
||||||
|
fee: 0, // internal invoices are free
|
||||||
|
memo: decodeURIComponent(info.description),
|
||||||
|
});
|
||||||
|
|
||||||
await u.setPaymentHashPaid(info.payment_hash);
|
await UserPayee.setPaymentHashPaid(info.payment_hash);
|
||||||
|
|
||||||
return res.send(info);
|
return res.send(info);
|
||||||
}
|
}
|
||||||
@@ -151,7 +165,7 @@ router.post('/payinvoice', async function(req, res) {
|
|||||||
return errorLnd(res);
|
return errorLnd(res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let inv = { payment_request: req.body.invoice };
|
let inv = { payment_request: req.body.invoice, amt: info.num_satoshis }; // amt is used only for 'tip' invoices
|
||||||
call.write(inv);
|
call.write(inv);
|
||||||
} else {
|
} else {
|
||||||
return errorNotEnougBalance(res);
|
return errorNotEnougBalance(res);
|
||||||
@@ -207,9 +221,14 @@ router.get('/gettxs', async function(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(await u.getAddress())) await u.generateAddress(); // onchain addr needed further
|
if (!(await u.getAddress())) await u.generateAddress(); // onchain addr needed further
|
||||||
await u.accountForPosibleTxids();
|
try {
|
||||||
let txs = await u.getTxs();
|
await u.accountForPosibleTxids();
|
||||||
res.send(txs);
|
let txs = await u.getTxs();
|
||||||
|
res.send(txs);
|
||||||
|
} catch (Err) {
|
||||||
|
console.log(Err);
|
||||||
|
res.send([]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/getuserinvoices', async function(req, res) {
|
router.get('/getuserinvoices', async function(req, res) {
|
||||||
|
|||||||
@@ -4,16 +4,63 @@ let fs = require('fs');
|
|||||||
let mustache = require('mustache');
|
let mustache = require('mustache');
|
||||||
let lightning = require('../lightning');
|
let lightning = require('../lightning');
|
||||||
|
|
||||||
router.get('/', function(req, res) {
|
let lightningGetInfo = {};
|
||||||
let html = fs.readFileSync('./templates/index.html').toString('utf8');
|
let lightningListChannels = {};
|
||||||
|
function updateLightning() {
|
||||||
lightning.getInfo({}, function(err, info) {
|
lightning.getInfo({}, function(err, info) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('lnd failure');
|
console.error('lnd failure');
|
||||||
process.exit(3);
|
process.exit(3);
|
||||||
}
|
}
|
||||||
res.setHeader('Content-Type', 'text/html');
|
lightningGetInfo = info;
|
||||||
return res.status(200).send(mustache.render(html, info));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
lightning.listChannels({}, function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
console.error('lnd failure');
|
||||||
|
process.exit(3);
|
||||||
|
}
|
||||||
|
lightningListChannels = response;
|
||||||
|
let channels = [];
|
||||||
|
for (let channel of lightningListChannels.channels) {
|
||||||
|
let divider = 524287;
|
||||||
|
let ascii_length1 = channel.local_balance / divider;
|
||||||
|
let ascii_length2 = channel.remote_balance / divider;
|
||||||
|
channel.ascii = '[';
|
||||||
|
channel.ascii += '-'.repeat(Math.round(ascii_length1));
|
||||||
|
channel.ascii += '/' + '-'.repeat(Math.round(ascii_length2));
|
||||||
|
channel.ascii += ']';
|
||||||
|
channel.capacity_btc = channel.capacity / 100000000;
|
||||||
|
channel.name = pubkey2name[channel.remote_pubkey];
|
||||||
|
channels.push(channel);
|
||||||
|
}
|
||||||
|
lightningListChannels.channels = channels;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateLightning();
|
||||||
|
setInterval(updateLightning, 60000);
|
||||||
|
|
||||||
|
const pubkey2name = {
|
||||||
|
'03e50492eab4107a773141bb419e107bda3de3d55652e6e1a41225f06a0bbf2d56': 'yalls.org',
|
||||||
|
'0232e20e7b68b9b673fb25f48322b151a93186bffe4550045040673797ceca43cf': 'zigzag.io',
|
||||||
|
'02df5ffe895c778e10f7742a6c5b8a0cefbe9465df58b92fadeb883752c8107c8f': 'blockstream store',
|
||||||
|
'030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f': 'bitrefill.com',
|
||||||
|
'03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f': 'ACINQ',
|
||||||
|
'03abf6f44c355dec0d5aa155bdbdd6e0c8fefe318eff402de65c6eb2e1be55dc3e': 'OpenNode',
|
||||||
|
'0242a4ae0c5bef18048fbecf995094b74bfb0f7391418d71ed394784373f41e4f3': 'coingate.com',
|
||||||
|
'0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4': 'ln1.satoshilabs.com',
|
||||||
|
'02c91d6aa51aa940608b497b6beebcb1aec05be3c47704b682b3889424679ca490': 'lnd-21.LNBIG.com',
|
||||||
|
'024655b768ef40951b20053a5c4b951606d4d86085d51238f2c67c7dec29c792ca': 'satoshis.place',
|
||||||
|
};
|
||||||
|
|
||||||
|
router.get('/', function(req, res) {
|
||||||
|
if (!lightningGetInfo) {
|
||||||
|
console.error('lnd failure');
|
||||||
|
process.exit(3);
|
||||||
|
}
|
||||||
|
res.setHeader('Content-Type', 'text/html');
|
||||||
|
let html = fs.readFileSync('./templates/index.html').toString('utf8');
|
||||||
|
return res.status(200).send(mustache.render(html, Object.assign({}, lightningGetInfo, lightningListChannels)));
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/about', function(req, res) {
|
router.get('/about', function(req, res) {
|
||||||
|
|||||||
28
package-lock.json
generated
28
package-lock.json
generated
@@ -2368,11 +2368,13 @@
|
|||||||
},
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -2385,15 +2387,18 @@
|
|||||||
},
|
},
|
||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -2496,7 +2501,8 @@
|
|||||||
},
|
},
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@@ -2506,6 +2512,7 @@
|
|||||||
"is-fullwidth-code-point": {
|
"is-fullwidth-code-point": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -2518,17 +2525,20 @@
|
|||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@@ -2545,6 +2555,7 @@
|
|||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@@ -2617,7 +2628,8 @@
|
|||||||
},
|
},
|
||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@@ -2627,6 +2639,7 @@
|
|||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@@ -2732,6 +2745,7 @@
|
|||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "LndHub",
|
"name": "LndHub",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -44,6 +44,19 @@
|
|||||||
{{#uris}}
|
{{#uris}}
|
||||||
<pre class="line">{{.}}</pre>
|
<pre class="line">{{.}}</pre>
|
||||||
{{/uris}}
|
{{/uris}}
|
||||||
|
<pre class="line"> </pre>
|
||||||
|
<pre class="line"><span class="dyer-white">Channels:</span></pre>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
{{#channels}}
|
||||||
|
<tr>
|
||||||
|
<td><pre class="line">{{ascii}}</pre></td>
|
||||||
|
<td><pre class="line">{{capacity_btc}} BTC </pre></td>
|
||||||
|
<td><pre class="line"><a href="https://1ml.com/node/{{remote_pubkey}}" target="_blank">{{remote_pubkey}}</a> {{name}} </pre></td>
|
||||||
|
</tr>
|
||||||
|
{{/channels}}
|
||||||
|
</table>
|
||||||
|
|
||||||
<pre class="line"> </pre>
|
<pre class="line"> </pre>
|
||||||
<pre class="line"><span class="dyer-white">num_active_channels:</span></pre>
|
<pre class="line"><span class="dyer-white">num_active_channels:</span></pre>
|
||||||
<pre class="line">{{num_active_channels}}</pre>
|
<pre class="line">{{num_active_channels}}</pre>
|
||||||
|
|||||||
Reference in New Issue
Block a user