parent
f83fa33a34
commit
1b86a8bc84
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],f=r[2],p=0,s=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"9f5a5551675b6e3c39b6",6:"23ff3e765459f2da33da",7:"417208cf5491f2b427d2"}[e]+".js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([]);
|
@ -0,0 +1 @@
|
||||
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],f=r[2],p=0,d=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&d.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);d.length;)d.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"bd61e6826dbafb306978",6:"04daddbdac8cd62e9aea",7:"4a4cbdfbbc02f4356464",8:"65561c0d66d24e36d541"}[e]+".js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,222 @@
|
||||
var request = require('request-promise');
|
||||
var common = require('../../common');
|
||||
var logger = require('../logger');
|
||||
const { resolve } = require('path');
|
||||
var options = {};
|
||||
|
||||
simplifyAllChannels = (channels) => {
|
||||
let channelNodeIds = '';
|
||||
let simplifiedChannels = [];
|
||||
channels.forEach(channel => {
|
||||
channelNodeIds = channelNodeIds + ',' + channel.nodeId;
|
||||
simplifiedChannels.push({
|
||||
nodeId: channel.nodeId ? channel.nodeId : '',
|
||||
channelId: channel.channelId ? channel.channelId : '',
|
||||
state: channel.state ? channel.state : '',
|
||||
channelFlags: channel.data && channel.data.commitments && channel.data.commitments.channelFlags ? channel.data.commitments.channelFlags : 0,
|
||||
toLocal: (channel.data.commitments.localCommit.spec.toLocal) ? Math.round(+channel.data.commitments.localCommit.spec.toLocal/1000) : 0,
|
||||
toRemote: (channel.data.commitments.localCommit.spec.toRemote) ? Math.round(+channel.data.commitments.localCommit.spec.toRemote/1000) : 0,
|
||||
shortChannelId: channel.data && channel.data.shortChannelId ? channel.data.shortChannelId : '',
|
||||
buried: channel.data && channel.data.buried ? channel.data.buried : false,
|
||||
feeBaseMsat: channel.data && channel.data.channelUpdate && channel.data.channelUpdate.feeBaseMsat ? channel.data.channelUpdate.feeBaseMsat : 0,
|
||||
feeProportionalMillionths: channel.data && channel.data.channelUpdate && channel.data.channelUpdate.feeProportionalMillionths ? channel.data.channelUpdate.feeProportionalMillionths : 0,
|
||||
alias: ''
|
||||
});
|
||||
});
|
||||
channelNodeIds = channelNodeIds.substring(1);
|
||||
return new Promise(function(resolve, reject) {
|
||||
options.url = common.getSelLNServerUrl() + '/nodes';
|
||||
options.form = { nodeIds: channelNodeIds };
|
||||
request.post(options).then(function(nodes) {
|
||||
logger.info({fileName: 'Channels', msg: 'Filtered Nodes: ' + JSON.stringify(nodes)});
|
||||
simplifiedChannels.map(channel => {
|
||||
channel.alias = nodes.find(channelWithAlias => channel.nodeId === channelWithAlias.nodeId).alias;
|
||||
});
|
||||
resolve(simplifiedChannels);
|
||||
}).catch(err => {
|
||||
resolve(simplifiedChannels);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.getChannels = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/channels';
|
||||
options.form = {};
|
||||
if (req.query && req.query.nodeId) {
|
||||
options.form = req.query;
|
||||
logger.info({fileName: 'Channels', msg: 'Channels Node Id: ' + JSON.stringify(options.form)});
|
||||
}
|
||||
logger.info({fileName: 'Channels', msg: 'Options: ' + JSON.stringify(options)});
|
||||
request.post(options).then(function (body) {
|
||||
logger.info({fileName: 'Channels', msg: 'All Channels: ' + JSON.stringify(body)});
|
||||
let channelTotal = 0;
|
||||
let totalLocalBalance = 0;
|
||||
let totalRemoteBalance = 0;
|
||||
let lightningBalances = { localBalance: 0, remoteBalance: 0 };
|
||||
let channelStatus = {active: { channels: 0, capacity: 0 }, inactive: { channels: 0, capacity: 0 }, pending: { channels: 0, capacity: 0 }};
|
||||
let activeChannels = [];
|
||||
let pendingChannels = [];
|
||||
let inactiveChannels = [];
|
||||
if(body && body.length) {
|
||||
simplifyAllChannels(body).then(function(simplifiedChannels) {
|
||||
logger.info({fileName: 'Channels', msg: 'Simplified Channels with Alias: ' + JSON.stringify(simplifiedChannels)});
|
||||
simplifiedChannels.forEach((channel, i) => {
|
||||
if (channel.state === 'NORMAL') {
|
||||
channelTotal = channel.toLocal + channel.toRemote;
|
||||
totalLocalBalance = totalLocalBalance + channel.toLocal;
|
||||
totalRemoteBalance = totalRemoteBalance + channel.toRemote;
|
||||
channel.balancedness = (channelTotal == 0) ? 1 : (1 - Math.abs((channel.toLocal-channel.toRemote)/channelTotal)).toFixed(3);
|
||||
activeChannels.push(channel);
|
||||
channelStatus.active.channels = channelStatus.active.channels + 1;
|
||||
channelStatus.active.capacity = channelStatus.active.capacity + channel.toLocal;
|
||||
} else if (channel.state.includes('WAIT') || channel.state.includes('CLOSING') || channel.state.includes('SYNCING')) {
|
||||
channel.state = channel.state.replace(/_/g, ' ');
|
||||
pendingChannels.push(channel);
|
||||
channelStatus.pending.channels = channelStatus.pending.channels + 1;
|
||||
channelStatus.pending.capacity = channelStatus.pending.capacity + channel.toLocal;
|
||||
} else {
|
||||
channel.state = channel.state.replace(/_/g, ' ');
|
||||
inactiveChannels.push(channel);
|
||||
channelStatus.inactive.channels = channelStatus.inactive.channels + 1;
|
||||
channelStatus.inactive.capacity = channelStatus.inactive.capacity + channel.toLocal;
|
||||
}
|
||||
});
|
||||
lightningBalances = { localBalance: totalLocalBalance, remoteBalance: totalRemoteBalance };
|
||||
activeChannels = common.sortDescByKey(activeChannels, 'balancedness');
|
||||
logger.info({fileName: 'Channels', msg: 'Lightning Balances: ' + JSON.stringify(lightningBalances)});
|
||||
logger.info({fileName: 'Channels', msg: 'Active Channels: ' + JSON.stringify(activeChannels)});
|
||||
logger.info({fileName: 'Channels', msg: 'Pending Channels: ' + JSON.stringify(pendingChannels)});
|
||||
logger.info({fileName: 'Channels', msg: 'Inactive Channels: ' + JSON.stringify(inactiveChannels)});
|
||||
res.status(200).json({activeChannels: activeChannels, pendingChannels: pendingChannels, inactiveChannels: inactiveChannels, lightningBalances: lightningBalances, channelStatus: channelStatus});
|
||||
});
|
||||
} else {
|
||||
res.status(200).json({activeChannels: activeChannels, pendingChannels: pendingChannels, inactiveChannels: inactiveChannels, lightningBalances: lightningBalances, channelStatus: channelStatus});
|
||||
}
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Channels', lineNum: 35, msg: 'Get Channels Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: 'Fetching Channels Failed!',
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.getChannelStats = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/channelstats';
|
||||
options.form = {};
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'ChannelStats', msg: 'Channel Stats Response: ' + JSON.stringify(body)});
|
||||
res.status(201).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'ChannelStats', lineNum: 54, msg: 'Get Channel Stats Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Channel Stats Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.openChannel = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/open';
|
||||
options.form = req.body;
|
||||
logger.info({fileName: 'Channels', msg: 'Open Channel Params: ' + JSON.stringify(options.form)});
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Channels', msg: 'Open Channel Response: ' + JSON.stringify(body)});
|
||||
if(!body || body.error) {
|
||||
logger.error({fileName: 'Channels', lineNum: 140, msg: 'Open Channel Error: ' + ((!body || !body.error) ? 'Error From Server!' : JSON.stringify(body.error))});
|
||||
res.status(500).json({
|
||||
message: 'Open Channel Failed!',
|
||||
error: (!body) ? 'Error From Server!' : body.error
|
||||
});
|
||||
} else {
|
||||
res.status(201).json(body);
|
||||
}
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Channels', lineNum: 58, msg: 'Open Channel Failed: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Open Channel Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.updateChannelRelayFee = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/updaterelayfee';
|
||||
options.form = req.query;
|
||||
logger.info({fileName: 'Channels', msg: 'Update Relay Fee Params: ' + JSON.stringify(options.form)});
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Channels', msg: 'Update Relay Fee Response: ' + JSON.stringify(body)});
|
||||
res.status(201).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Channels', lineNum: 186, msg: 'Update Relay Fee Failed: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Update Relay Fee Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.closeChannel = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
if (!req.query.force) {
|
||||
options.url = common.getSelLNServerUrl() + '/close';
|
||||
} else {
|
||||
options.url = common.getSelLNServerUrl() + '/forceclose';
|
||||
}
|
||||
options.form = { channelId: req.query.channelId };
|
||||
logger.info({fileName: 'Channels', msg: 'Close Channel Params: ' + JSON.stringify(options.form)});
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Channels', msg: 'Close Channel Response: ' + JSON.stringify(body)});
|
||||
res.status(204).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Channels', lineNum: 217, msg: 'Close Channel Failed: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Close Channel Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
var request = require('request-promise');
|
||||
var common = require('../../common');
|
||||
var logger = require('../logger');
|
||||
var options = {};
|
||||
|
||||
exports.getFees = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/audit';
|
||||
tillToday = Math.floor(Date.now() / 1000);
|
||||
fromLastMonth = tillToday - (86400 * 30);
|
||||
options.form = {
|
||||
from: fromLastMonth,
|
||||
to: tillToday
|
||||
};
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Fees', msg: 'Audit Response: ' + JSON.stringify(body)});
|
||||
let resBody = {
|
||||
fees: {daily_fee: 0, daily_txs: 0, weekly_fee: 0, weekly_txs: 0, monthly_fee: 0, monthly_txs: 0 },
|
||||
payments: {
|
||||
sent: body && body.sent ? body.sent : [],
|
||||
received: body && body.received ? body.received : [],
|
||||
relayed: body && body.relayed ? body.relayed : []
|
||||
}
|
||||
};
|
||||
let current_time = Math.round((new Date().getTime()) / 1000);
|
||||
let month_start_time = current_time - 2629743;
|
||||
let week_start_time = current_time - 604800;
|
||||
let day_start_time = current_time - 86400;
|
||||
let fee = 0;
|
||||
resBody.payments.sent.forEach(sentEle => {
|
||||
if (sentEle.recipientAmount) { sentEle.recipientAmount = Math.round(sentEle.recipientAmount/1000); }
|
||||
if (sentEle.parts && sentEle.parts.length > 0) {
|
||||
sentEle.firstPartTimestamp = sentEle.parts[0].timestamp;
|
||||
sentEle.firstPartTimestampStr = (!sentEle.firstPartTimestamp) ? '' : common.convertTimestampToDate(Math.round(sentEle.firstPartTimestamp / 1000));
|
||||
}
|
||||
sentEle.parts.forEach(part => {
|
||||
part.timestampStr = (!part.timestamp) ? '' : common.convertTimestampToDate(Math.round(part.timestamp / 1000));
|
||||
if (part.amount) { part.amount = Math.round(part.amount/1000); }
|
||||
if (part.feesPaid) { part.feesPaid = Math.round(part.feesPaid/1000); }
|
||||
});
|
||||
});
|
||||
resBody.payments.received.forEach(receivedEle => {
|
||||
if (receivedEle.parts && receivedEle.parts.length > 0) {
|
||||
receivedEle.firstPartTimestamp = receivedEle.parts[0].timestamp;
|
||||
receivedEle.firstPartTimestampStr = (!receivedEle.firstPartTimestamp) ? '' : common.convertTimestampToDate(Math.round(receivedEle.firstPartTimestamp / 1000));
|
||||
}
|
||||
receivedEle.parts.forEach(part => {
|
||||
part.timestampStr = (!part.timestamp) ? '' : common.convertTimestampToDate(Math.round(part.timestamp / 1000));
|
||||
if (part.amount) { part.amount = Math.round(part.amount/1000); }
|
||||
});
|
||||
});
|
||||
resBody.payments.relayed.forEach(relayedEle => {
|
||||
logger.info({fileName: 'Fees', msg: 'Relayed Transaction: ' + JSON.stringify(relayedEle)});
|
||||
relayedEle.timestampStr = (!relayedEle.timestamp) ? '' : common.convertTimestampToDate(Math.round(relayedEle.timestamp / 1000));
|
||||
if (relayedEle.amountIn) { relayedEle.amountIn = Math.round(relayedEle.amountIn/1000); }
|
||||
if (relayedEle.amountOut) { relayedEle.amountOut = Math.round(relayedEle.amountOut/1000); }
|
||||
fee = relayedEle.amountIn - relayedEle.amountOut;
|
||||
if (relayedEle.timestamp >= day_start_time) {
|
||||
resBody.fees.daily_fee = resBody.fees.daily_fee + fee;
|
||||
resBody.fees.daily_txs = resBody.fees.daily_txs + 1;
|
||||
}
|
||||
if (relayedEle.timestamp >= week_start_time) {
|
||||
resBody.fees.weekly_fee = resBody.fees.weekly_fee + fee;
|
||||
resBody.fees.weekly_txs = resBody.fees.weekly_txs + 1;
|
||||
}
|
||||
if (relayedEle.timestamp >= month_start_time) {
|
||||
resBody.fees.monthly_fee = resBody.fees.monthly_fee + fee;
|
||||
resBody.fees.monthly_txs = resBody.fees.monthly_txs + 1;
|
||||
}
|
||||
});
|
||||
resBody.payments.sent = common.sortDescByKey(resBody.payments.sent, 'firstPartTimestamp');
|
||||
resBody.payments.received = common.sortDescByKey(resBody.payments.received, 'firstPartTimestamp');
|
||||
resBody.payments.relayed = common.sortDescByKey(resBody.payments.relayed, 'timestamp');
|
||||
logger.info({fileName: 'Fees', msg: JSON.stringify(resBody)});
|
||||
res.status(200).json(resBody);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Fees', lineNum: 57, msg: 'Get Fees Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Fetching Fees failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
@ -0,0 +1,44 @@
|
||||
var request = require('request-promise');
|
||||
var common = require('../../common');
|
||||
var logger = require('../logger');
|
||||
var options = {};
|
||||
|
||||
exports.getInfo = (req, res, next) => {
|
||||
common.setOptions();
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/getinfo';
|
||||
options.form = {};
|
||||
logger.info({fileName:'GetInfo', msg: 'Selected Node: ' + JSON.stringify(common.selectedNode.ln_node)});
|
||||
logger.info({fileName: 'GetInfo', msg: 'Calling Info from Eclair server url: ' + options.url});
|
||||
if (!options.headers || !options.headers.authorization) {
|
||||
logger.error({fileName: 'GetInfo', lineNum: 13, msg: 'Eclair Get info failed due to missing or wrong password!'});
|
||||
res.status(502).json({
|
||||
message: "Fetching Info Failed!",
|
||||
error: "Missing Or Wrong Password"
|
||||
});
|
||||
} else {
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'GetInfo', msg: JSON.stringify(body)});
|
||||
const body_str = (!body) ? '' : JSON.stringify(body);
|
||||
const search_idx = (!body) ? -1 : body_str.search('Not Found');
|
||||
body.currency_unit = 'BTC';
|
||||
body.smaller_currency_unit = 'Sats';
|
||||
body.lnImplementation = 'Eclair';
|
||||
res.status(200).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'GetInfo', lineNum: 57, msg: 'Get Info Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Fetching Info failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
@ -0,0 +1,116 @@
|
||||
var request = require('request-promise');
|
||||
var common = require('../../common');
|
||||
var logger = require('../logger');
|
||||
var options = {};
|
||||
var pendingInvoices = [];
|
||||
|
||||
getReceivedPaymentInfo = (invoice) => {
|
||||
let idx = -1;
|
||||
return new Promise(function(resolve, reject) {
|
||||
invoice.timestampStr = (!invoice.timestamp) ? '' : common.convertTimestampToDate(invoice.timestamp);
|
||||
invoice.expiresAt = (!invoice.expiry) ? null : (+invoice.timestamp + +invoice.expiry);
|
||||
invoice.expiresAtStr = (!invoice.expiresAt) ? '' : common.convertTimestampToDate(invoice.expiresAt);
|
||||
if (invoice.amount) { invoice.amount = Math.round(invoice.amount/1000); }
|
||||
idx = pendingInvoices.findIndex(pendingInvoice => invoice.serialized === pendingInvoice.serialized);
|
||||
if (idx < 0) {
|
||||
options.url = common.getSelLNServerUrl() + '/getreceivedinfo';
|
||||
options.form = { paymentHash: invoice.paymentHash };
|
||||
request(options).then(response => {
|
||||
invoice.status = response.status.type;
|
||||
invoice.amount = Math.round(response.status.amount/1000);
|
||||
if (response.status.receivedAt) {
|
||||
invoice.receivedAt = Math.round(response.status.receivedAt / 1000);
|
||||
invoice.receivedAtStr = common.convertTimestampToDate(invoice.receivedAt);
|
||||
}
|
||||
resolve(invoice);
|
||||
}).catch(err => {
|
||||
invoice.status = 'unknown';
|
||||
resolve(invoice);
|
||||
});
|
||||
} else {
|
||||
pendingInvoices.splice(idx, 1);
|
||||
invoice.status = 'unpaid';
|
||||
resolve(invoice);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports.listInvoices = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.form = {};
|
||||
options1 = JSON.parse(JSON.stringify(options));
|
||||
options1.url = common.getSelLNServerUrl() + '/listinvoices';
|
||||
options1.form = {};
|
||||
options2 = JSON.parse(JSON.stringify(options));
|
||||
options2.url = common.getSelLNServerUrl() + '/listpendinginvoices';
|
||||
options2.form = {};
|
||||
Promise.all([request(options1), request(options2)])
|
||||
.then(body => {
|
||||
logger.info({fileName: 'Invoice', msg: 'Invoices List Received: ' + JSON.stringify(body)});
|
||||
let invoices = (!body[0] || body[0].length <= 0) ? [] : body[0];
|
||||
pendingInvoices = (!body[1] || body[1].length <= 0) ? [] : body[1];
|
||||
if (invoices && invoices.length > 0) {
|
||||
Promise.all(invoices.map(invoice => getReceivedPaymentInfo(invoice)))
|
||||
.then(values => {
|
||||
body = common.sortDescByKey(invoices, 'expiresAt');
|
||||
logger.info({fileName: 'Invoice', msg: 'Final Invoices List: ' + JSON.stringify(invoices)});
|
||||
res.status(200).json(invoices);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Invoice', lineNum: 66, msg: 'List Invoices Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Fetching Invoices failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.status(200).json([]);
|
||||
}
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Invoice', lineNum: 84, msg: 'List Invoices Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Fetching Invoices failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.createInvoice = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/createinvoice';
|
||||
options.form = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Invoice', msg: 'Create Invoice Response: ' + JSON.stringify(body)});
|
||||
if (body.amount) { body.amount = Math.round(body.amount/1000); }
|
||||
res.status(201).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Invoice', lineNum: 108, msg: 'Create Invoice Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Create Invoice Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
@ -0,0 +1,31 @@
|
||||
var request = require('request-promise');
|
||||
var common = require('../../common');
|
||||
var logger = require('../logger');
|
||||
var options = {};
|
||||
|
||||
exports.getNodes = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/nodes';
|
||||
options.form = { nodeIds: req.params.id };
|
||||
request.post(options).then(function (body) {
|
||||
logger.info({fileName: 'Network', msg: 'Node Lookup: ' + JSON.stringify(body)});
|
||||
body.forEach(node => {
|
||||
node.timestampStr = (node.timestamp) ? common.convertTimestampToDate(node.timestamp) : '';
|
||||
});
|
||||
res.status(200).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Network', lineNum: 49, msg: 'Node Lookup Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: 'Node Lookup Failed!',
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
@ -0,0 +1,127 @@
|
||||
var request = require('request-promise');
|
||||
var common = require('../../common');
|
||||
var logger = require('../logger');
|
||||
var options = {};
|
||||
|
||||
exports.getNewAddress = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/getnewaddress';
|
||||
options.form = {};
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Onchain', msg: JSON.stringify(body)});
|
||||
res.status(200).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Onchain', lineNum: 21, msg: 'Get New Address Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Getting New Address failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.getBalance = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/onchainbalance';
|
||||
options.form = {};
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Onchain', msg: 'Balance Received: ' + JSON.stringify(body)});
|
||||
if(!body.confirmed) {
|
||||
body.confirmed = 0;
|
||||
body.btc_confirmed = 0;
|
||||
} else {
|
||||
body.btc_confirmed = common.convertToBTC(body.confirmed);
|
||||
}
|
||||
if(!body.unconfirmed) {
|
||||
body.unconfirmed = 0;
|
||||
body.btc_unconfirmed = 0;
|
||||
} else {
|
||||
body.btc_unconfirmed = common.convertToBTC(body.unconfirmed);
|
||||
}
|
||||
body.total = +body.confirmed + +body.unconfirmed;
|
||||
body.btc_total = +body.btc_confirmed + +body.btc_unconfirmed;
|
||||
res.status(200).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Onchain', lineNum: 58, msg: 'Fetch Balance Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Fetching balance failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.getTransactions = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/onchaintransactions';
|
||||
options.form = {
|
||||
count: req.query.count,
|
||||
skip: req.query.skip
|
||||
};
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Transactions', msg: 'Transaction Received: ' + JSON.stringify(body)});
|
||||
if (body && body.length > 0) {
|
||||
body.forEach(transaction => {
|
||||
transaction.timestampStr = (!transaction.timestamp) ? '' : common.convertTimestampToDate(transaction.timestamp);
|
||||
});
|
||||
body = common.sortDescByKey(body, 'timestamp');
|
||||
}
|
||||
res.status(200).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Onchain', lineNum: 101, msg: 'Get Transactions Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Getting transactions failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.sendFunds = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/sendonchain';
|
||||
options.form = {
|
||||
address: req.body.address,
|
||||
amountSatoshis: req.body.amount,
|
||||
confirmationTarget: req.body.blocks
|
||||
};
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Onchain', msg: 'Send Funds Response: ' + JSON.stringify(body)});
|
||||
res.status(201).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Onchain', lineNum: 129, msg: 'Send Funds Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Send funds failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
@ -0,0 +1,107 @@
|
||||
var request = require('request-promise');
|
||||
var common = require('../../common');
|
||||
var logger = require('../logger');
|
||||
var options = {};
|
||||
|
||||
getQueryNodes = (nodeIds) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
options.url = common.getSelLNServerUrl() + '/nodes';
|
||||
options.form = { nodeIds: nodeIds };
|
||||
request.post(options).then(function(nodes) {
|
||||
logger.info({fileName: 'Payments', msg: 'Query Nodes: ' + JSON.stringify(nodes)});
|
||||
resolve(nodes);
|
||||
}).catch(err => {
|
||||
resolve([]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.decodePayment = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/parseinvoice';
|
||||
options.form = { invoice: req.params.invoice };
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Payments', msg: 'Payment Decode Received: ' + JSON.stringify(body)});
|
||||
body.timestampStr = (!body.timestamp) ? '' : common.convertTimestampToDate(body.timestamp);
|
||||
if (body.amount) { body.amount = Math.round(body.amount/1000); }
|
||||
res.status(200).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Payments', lineNum: 22, msg: 'Payment Decode Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Payment Decode Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.postPayment = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/payinvoice';
|
||||
options.form = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Payments', msg: 'Send Payment Response: ' + JSON.stringify(body)});
|
||||
res.status(201).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Payments', lineNum: 46, msg: 'Send Payment Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Send Payment Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.queryPaymentRoute = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/findroutetonode';
|
||||
options.form = {
|
||||
nodeId: req.query.nodeId,
|
||||
amountMsat: req.query.amountMsat
|
||||
};
|
||||
request.post(options).then((body) => {
|
||||
logger.info({fileName: 'Payments', msg: 'Query Payment Route Received: ' + JSON.stringify(body)});
|
||||
if (body && body.length) {
|
||||
let queryRoutes = [];
|
||||
getQueryNodes(body).then(function(hopsWithAlias) {
|
||||
let foundPeer = {};
|
||||
body.map(hop => {
|
||||
foundPeer = hopsWithAlias.find(hopWithAlias => hop === hopWithAlias.nodeId);
|
||||
queryRoutes.push({nodeId: hop, alias: foundPeer ? foundPeer.alias : ''});
|
||||
});
|
||||
logger.info({fileName: 'Payments', msg: 'Query Routes with Alias: ' + JSON.stringify(queryRoutes)});
|
||||
res.status(200).json(queryRoutes);
|
||||
});
|
||||
} else {
|
||||
res.status(200).json([]);
|
||||
}
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Payments', lineNum: 109, msg: 'Query Payment Route Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Query Payment Route Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
@ -0,0 +1,153 @@
|
||||
var request = require('request-promise');
|
||||
var common = require('../../common');
|
||||
var logger = require('../logger');
|
||||
var options = {};
|
||||
|
||||
getFilteredNodes = (peersNodeIds) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
options.url = common.getSelLNServerUrl() + '/nodes';
|
||||
options.form = { nodeIds: peersNodeIds };
|
||||
request.post(options).then(function(nodes) {
|
||||
logger.info({fileName: 'Peers', msg: 'Filtered Nodes: ' + JSON.stringify(nodes)});
|
||||
resolve(nodes);
|
||||
}).catch(err => {
|
||||
resolve([]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.getPeers = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/peers';
|
||||
options.form = {};
|
||||
request.post(options).then(function (body) {
|
||||
logger.info({fileName: 'Peers', msg: 'Peers Received: ' + JSON.stringify(body)});
|
||||
if (body && body.length) {
|
||||
let peersNodeIds = '';
|
||||
body.forEach(peer => { peersNodeIds = peersNodeIds + ',' + peer.nodeId; });
|
||||
peersNodeIds = peersNodeIds.substring(1);
|
||||
getFilteredNodes(peersNodeIds).then(function(peersWithAlias) {
|
||||
let foundPeer = {};
|
||||
body.map(peer => {
|
||||
foundPeer = peersWithAlias.find(peerWithAlias => peer.nodeId === peerWithAlias.nodeId);
|
||||
peer.alias = foundPeer ? foundPeer.alias : '';
|
||||
});
|
||||
body = common.sortDescByStrKey(body, 'alias');
|
||||
logger.info({fileName: 'Peers', msg: 'Peers with Alias: ' + JSON.stringify(body)});
|
||||
res.status(200).json(body);
|
||||
});
|
||||
} else {
|
||||
res.status(200).json([]);
|
||||
}
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Peers', lineNum: 49, msg: 'Get Peers Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: 'Fetching Peers Failed!',
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.connectPeer = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/connect';
|
||||
options.form = {};
|
||||
if (req.query) {
|
||||
options.form = req.query;
|
||||
logger.info({fileName: 'Peers', msg: 'Connect Peer Params: ' + JSON.stringify(options.form)});
|
||||
}
|
||||
request.post(options, (error, response, body) => {
|
||||
logger.info({fileName: 'Peers', msg: 'Add Peer Response: ' + JSON.stringify(body)});
|
||||
if (body === 'already connected') {
|
||||
return res.status(500).json({
|
||||
message: "Connect Peer Failed!",
|
||||
error: "already connected"
|
||||
});
|
||||
}
|
||||
options.url = common.getSelLNServerUrl() + '/peers';
|
||||
options.form = {};
|
||||
request.post(options).then(function (body) {
|
||||
logger.info({fileName: 'Peers', msg: 'Peers Received: ' + JSON.stringify(body)});
|
||||
if (body && body.length) {
|
||||
let peersNodeIds = '';
|
||||
body.forEach(peer => { peersNodeIds = peersNodeIds + ',' + peer.nodeId; });
|
||||
peersNodeIds = peersNodeIds.substring(1);
|
||||
getFilteredNodes(peersNodeIds).then(function(peersWithAlias) {
|
||||
body.map(peer => {
|
||||
peer.alias = peersWithAlias.find(peerWithAlias => peer.nodeId === peerWithAlias.nodeId).alias;
|
||||
});
|
||||
let peers = (body) ? common.sortDescByStrKey(body, 'alias') : [];
|
||||
peers = common.newestOnTop(peers, 'nodeId', req.query.uri ? req.query.uri.substring(0, req.query.uri.indexOf('@')) : req.query.nodeId ? req.query.nodeId : '');
|
||||
logger.info({fileName: 'Peers', msg: 'Peer with Newest On Top: ' + JSON.stringify(peers)});
|
||||
logger.info({fileName: 'Peers', msg: 'Peer Added Successfully'});
|
||||
res.status(201).json(peers);
|
||||
});
|
||||
} else {
|
||||
res.status(201).json([]);
|
||||
}
|
||||
}).catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Peers', lineNum: 89, msg: 'Connect Peer Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Connect Peer Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
}).catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Peers', lineNum: 103, msg: 'Connect Peer Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Connect Peer Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.deletePeer = (req, res, next) => {
|
||||
options = common.getOptions();
|
||||
options.url = common.getSelLNServerUrl() + '/disconnect';
|
||||
options.form = {};
|
||||
if (req.params.nodeId) {
|
||||
options.form = { nodeId: req.params.nodeId };
|
||||
logger.info({fileName: 'Peers', msg: 'Disconnect Peer Params: ' + JSON.stringify(options.form)});
|
||||
}
|
||||
request.post(options, (error, response, body) => {
|
||||
logger.info({fileName: 'Peers', msg: 'Disconnect Peer Response: ' + JSON.stringify(body)});
|
||||
logger.info({fileName: 'Peers', msg: 'Peer Disconnected: ' + req.params.nodeId});
|
||||
res.status(204).json(body);
|
||||
})
|
||||
.catch(errRes => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err.options && err.options.headers && err.options.headers.authorization) {
|
||||
delete err.options.headers.authorization;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
|
||||
delete err.response.request.headers.authorization;
|
||||
}
|
||||
logger.error({fileName: 'Peers', lineNum: 132, msg: 'Disconnect Peer Error: ' + JSON.stringify(err)});
|
||||
return res.status(err.statusCode ? err.statusCode : 500).json({
|
||||
message: "Disconnect Peer Failed!",
|
||||
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
|
||||
});
|
||||
});
|
||||
};
|
@ -0,0 +1,98 @@
|
||||
![](../screenshots/RTL-ECL-Dashboard.png)
|
||||
|
||||
## RTL Eclair setup
|
||||
|
||||
* [Introduction](#intro)
|
||||
* [Pre-requisite](#prereq)
|
||||
* [Architecture](#arch)
|
||||
* [Installation](#install)
|
||||
* [Prep for execution](#prep)
|
||||
* [Start the server and access the app](#start)
|
||||
|
||||
### <a name="intro"></a>Introduction
|
||||
RTL is now enabled to manage an Eclair node.
|
||||
|
||||
Follow the below steps to install and setup RTL to run on Eclair.
|
||||
|
||||
### <a name="prereq"></a>Pre-requisites:
|
||||
1. Functioning Eclair node
|
||||
2. NodeJS - Can be downloaded [here](https://nodejs.org/en/download)
|
||||
|
||||
### <a name="arch"></a>Architecture
|
||||
![](../screenshots/RTL-ECL-Arch-2.png)
|
||||
|
||||
### <a name="install"></a>Installation:
|
||||
#### First time setup
|
||||
* Fetch sources from RTL git repository, by executing the below on the command prompt:
|
||||
|
||||
`$ git clone https://github.com/Ride-The-Lightning/RTL.git`
|
||||
* Change directory to RTL folder:
|
||||
|
||||
`$ cd RTL`
|
||||
|
||||
* Fetch the production dependencies by running:
|
||||
`$ npm install --only=prod`
|
||||
|
||||
#### Or: Update existing build
|
||||
```
|
||||
$ cd RTL
|
||||
$ git reset --hard HEAD
|
||||
$ git clean -f -d
|
||||
$ git pull
|
||||
$ npm install --only=prod
|
||||
```
|
||||
### <a name="prep"></a>Prep for Execution
|
||||
RTL requires its own config file `RTL-Config.json`, to start the server and provide user authentication on the app.
|
||||
* Rename `sample-RTL-Config.json` file to `RTL-Config.json`.
|
||||
* Locate the complete path of the readable `eclair.conf` for your node.
|
||||
* Modify the RTL conf file per the example file below
|
||||
|
||||
Ensure that the follow values are correct per your config:
|
||||
* `lnImplementation` - This should be `ECL`, indicating that RTL is connecting to an Eclair node.
|
||||
* `lnServerUrl` - complete url with ip address and port of the eclair server.
|
||||
* `multiPass` - Specify the password (in plain text) to access RTL. This password will be hashed and not stored as plain text.
|
||||
* `configPath` (Mandatory) - Full path of the folder containing `eclair.conf` including the file name for the basic password authentication through `eclair.api.password`.
|
||||
|
||||
```
|
||||
{
|
||||
"port": "3000",
|
||||
"SSO": {
|
||||
"rtlSSO": 0,
|
||||
"rtlCookiePath": "",
|
||||
"logoutRedirectLink": ""
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"index": 1,
|
||||
"lnNode": "Eclair Testnet # 1",
|
||||
"lnImplementation": "ECL",
|
||||
"Authentication": {
|
||||
"configPath": "<Mandatory - Config file path, including .conf file, for authentication>"
|
||||
},
|
||||
"Settings": {
|
||||
"userPersona": "OPERATOR",
|
||||
"themeMode": "DAY",
|
||||
"themeColor": "PURPLE",
|
||||
"bitcoindConfigPath": "",
|
||||
"enableLogging": true,
|
||||
"fiatConversion": false,
|
||||
"lnServerUrl": "http://<eclair api server ip address>:port"
|
||||
}
|
||||
}
|
||||
],
|
||||
"multiPass": <password required for accessing RTL>
|
||||
}
|
||||
```
|
||||
### <a name="start"></a>Start the server and access the app
|
||||
Run the following command:
|
||||
|
||||
`$ node rtl`
|
||||
|
||||
If the server started successfully, you should get the below output on the console:
|
||||
|
||||
`$ Server is up and running, please open the UI at http://localhost:3000`
|
||||
|
||||
Open your browser at the following address: http://localhost:3000 to access the RTL app.
|
||||
|
||||
### Detailed config and instructions
|
||||
For detailed config and access options and other information, view the main readme page.
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@
|
||||
const ChannelsController = require("../../controllers/eclair/channels");
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const authCheck = require("../authCheck");
|
||||
|
||||
router.get("/", authCheck, ChannelsController.getChannels);
|
||||
router.get("/stats", authCheck, ChannelsController.getChannelStats);
|
||||
router.post("/", authCheck, ChannelsController.openChannel);
|
||||
router.post("/updateRelayFee", authCheck, ChannelsController.updateChannelRelayFee);
|
||||
router.delete("/", authCheck, ChannelsController.closeChannel);
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,8 @@
|
||||
const FeesController = require("../../controllers/eclair/fees");
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const authCheck = require("../authCheck");
|
||||
|
||||
router.get("/", authCheck, FeesController.getFees);
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,8 @@
|
||||
const infoController = require("../../controllers/eclair/getInfo");
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const authCheck = require("../authCheck");
|
||||
|
||||
router.get("/", authCheck, infoController.getInfo);
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,9 @@
|
||||
const invoicesController = require("../../controllers/eclair/invoices");
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const authCheck = require("../authCheck");
|
||||
|
||||
router.get("/", authCheck, invoicesController.listInvoices);
|
||||
router.post("/", authCheck, invoicesController.createInvoice);
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,8 @@
|
||||
const NetworkController = require("../../controllers/eclair/network");
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const authCheck = require("../authCheck");
|
||||
|
||||
router.get("/nodes/:id", authCheck, NetworkController.getNodes);
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,11 @@
|
||||
const OnChainController = require("../../controllers/eclair/onchain");
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const authCheck = require("../authCheck");
|
||||
|
||||
router.get("/", authCheck, OnChainController.getNewAddress);
|
||||
router.get("/balance/", authCheck, OnChainController.getBalance);
|
||||
router.get("/transactions/", authCheck, OnChainController.getTransactions);
|
||||
router.post("/", authCheck, OnChainController.sendFunds);
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,10 @@
|
||||
const PaymentsController = require("../../controllers/eclair/payments");
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const authCheck = require("../authCheck");
|
||||
|
||||
router.get("/route/", authCheck, PaymentsController.queryPaymentRoute);
|
||||
router.get("/:invoice", authCheck, PaymentsController.decodePayment);
|
||||
router.post("/", authCheck, PaymentsController.postPayment);
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,10 @@
|
||||
const PeersController = require("../../controllers/eclair/peers");
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const authCheck = require("../authCheck");
|
||||
|
||||
router.get("/", authCheck, PeersController.getPeers);
|
||||
router.post("/", authCheck, PeersController.connectPeer);
|
||||
router.delete("/:nodeId", authCheck, PeersController.deletePeer);
|
||||
|
||||
module.exports = router;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue