Release 0.10.1 (#605)

Dahboard layout fix #576
Boltz integration (#590)
Merged verify token and password authentication
Channel mobile view update
ECL Adding inactive channels force close
Flag Dust UTXOs
Bug fix for forwarding history browser crash #596
Label and Lease UTXOs
UI Table Fixes
App settings (#604)
Settings updates
UTXO lease confirmation box
Login and Settings page  without add new node
pull/609/head v0.10.1
ShahanaFarooqui 3 years ago committed by GitHub
parent d040ab891c
commit f817ae39bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -52,3 +52,4 @@ RTL.conf
RTL-1.conf
RTL-Multi-Node-Conf-1.json
RTL-Config-for-BTC-Testing.json
ECLDummyData.log

@ -94,8 +94,9 @@ Example RTL-Config.json:
"lnNode": "LND Testnet",
"lnImplementation": "LND",
"Authentication": {
"macaroonPath": "<Complete path of the folder containing admin.macaroon for the node # 1>",
"swapMacaroonPath": "<Complete path of the folder containing loop.macaroon for the node # 1>",
"macaroonPath": "<Complete path of the folder containing LND's admin.macaroon for the node # 1>",
"swapMacaroonPath": "<Complete path of the folder containing Loop's loop.macaroon for the node>",
"boltzMacaroonPath": "<Complete path of the folder containing Boltz admin.macaroon for the node>",
"configPath": "<Optional:Path of the .conf if present locally or empty>",
"lnApiPassword": "<Optional:Can be used to provide password in ECL implementation>"
},
@ -108,7 +109,8 @@ Example RTL-Config.json:
"enableLogging": true,
"fiatConversion": false,
"lnServerUrl": "<url for LND REST APIs for node #1 e.g. https://192.168.0.1:8080>",
"swapServerUrl": "<url for swap server REST APIs for the node. e.g. https://localhost:8081>"
"swapServerUrl": "<url for swap server REST APIs for the node. e.g. https://localhost:8081>",
"boltzServerUrl": "<url for boltz server REST APIs for the node. e.g. https://localhost:9003>"
}
}
]

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

@ -12,8 +12,8 @@
<link rel="mask-icon" href="assets/images/favicon-light/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="styles.ee9d4139f693ecb219aa.css"></head>
<link rel="stylesheet" href="styles.b19cbfbd6204e537cd8b.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.4560fb3bcc56015af5b6.js" defer></script><script src="polyfills.ea991b800cfaf577eb9d.js" defer></script><script src="main.a9c3fed74cd736cbe7ae.js" defer></script></body>
<script src="runtime.4a1371653e10aae2a656.js" defer></script><script src="polyfills.ea991b800cfaf577eb9d.js" defer></script><script src="main.bf1f3d303d9abc6dfc78.js" defer></script></body>
</html>

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:"d3191dc862bb96ad8a12",5:"3593974ed7a18cef9807",6:"a0ce69bc4fc32a59e836",7:"2a4fb50bff6654155ed9"}[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,c=r[0],i=r[1],f=r[2],p=0,s=[];p<c.length;p++)a=c[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[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,c=1;c<t.length;c++)0!==o[t[c]]&&(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,c=document.createElement("script");c.charset="utf-8",c.timeout=120,a.nc&&c.setAttribute("nonce",a.nc),c.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"731a8de203edc88f38d8",5:"3cc9f14aefc4012c6f28",6:"d59c34ac7722c1fea6aa",7:"3f5e1768ebd105934cfb"}[e]+".js"}(e);var i=new Error;u=function(r){c.onerror=c.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;i.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",i.name="ChunkLoadError",i.type=n,i.request=u,t[1](i)}o[e]=void 0}};var f=setTimeout(function(){u({type:"timeout",target:c})},12e4);c.onerror=c.onload=u,document.head.appendChild(c)}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 c=window.webpackJsonp=window.webpackJsonp||[],i=c.push.bind(c);c.push=r,c=c.slice();for(var f=0;f<c.length;f++)r(c[f]);var l=i;t()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -11,8 +11,11 @@ const apiLNDRoot = baseHref + "api/lnd/";
const apiCLRoot = baseHref + "api/cl/";
const apiECLRoot = baseHref + "api/ecl/";
const authenticateRoutes = require("./routes/authenticate");
const RTLConfRoutes = require("./routes/RTLConf");
const authenticateRoutes = require("./routes/shared/authenticate");
const RTLConfRoutes = require("./routes/shared/RTLConf");
const loopRoutes = require('./routes/shared/loop');
const boltzRoutes = require('./routes/shared/boltz');
const infoRoutes = require("./routes/lnd/getInfo");
const channelsRoutes = require("./routes/lnd/channels");
const channelsBackupRoutes = require("./routes/lnd/channelsBackup");
@ -27,7 +30,6 @@ const payReqRoutes = require("./routes/lnd/payReq");
const paymentsRoutes = require("./routes/lnd/payments");
const invoiceRoutes = require("./routes/lnd/invoices");
const switchRoutes = require("./routes/lnd/switch");
const loopRoutes = require('./routes/lnd/loop');
const messageRoutes = require("./routes/lnd/message");
const infoCLRoutes = require("./routes/c-lightning/getInfo");
@ -73,6 +75,8 @@ app.use((req, res, next) => {
app.use(apiRoot + "authenticate", authenticateRoutes);
app.use(apiRoot + "conf", RTLConfRoutes);
app.use(apiRoot + "boltz", boltzRoutes);
app.use(apiLNDRoot + "getinfo", infoRoutes);
app.use(apiLNDRoot + "channels", channelsRoutes);
app.use(apiLNDRoot + "channels/backup", channelsBackupRoutes);

@ -3,6 +3,7 @@ var crypto = require('crypto');
var path = require('path');
var common = {};
const MONTH_NAMES = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
var dummy_data_array_from_file = [];
common.rtl_conf_file_path = '';
common.rtl_pass = '';
@ -11,11 +12,12 @@ common.rtl_sso = 0;
common.port = 3000;
common.host = null;
common.rtl_cookie_path = '';
common.logout_redirect_link = '/login';
common.logout_redirect_link = '';
common.cookie = '';
common.secret_key = crypto.randomBytes(64).toString('hex');
common.nodes = [];
common.selectedNode = {};
common.read_dummy_data = false;
common.getSwapServerOptions = () => {
let swapOptions = {
@ -36,6 +38,25 @@ common.getSwapServerOptions = () => {
return swapOptions;
};
common.getBoltzServerOptions = () => {
let boltzOptions = {
url: common.selectedNode.boltz_server_url,
rejectUnauthorized: false,
json: true,
headers: {
'Grpc-Metadata-macaroon': ''
}
};
if (common.selectedNode.boltz_macaroon_path) {
try {
boltzOptions.headers = {'Grpc-Metadata-macaroon': fs.readFileSync(path.join(common.selectedNode.boltz_macaroon_path, 'admin.macaroon')).toString('hex')};
} catch(err) {
console.error('Boltz macaroon Error: ' + JSON.stringify(err));
}
}
return boltzOptions;
};
common.getSelLNServerUrl = () => {
return common.selectedNode.ln_server_url;
};
@ -131,7 +152,8 @@ common.findNode = (selNodeIndex) => {
}
common.replaceNode = (selNodeIndex, newNode) => {
common.nodes.splice(common.nodes.findIndex((node) => {node.index == selNodeIndex}), 1, newNode);
let foundIndex = common.nodes.findIndex((node) => node.index == selNodeIndex);
common.nodes.splice(foundIndex, 1, newNode);
common.selectedNode = common.findNode(selNodeIndex);
}
@ -210,5 +232,62 @@ common.getRequestIP = (req) => {
|| (req.connection.socket ? req.connection.socket.remoteAddress : null);
}
common.getDummyData = (data_key) => {
let dummyDataFile = common.rtl_conf_file_path + common.path_separator + 'ECLDummyData.log';
return new Promise(function(resolve, reject) {
if (dummy_data_array_from_file.length === 0) {
fs.readFile(dummyDataFile, 'utf8', function(err, data) {
if (err) {
if (err.code === 'ENOENT') {
console.error('Dummy data file does not exist!');
} else {
console.error('Getting dummy data failed!');
}
} else {
dummy_data_array_from_file = data.split('\n');
resolve(filterData(data_key));
}
});
} else {
resolve(filterData(data_key));
}
});
}
filterData = (data_key) => {
let search_string = '';
switch (data_key) {
case 'GetInfo':
search_string = 'INFO: GetInfo => Get Info Response: ';
break;
case 'Fees':
search_string = 'INFO: Fees => Fee Response: ';
break;
case 'Payments':
search_string = 'INFO: Fees => Payments Response: ';
break;
case 'OnChainBalance':
search_string = 'INFO: Onchain => Balance Received: ';
break;
case 'Peers':
search_string = 'INFO: Peers => Peers with Alias: ';
break;
case 'Channels':
search_string = 'INFO: Channels => Simplified Channels with Alias: ';
break;
default:
search_string = 'INFO: GetInfo => Get Info Response: ';
break;
}
let foundDataLine = dummy_data_array_from_file.find(dataItem => dataItem.includes(search_string));
let dataStr = foundDataLine ? foundDataLine.replace(search_string, '') : {};
return JSON.parse(dataStr);
}
module.exports = common;

@ -5,7 +5,7 @@ var crypto = require('crypto');
var hash = crypto.createHash('sha256');
var common = require('./common');
var path = require('path');
var logger = require('./controllers/logger');
var logger = require('./controllers/shared/logger');
var connect = {};
var errMsg = '';
var request = require('request');
@ -195,6 +195,16 @@ connect.validateNodeConfig = (config) => {
common.nodes[idx].swap_server_url = '';
common.nodes[idx].swap_macaroon_path = '';
}
if(process.env.BOLTZ_SERVER_URL && process.env.BOLTZ_SERVER_URL.trim() !== '') {
common.nodes[idx].boltz_server_url = process.env.BOLTZ_SERVER_URL.endsWith('/v1') ? process.env.BOLTZ_SERVER_URL.slice(0, -3) : process.env.BOLTZ_SERVER_URL;
common.nodes[idx].boltz_macaroon_path = process.env.BOLTZ_MACAROON_PATH;
} else if(node.Settings.boltzServerUrl && node.Settings.boltzServerUrl.trim() !== '') {
common.nodes[idx].boltz_server_url = node.Settings.boltzServerUrl.endsWith('/v1') ? node.Settings.boltzServerUrl.slice(0, -3) : node.Settings.boltzServerUrl;
common.nodes[idx].boltz_macaroon_path = node.Authentication.boltzMacaroonPath ? node.Authentication.boltzMacaroonPath : '';
} else {
common.nodes[idx].boltz_server_url = '';
common.nodes[idx].boltz_macaroon_path = '';
}
common.nodes[idx].bitcoind_config_path = process.env.BITCOIND_CONFIG_PATH ? process.env.BITCOIND_CONFIG_PATH : (node.Settings.bitcoindConfigPath) ? node.Settings.bitcoindConfigPath : '';
common.nodes[idx].enable_logging = (node.Settings.enableLogging) ? !!node.Settings.enableLogging : false;
common.nodes[idx].channel_backup_path = process.env.CHANNEL_BACKUP_PATH ? process.env.CHANNEL_BACKUP_PATH : (node.Settings.channelBackupPath) ? node.Settings.channelBackupPath : common.rtl_conf_file_path + common.path_separator + 'backup' + common.path_separator + 'node-' + node.index;
@ -243,22 +253,22 @@ connect.setSSOParams = (config) => {
} else if (config.SSO && config.SSO.rtlSSO) {
common.rtl_sso = config.SSO.rtlSSO;
}
if (process.env.RTL_COOKIE_PATH) {
common.rtl_cookie_path = process.env.RTL_COOKIE_PATH;
} else if (config.SSO && config.SSO.rtlCookiePath) {
common.rtl_cookie_path = config.SSO.rtlCookiePath;
} else {
common.rtl_cookie_path = '';
}
if (+common.rtl_sso) {
if (process.env.LOGOUT_REDIRECT_LINK) {
common.logout_redirect_link = process.env.LOGOUT_REDIRECT_LINK;
} else if (config.SSO && config.SSO.logoutRedirectLink) {
common.logout_redirect_link = config.SSO.logoutRedirectLink;
}
if (process.env.RTL_COOKIE_PATH) {
common.rtl_cookie_path = process.env.RTL_COOKIE_PATH;
} else if (config.SSO && config.SSO.rtlCookiePath) {
common.rtl_cookie_path = config.SSO.rtlCookiePath;
} else {
common.rtl_cookie_path = common.rtl_conf_file_path + '/cookies/auth.cookie';
}
if (process.env.LOGOUT_REDIRECT_LINK) {
common.logout_redirect_link = process.env.LOGOUT_REDIRECT_LINK;
} else if (config.SSO && config.SSO.logoutRedirectLink) {
common.logout_redirect_link = config.SSO.logoutRedirectLink;
}
if (+common.rtl_sso) {
if (!common.rtl_cookie_path || common.rtl_cookie_path.trim() === '') {
errMsg = 'Please set rtlCookiePath value for single sign on option!';
} else {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getBalance = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.listChannels = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getFees = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getInfo = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.deleteExpiredInvoice = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.signMessage = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getRoute = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getNewAddress = (req, res, next) => {
@ -58,7 +58,7 @@ exports.onChainWithdraw = (req, res, next) => {
});
}
exports.getTransactions = (req, res, next) => {
exports.getUTXOs = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/v1/listFunds';
request(options).then((body) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
function paymentReducer(accumulator, currentPayment) {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getPeers = (req, res, next) => {

@ -1,8 +1,47 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
arrangeChannels = (simplifiedChannels) => {
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 = [];
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)});
return ({activeChannels: activeChannels, pendingChannels: pendingChannels, inactiveChannels: inactiveChannels, lightningBalances: lightningBalances, channelStatus: channelStatus});
};
simplifyAllChannels = (channels) => {
let channelNodeIds = '';
let simplifiedChannels = [];
@ -51,66 +90,35 @@ exports.getChannels = (req, res, next) => {
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;
}
if (common.read_dummy_data) {
common.getDummyData('Channels').then(function(data) { res.status(200).json(arrangeChannels(data)); });
} else {
request.post(options).then(function (body) {
logger.info({fileName: 'Channels', msg: 'All Channels: ' + JSON.stringify(body)});
if(body && body.length) {
simplifyAllChannels(body).then(function(simplifiedChannels) {
logger.info({fileName: 'Channels', msg: 'Simplified Channels with Alias: ' + JSON.stringify(simplifiedChannels)});
res.status(200).json(arrangeChannels(simplifiedChannels));
});
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: [], pendingChannels: [], inactiveChannels: [], lightningBalances: { localBalance: 0, remoteBalance: 0 }, channelStatus: {active: { channels: 0, capacity: 0 }, inactive: { channels: 0, capacity: 0 }, pending: { channels: 0, capacity: 0 }}});
}
})
.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"
});
} 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) => {
@ -224,3 +232,4 @@ exports.closeChannel = (req, res, next) => {
});
});
}

@ -1,8 +1,75 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
arrangeFees = (body, current_time) => {
let fees = { daily_fee: 0, daily_txs: 0, weekly_fee: 0, weekly_txs: 0, monthly_fee: 0, monthly_txs: 0 };
let month_start_time = current_time - 2629743000;
let week_start_time = current_time - 604800000;
let day_start_time = current_time - 86400000;
let fee = 0;
body.relayed.forEach(relayedEle => {
logger.info({fileName: 'Fees', msg: 'Fee Relayed Transaction: ' + JSON.stringify(relayedEle)});
fee = Math.round((relayedEle.amountIn - relayedEle.amountOut)/1000);
if (relayedEle.timestamp >= day_start_time) {
fees.daily_fee = fees.daily_fee + fee;
fees.daily_txs = fees.daily_txs + 1;
}
if (relayedEle.timestamp >= week_start_time) {
fees.weekly_fee = fees.weekly_fee + fee;
fees.weekly_txs = fees.weekly_txs + 1;
}
if (relayedEle.timestamp >= month_start_time) {
fees.monthly_fee = fees.monthly_fee + fee;
fees.monthly_txs = fees.monthly_txs + 1;
}
});
logger.info({fileName: 'Fees', msg: JSON.stringify(fees)});
return fees;
};
arrangePayments = (body) => {
let payments = {
sent: body && body.sent ? body.sent : [],
received: body && body.received ? body.received : [],
relayed: body && body.relayed ? body.relayed : []
};
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); }
});
});
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); }
});
});
payments.relayed.forEach(relayedEle => {
logger.info({fileName: 'Fees', msg: 'Payment 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); }
});
payments.sent = common.sortDescByKey(payments.sent, 'firstPartTimestamp');
payments.received = common.sortDescByKey(payments.received, 'firstPartTimestamp');
payments.relayed = common.sortDescByKey(payments.relayed, 'timestamp');
logger.info({fileName: 'Fees', msg: JSON.stringify(payments)});
return payments;
};
exports.getFees = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/audit';
@ -13,106 +80,54 @@ exports.getFees = (req, res, next) => {
from: fromLastMonth,
to: tillToday
};
request.post(options).then((body) => {
logger.info({fileName: 'Fees', msg: 'Fee Response: ' + JSON.stringify(body)});
let fees = { daily_fee: 0, daily_txs: 0, weekly_fee: 0, weekly_txs: 0, monthly_fee: 0, monthly_txs: 0 };
let current_time = Math.round((new Date().getTime()));
let month_start_time = current_time - 2629743000;
let week_start_time = current_time - 604800000;
let day_start_time = current_time - 86400000;
let fee = 0;
body.relayed.forEach(relayedEle => {
logger.info({fileName: 'Fees', msg: 'Fee Relayed Transaction: ' + JSON.stringify(relayedEle)});
fee = Math.round((relayedEle.amountIn - relayedEle.amountOut)/1000);
if (relayedEle.timestamp >= day_start_time) {
fees.daily_fee = fees.daily_fee + fee;
fees.daily_txs = fees.daily_txs + 1;
if (common.read_dummy_data) {
common.getDummyData('Fees').then(function(data) { res.status(200).json(arrangeFees(data, 1609796725000)); });
} else {
request.post(options).then((body) => {
logger.info({fileName: 'Fees', msg: 'Fee Response: ' + JSON.stringify(body)});
res.status(200).json(arrangeFees(body, Math.round((new Date().getTime()))));
})
.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 (relayedEle.timestamp >= week_start_time) {
fees.weekly_fee = fees.weekly_fee + fee;
fees.weekly_txs = fees.weekly_txs + 1;
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
delete err.response.request.headers.authorization;
}
if (relayedEle.timestamp >= month_start_time) {
fees.monthly_fee = fees.monthly_fee + fee;
fees.monthly_txs = fees.monthly_txs + 1;
}
});
logger.info({fileName: 'Fees', msg: JSON.stringify(fees)});
res.status(200).json(fees);
})
.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: 51, 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"
logger.error({fileName: 'Fees', lineNum: 51, 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"
});
});
});
}
};
exports.getPayments = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/audit';
options.form = null;
request.post(options).then((body) => {
logger.info({fileName: 'Fees', msg: 'Payments Response: ' + JSON.stringify(body)});
let payments = {
sent: body && body.sent ? body.sent : [],
received: body && body.received ? body.received : [],
relayed: body && body.relayed ? body.relayed : []
};
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));
if (common.read_dummy_data) {
common.getDummyData('Payments').then(function(data) { res.status(200).json(arrangePayments(data)); });
} else {
request.post(options).then((body) => {
logger.info({fileName: 'Fees', msg: 'Payments Response: ' + JSON.stringify(body)});
res.status(200).json(arrangePayments(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;
}
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); }
});
});
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));
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.authorization) {
delete err.response.request.headers.authorization;
}
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); }
});
});
payments.relayed.forEach(relayedEle => {
logger.info({fileName: 'Fees', msg: 'Payment 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); }
});
payments.sent = common.sortDescByKey(payments.sent, 'firstPartTimestamp');
payments.received = common.sortDescByKey(payments.received, 'firstPartTimestamp');
payments.relayed = common.sortDescByKey(payments.relayed, 'timestamp');
logger.info({fileName: 'Fees', msg: JSON.stringify(payments)});
res.status(200).json(payments);
})
.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: 113, msg: 'Get Payments Error: ' + JSON.stringify(err)});
return res.status(err.statusCode ? err.statusCode : 500).json({
message: "Fetching Payments failed!",
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
logger.error({fileName: 'Fees', lineNum: 113, msg: 'Get Payments Error: ' + JSON.stringify(err)});
return res.status(err.statusCode ? err.statusCode : 500).json({
message: "Fetching Payments failed!",
error: err.error && err.error.error ? err.error.error : err.error ? err.error : "Unknown Server Error"
});
});
});
}
};

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getInfo = (req, res, next) => {
@ -10,35 +10,44 @@ exports.getInfo = (req, res, next) => {
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"
if (common.read_dummy_data) {
common.getDummyData('GetInfo').then(function(data) {
data.currency_unit = 'BTC';
data.smaller_currency_unit = 'Sats';
data.lnImplementation = 'Eclair';
res.status(200).json(data);
});
} 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"
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: 'Get Info Response: ' + 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"
});
});
}
}
};

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
var pendingInvoices = [];

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getNodes = (req, res, next) => {

@ -1,8 +1,26 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
arrangeBalances = (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;
return body;
};
exports.getNewAddress = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/getnewaddress';
@ -31,38 +49,28 @@ 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"
if (common.read_dummy_data) {
common.getDummyData('OnChainBalance').then(function(data) { res.status(200).json(arrangeBalances(data)); });
} else {
request.post(options).then((body) => {
logger.info({fileName: 'Onchain', msg: 'Balance Received: ' + JSON.stringify(body)});
res.status(200).json(arrangeBalances(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) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
getQueryNodes = (nodeIds) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
getFilteredNodes = (peersNodeIds) => {
@ -20,40 +20,44 @@ 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 : peer.nodeId.substring(0, 20);
if (common.read_dummy_data) {
common.getDummyData('Peers').then(function(data) { res.status(200).json(data); });
} else {
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 : peer.nodeId.substring(0, 20);
});
body = common.sortDescByStrKey(body, 'alias');
logger.info({fileName: 'Peers', msg: 'Peers with Alias: ' + JSON.stringify(body)});
res.status(200).json(body);
});
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"
});
} 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) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getBalance = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
getAliasForChannel = (channel) => {

@ -1,7 +1,7 @@
var request = require('request-promise');
var fs = require('fs');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
function getFilesList(callback) {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var swtch = require('./switch');
var options = {};

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var connect = require('../../connect');
var options = {};

@ -1,6 +1,6 @@
var request = require("request-promise");
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
getAliasFromPubkey = (pubkey) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getInvoice = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.signMessage = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getNewAddress = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.decodePayment = (req, res, next) => {

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getPayments = (req, res, next) => {

@ -1,13 +1,12 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
getAliasForPeers = (peer) => {
return new Promise(function(resolve, reject) {
options.url = common.getSelLNServerUrl() + '/v1/graph/node/' + peer.pub_key;
request(options)
.then(function(aliasBody) {
request(options).then(function(aliasBody) {
logger.info({fileName: 'Peers', msg: 'Alias: ' + JSON.stringify(aliasBody.node.alias)});
peer.alias = aliasBody.node.alias;
resolve(aliasBody.node.alias);

@ -1,7 +1,7 @@
var request = require('request-promise');
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
var num_max_events = 100;
var responseData = { forwarding_events: [], last_offset_index: 0 };

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.getTransactions = (req, res, next) => {

@ -1,7 +1,7 @@
var request = require('request-promise');
var common = require('../../common');
var atob = require('atob');
var logger = require('../logger');
var logger = require('../shared/logger');
var options = {};
exports.genSeed = (req, res, next) => {
@ -122,6 +122,7 @@ exports.getUTXOs = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/v2/wallet/utxos?max_confs=' + req.query.max_confs;
request.post(options).then((body) => {
logger.info({fileName: 'Wallet', msg: 'UTXO List Response: ' + JSON.stringify(body)});
res.status(200).json(body.utxos ? body.utxos : []);
})
.catch(errRes => {
@ -155,6 +156,7 @@ exports.bumpFee = (req, res, next) => {
}
options.form = JSON.stringify(options.form);
request.post(options).then((body) => {
logger.info({fileName: 'Wallet', msg: 'Bump Fee Response: ' + JSON.stringify(body)});
res.status(200).json(body);
})
.catch(errRes => {
@ -172,3 +174,93 @@ exports.bumpFee = (req, res, next) => {
});
});
}
exports.labelTransaction = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/v2/wallet/tx/label';
options.form = {};
options.form.txid = req.body.txid;
options.form.label = req.body.label;
options.form.overwrite = req.body.overwrite;
options.form = JSON.stringify(options.form);
logger.info({fileName: 'Wallet', msg: 'Label Transaction Options: ' + JSON.stringify(options.form)});
request.post(options).then((body) => {
logger.info({fileName: 'Wallet', msg: 'Label Transaction Post Response: ' + 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['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Wallet', lineNum: 253, msg: 'Label Transaction Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Transaction label failed!",
error: err.error
});
});
}
exports.leaseUTXO = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/v2/wallet/utxos/lease';
options.form = {};
options.form.id = req.body.txid;
options.form.outpoint = {
txid_bytes: req.body.txid,
output_index: req.body.outputIndex
};
options.form = JSON.stringify(options.form);
logger.info({fileName: 'Wallet', msg: 'UTXO Lease Options: ' + options.form});
request.post(options).then((body) => {
logger.info({fileName: 'Wallet', msg: 'UTXO Lease Response: ' + 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['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Wallet', lineNum: 197, msg: 'Lease UTXO Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Lease UTXO failed!",
error: err.error
});
});
}
exports.releaseUTXO = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/v2/wallet/utxos/release';
options.form = {};
options.form.id = req.body.txid;
options.form.outpoint = {
txid_bytes: req.body.txid,
output_index: req.body.outputIndex
};
options.form = JSON.stringify(options.form);
request.post(options).then((body) => {
logger.info({fileName: 'Wallet', msg: 'UTXO Release Response: ' + 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['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Wallet', lineNum: 226, msg: 'Release UTXO Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Release UTXO failed!",
error: err.error
});
});
}

@ -2,7 +2,7 @@ var ini = require('ini');
var parseHocon = require('hocon-parser');
var fs = require('fs');
var logger = require('./logger');
var common = require('../common');
var common = require('../../common');
var request = require('request-promise');
var options = {};
@ -37,11 +37,9 @@ exports.getRTLConfig = (req, res, next) => {
if (common.nodes && common.nodes.length > 0) {
common.nodes.forEach((node, i) => {
const authentication = {};
if(node.config_path) {
authentication.configPath = node.config_path;
} else {
authentication.configPath = '';
}
authentication.configPath = (node.config_path) ? node.config_path : '';
authentication.swapMacaroonPath = (node.swap_macaroon_path) ? node.swap_macaroon_path : '';
authentication.boltzMacaroonPath = (node.boltz_macaroon_path) ? node.boltz_macaroon_path : '';
const settings = {};
settings.userPersona = node.user_persona ? node.user_persona : 'MERCHANT';
settings.themeMode = (node.theme_mode) ? node.theme_mode : 'DAY';
@ -51,6 +49,7 @@ exports.getRTLConfig = (req, res, next) => {
settings.enableLogging = node.enable_logging ? !!node.enable_logging : false;
settings.lnServerUrl = node.ln_server_url;
settings.swapServerUrl = node.swap_server_url;
settings.boltzServerUrl = node.boltz_server_url;
settings.channelBackupPath = node.channel_backup_path;
settings.currencyUnit = node.currency_unit;
nodesArr.push({
@ -95,14 +94,14 @@ exports.updateUISettings = (req, res, next) => {
});
try {
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
logger.info({fileName: 'RTLConf', msg: 'Updating Application Node Settings Succesful!'});
res.status(201).json({message: 'Application Node Settings Updated Successfully'});
logger.info({fileName: 'RTLConf', msg: 'Updating Node Settings Succesful!'});
res.status(201).json({message: 'Node Settings Updated Successfully'});
}
catch (err) {
logger.error({fileName: 'Conf', lineNum: 101, msg: 'Updating Application Node Settings Failed!'});
logger.error({fileName: 'Conf', lineNum: 101, msg: 'Updating Node Settings Failed!'});
res.status(500).json({
message: "Updating Application Node Settings Failed!",
error: 'Updating Application Node Settings Failed!'
message: "Updating Node Settings Failed!",
error: 'Updating Node Settings Failed!'
});
}
};
@ -177,8 +176,6 @@ exports.getConfig = (req, res, next) => {
jsonConfig = JSON.parse(data);
} else {
jsonConfig = ini.parse(data);
console.warn();
console.warn(jsonConfig);
switch (common.selectedNode.ln_implementation) {
case 'ECL':
if (jsonConfig['eclair.api.password']) {
@ -263,4 +260,78 @@ exports.getCurrencyRates = (req, res, next) => {
error: err.error
});
});
};
};
exports.updateSSO = (req, res, next) => {
RTLConfFile = common.rtl_conf_file_path + common.path_separator + 'RTL-Config.json';
var config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
delete config.SSO;
config.SSO = req.body.SSO;
try {
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
logger.info({fileName: 'RTLConf', msg: 'Updating SSO Succesful!'});
res.status(201).json({message: 'SSO Updated Successfully'});
}
catch (err) {
logger.error({fileName: 'RTLConf', lineNum: 279, msg: 'Updating SSO Failed!'});
res.status(500).json({
message: "Updating SSO Failed!",
error: 'Updating SSO Failed!'
});
}
};
exports.updateServiceSettings = (req, res, next) => {
var RTLConfFile = common.rtl_conf_file_path + common.path_separator + 'RTL-Config.json';
var config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
const selectedNode = common.findNode(common.selectedNode.index);
config.nodes.find(node => {
if(node.index == common.selectedNode.index) {
switch (req.body.service) {
case 'LOOP':
if (req.body.settings.enable) {
node.Settings.swapServerUrl = req.body.settings.serverUrl;
node.Authentication.swapMacaroonPath = req.body.settings.macaroonPath;
selectedNode.swap_server_url = req.body.settings.serverUrl;
selectedNode.swap_macaroon_path = req.body.settings.macaroonPath;
} else {
delete node.Settings.swapServerUrl;
delete node.Authentication.swapMacaroonPath;
delete selectedNode.swap_server_url;
delete selectedNode.swap_macaroon_path;
}
break;
case 'BOLTZ':
if (req.body.settings.enable) {
node.Settings.boltzServerUrl = req.body.settings.serverUrl;
node.Authentication.boltzMacaroonPath = req.body.settings.macaroonPath;
selectedNode.boltz_server_url = req.body.settings.serverUrl;
selectedNode.boltz_macaroon_path = req.body.settings.macaroonPath;
} else {
delete node.Settings.boltzServerUrl;
delete node.Authentication.boltzMacaroonPath;
delete selectedNode.boltz_server_url;
delete selectedNode.boltz_macaroon_path;
}
break;
default:
break;
}
common.replaceNode(common.selectedNode.index, selectedNode);
}
});
try {
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
logger.info({fileName: 'RTLConf', msg: 'Updating Service Settings Succesful!'});
res.status(201).json({message: 'Service Settings Updated Successfully'});
}
catch (err) {
logger.error({fileName: 'RTLConf', lineNum: 333, msg: 'Updating Service Settings Failed!'});
res.status(500).json({
message: "Updating Service Settings Failed!",
error: 'Updating Service Settings Failed!'
});
}
};

@ -1,5 +1,5 @@
var common = require('../common');
var connect = require('../connect');
var common = require('../../common');
var connect = require('../../connect');
var logger = require('./logger');
const jwt = require("jsonwebtoken");
const otplib = require("otplib");
@ -25,9 +25,30 @@ getFailedInfo = (reqIP, currentTime) => {
return failed;
}
handleError = (failed, currentTime, errMsg) => {
if (failed.count >= ALLOWED_LOGIN_ATTEMPTS && (currentTime <= (failed.lastTried + LOCKING_PERIOD))) {
return {
message: "Multiple Failed Login Attempts!",
error: "Application locked for " + (LOCKING_PERIOD/ONE_MINUTE) + " minutes due to multiple failed login attempts! Try again after " + common.convertTimestampToLocalDate((failed.lastTried + LOCKING_PERIOD)/1000) + "!"
};
} else {
return {
message: "Authentication Failed!",
error: errMsg + "\nApplication will be locked after " + (ALLOWED_LOGIN_ATTEMPTS - failed.count) + " more unsuccessful attempts!"
};
}
}
exports.verifyToken = (twoFAToken) => {
if (common.rtl_secret2fa && common.rtl_secret2fa !== '' && otplib.authenticator.check(twoFAToken, common.rtl_secret2fa)) {
return true;
}
return false;
};
exports.authenticateUser = (req, res, next) => {
if(+common.rtl_sso) {
if(req.body.authenticateWith === 'TOKEN' && jwt.verify(req.body.authenticationValue, common.secret_key)) {
if(req.body.authenticateWith === 'JWT' && jwt.verify(req.body.authenticationValue, common.secret_key)) {
res.status(200).json({ token: token });
} else if (req.body.authenticateWith === 'PASSWORD' && crypto.createHash('sha256').update(common.cookie).digest('hex') === req.body.authenticationValue) {
connect.refreshCookie(common.rtl_cookie_path);
@ -49,6 +70,14 @@ exports.authenticateUser = (req, res, next) => {
let failed = getFailedInfo(reqIP, currentTime);
const password = req.body.authenticationValue;
if (common.rtl_pass === password && failed.count < ALLOWED_LOGIN_ATTEMPTS) {
if (req.body.twoFAToken && req.body.twoFAToken !== '') {
if (!this.verifyToken(req.body.twoFAToken)) {
logger.error({fileName: 'Authenticate', lineNum: 61, msg: 'Invalid Token! Failed IP ' + reqIP});
failed.count = failed.count + 1;
failed.lastTried = currentTime;
return res.status(401).json(handleError(failed, currentTime, 'Invalid 2FA Token!'));
}
}
delete failedLoginAttempts[reqIP];
let rpcUser = 'NODE_USER';
const token = jwt.sign(
@ -57,20 +86,10 @@ exports.authenticateUser = (req, res, next) => {
);
res.status(200).json({ token: token });
} else {
logger.error({fileName: 'Authenticate', lineNum: 61, msg: 'Invalid Password! Failed IP ' + reqIP});
logger.error({fileName: 'Authenticate', lineNum: 85, msg: 'Invalid Password! Failed IP ' + reqIP});
failed.count = common.rtl_pass !== password ? (failed.count + 1) : failed.count;
failed.lastTried = common.rtl_pass !== password ? currentTime : failed.lastTried;
if (failed.count >= ALLOWED_LOGIN_ATTEMPTS && (currentTime <= (failed.lastTried + LOCKING_PERIOD))) {
res.status(401).json({
message: "Multiple Failed Login Attempts!",
error: "Application locked for " + (LOCKING_PERIOD/ONE_MINUTE) + " minutes due to multiple failed login attempts! Try again after " + common.convertTimestampToLocalDate((failed.lastTried + LOCKING_PERIOD)/1000) + "!"
});
} else {
res.status(401).json({
message: "Authentication Failed!",
error: "Invalid password! Application will be locked after " + (ALLOWED_LOGIN_ATTEMPTS - failed.count) + " more unsuccessful attempts!"
});
}
return res.status(401).json(handleError(failed, currentTime, 'Invalid Password!'));
}
}
};
@ -101,16 +120,3 @@ exports.resetPassword = (req, res, next) => {
}
}
};
exports.verifyToken = (req, res, next) => {
const token2fa = req.body.authentication2FA;
if (!common.rtl_secret2fa || otplib.authenticator.check(token2fa, common.rtl_secret2fa)) {
res.status(200).json({ isValidToken: true });
} else {
logger.error({fileName: 'Authenticate', lineNum: 77, msg: 'Token Verification Failed!'});
res.status(401).json({
message: "Authentication Failed!",
error: "Token Verification Failed!"
});
}
};

@ -0,0 +1,239 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../shared/logger');
var options = {};
exports.getInfo = (req, res, next) => {
options = common.getBoltzServerOptions();
if(options.url === '') { return res.status(500).json({message: "Boltz Get Info Failed!",error: { message: 'Boltz Server URL is missing in the configuration.'}}); }
options.url = options.url + '/v1/info';
request(options).then(function (body) {
logger.info({fileName: 'Boltz', msg: 'Boltz Get Info: ' + 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['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Boltz', lineNum: 22, msg: 'Boltz Get Info Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Boltz Get Info Failed!",
error: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : err
});
});
};
exports.getServiceInfo = (req, res, next) => {
options = common.getBoltzServerOptions();
if(options.url === '') { return res.status(500).json({message: "Boltz Get Service Info Failed!",error: { message: 'Boltz Server URL is missing in the configuration.'}}); }
options.url = options.url + '/v1/serviceinfo';
request(options).then(function (body) {
logger.info({fileName: 'Boltz', msg: 'Boltz Get Service Info: ' + 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['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Boltz', lineNum: 46, msg: 'Boltz Get Service Info Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Boltz Get Service Info Failed!",
error: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : err
});
});
};
exports.listSwaps = (req, res, next) => {
options = common.getBoltzServerOptions();
if(options.url === '') { return res.status(500).json({message: "Boltz List Swaps Failed!",error: { message: 'Boltz Server URL is missing in the configuration.'}}); }
options.url = options.url + '/v1/listswaps';
request(options).then(function (body) {
logger.info({fileName: 'Boltz', msg: 'Boltz List Swaps Info: ' + JSON.stringify(body)});
if (body && body.swaps && body.swaps.length && body.swaps.length > 0) { body.swaps = body.swaps.reverse(); }
if (body && body.reverseSwaps && body.reverseSwaps.length && body.reverseSwaps.length > 0) { body.reverseSwaps = body.reverseSwaps.reverse(); }
res.status(200).json(body);
})
.catch(errRes => {
let err = JSON.parse(JSON.stringify(errRes));
if (err.options && err.options.headers && err.options.headers['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Boltz', lineNum: 70, msg: 'Boltz List Swaps Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Boltz List Swaps Failed!",
error: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : err
});
});
};
exports.getSwapInfo = (req, res, next) => {
options = common.getBoltzServerOptions();
if(options.url === '') { return res.status(500).json({message: "Boltz Swap Info Failed!",error: { message: 'Boltz Server URL is missing in the configuration.'}}); }
options.url = options.url + '/v1/swap/' + req.params.swapId;
request(options).then(function (body) {
logger.info({fileName: 'Boltz', msg: 'Boltz Swap Info: ' + 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['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Boltz', lineNum: 94, msg: 'Boltz Swap Info Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Boltz Swap Info Failed!",
error: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : err
});
});
};
exports.createSwap = (req, res, next) => {
options = common.getBoltzServerOptions();
if(options.url === '') { return res.status(500).json({message: "Create Swap Failed!",error: { message: 'Boltz Server URL is missing in the configuration.'}}); }
options.url = options.url + '/v1/createswap';
options.body = { amount: req.body.amount };
if (req.body.address !== '') { options.body.address = req.body.address; }
logger.info({fileName: 'Boltz', msg: 'Create Swap Body: ' + JSON.stringify(options.body)});
request.post(options).then(createSwapRes => {
logger.info({fileName: 'Boltz', msg: 'Create Swap Response: ' + JSON.stringify(createSwapRes)});
if(!createSwapRes || createSwapRes.error) {
logger.error({fileName: 'Boltz', lineNum: 112, msg: 'Create Swap Error: ' + JSON.stringify(createSwapRes.error)});
res.status(500).json({
message: 'Create Swap Failed!',
error: (!createSwapRes) ? 'Error From Server!' : createSwapRes.error.message
});
} else {
res.status(201).json(createSwapRes);
}
})
.catch(errRes => {
let err = JSON.parse(JSON.stringify(errRes));
if (err.options && err.options.headers && err.options.headers['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Boltz', lineNum: 129, msg: 'Create Swap Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Create Swap Failed!",
error: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : err
});
});
};
exports.createReverseSwap = (req, res, next) => {
options = common.getBoltzServerOptions();
if(options.url === '') { return res.status(500).json({message: "Create Reverse Swap Failed!",error: { message: 'Boltz Server URL is missing in the configuration.'}}); }
options.url = options.url + '/v1/createreverseswap';
options.body = { amount: req.body.amount };
if (req.body.address !== '') { options.body.address = req.body.address; }
logger.info({fileName: 'Boltz', msg: 'Create Reverse Swap Body: ' + JSON.stringify(options.body)});
request.post(options).then(createReverseSwapRes => {
logger.info({fileName: 'Boltz', msg: 'Create Reverse Swap Response: ' + JSON.stringify(createReverseSwapRes)});
if(!createReverseSwapRes || createReverseSwapRes.error) {
logger.error({fileName: 'Boltz', lineNum: 147, msg: 'Create Reverse Swap Error: ' + JSON.stringify(createReverseSwapRes.error)});
res.status(500).json({
message: 'Create Reverse Swap Failed!',
error: (!createReverseSwapRes) ? 'Error From Server!' : createReverseSwapRes.error.message
});
} else {
res.status(201).json(createReverseSwapRes);
}
})
.catch(errRes => {
let err = JSON.parse(JSON.stringify(errRes));
if (err.options && err.options.headers && err.options.headers['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Boltz', lineNum: 164, msg: 'Create Reverse Swap Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Create Reverse Swap Failed!",
error: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : err
});
});
};
exports.createChannel = (req, res, next) => {
options = common.getBoltzServerOptions();
if(options.url === '') { return res.status(500).json({message: "Create Channel Failed!",error: { message: 'Boltz Server URL is missing in the configuration.'}}); }
options.url = options.url + '/v1/createchannel';
options.body = { amount: req.body.amount };
if (req.body.address !== '') { options.body.address = req.body.address; }
logger.info({fileName: 'Boltz', msg: 'Create Channel Body: ' + JSON.stringify(options.body)});
request.post(options).then(createChannelRes => {
logger.info({fileName: 'Boltz', msg: 'Create Channel Response: ' + JSON.stringify(createChannelRes)});
if(!createChannelRes || createChannelRes.error) {
logger.error({fileName: 'Boltz', lineNum: 182, msg: 'Create Channel Error: ' + JSON.stringify(createChannelRes.error)});
res.status(500).json({
message: 'Create Channel Failed!',
error: (!createChannelRes) ? 'Error From Server!' : createChannelRes.error.message
});
} else {
res.status(201).json(createChannelRes);
}
})
.catch(errRes => {
let err = JSON.parse(JSON.stringify(errRes));
if (err.options && err.options.headers && err.options.headers['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Boltz', lineNum: 199, msg: 'Create Channel Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Create Channel Failed!",
error: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : err
});
});
};
exports.deposit = (req, res, next) => {
options = common.getBoltzServerOptions();
if(options.url === '') { return res.status(500).json({message: "Deposit Failed!",error: { message: 'Boltz Server URL is missing in the configuration.'}}); }
options.url = options.url + '/v1/deposit';
request.post(options).then(depositRes => {
logger.info({fileName: 'Boltz', msg: 'Deposit Response: ' + JSON.stringify(depositRes)});
if(!depositRes || depositRes.error) {
logger.error({fileName: 'Boltz', lineNum: 214, msg: 'Deposit Error: ' + JSON.stringify(depositRes.error)});
res.status(500).json({
message: 'Deposit Failed!',
error: (!depositRes) ? 'Error From Server!' : depositRes.error.message
});
} else {
res.status(201).json(depositRes);
}
})
.catch(errRes => {
let err = JSON.parse(JSON.stringify(errRes));
if (err.options && err.options.headers && err.options.headers['Grpc-Metadata-macaroon']) {
delete err.options.headers['Grpc-Metadata-macaroon'];
}
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers['Grpc-Metadata-macaroon']) {
delete err.response.request.headers['Grpc-Metadata-macaroon'];
}
logger.error({fileName: 'Boltz', lineNum: 231, msg: 'Deposit Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Deposit Failed!",
error: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : err
});
});
};

@ -1,5 +1,5 @@
var fs = require('fs');
var common = require('../common');
var common = require('../../common');
exports.info = (msgJSON, selNode = common.selectedNode) => {
const msgStr = '\r\nINFO: ' + msgJSON.fileName + ' => ' + msgJSON.msg;

@ -1,6 +1,6 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var logger = require('./logger');
var options = {};
exports.loopOut = (req, res, next) => {

@ -67,6 +67,38 @@ services:
- lightning_data:/lnd
- lightning_shared:/shared
boltz:
container_name: ${COMPOSE_PROJECT_NAME}_boltz
image: boltz:1.2.0
build: ./boltz
restart: unless-stopped
command: [
"boltz",
"--noseedbackup",
"--rpclisten=0.0.0.0:${BOLTZ_RPC_PORT}",
"--restlisten=0.0.0.0:${BOLTZ_REST_PORT}",
"--adminmacaroonpath=/shared/admin.macaroon",
"--tlsextradomain=${BOLTZ_HOST}",
"--tlsextraip=0.0.0.0",
"--tlscertpath=/shared/tls.cert",
"--datadir=/boltz",
"--bitcoin.active",
"--bitcoin.regtest",
"--bitcoin.node=bitcoind",
"--bitcoind.rpchost=${BITCOIN_HOST}:${BITCOIN_RPC_PORT}",
"--bitcoind.rpcuser=${BITCOIN_RPC_USER}",
"--bitcoind.rpcpass=${BITCOIN_RPC_PASSWORD}",
"--bitcoind.zmqpubrawtx=tcp://${BITCOIN_HOST}:${BITCOIN_ZMQ_TX_PORT}",
"--bitcoind.zmqpubrawblock=tcp://${BITCOIN_HOST}:${BITCOIN_ZMQ_BLOCK_PORT}"
]
depends_on:
- bitcoind
ports:
- "${BOLTZ_REST_PORT}:${BOLTZ_REST_PORT}"
volumes:
- boltz_data:/boltz
- boltz_shared:/shared
rtl:
container_name: ${COMPOSE_PROJECT_NAME}_rtl
image: shahanafarooqui/rtl:0.6.4
@ -84,8 +116,10 @@ services:
LN_SERVER_URL: https://${LIGHTNING_HOST}:${LIGHTNING_REST_PORT}
CONFIG_PATH: ''
LN_IMPLEMENTATION: LND
SWAP_SERVER_URL: http://${LIGHTNING_HOST}:${LIGHTNING_LOOP_PORT}
SWAP_SERVER_URL: https://${LIGHTNING_HOST}:${LIGHTNING_LOOP_PORT}
SWAP_MACAROON_PATH: /shared
BOLTZ_SERVER_URL: https://${BOLTZ_HOST}:${BOLTZ_PORT}
BOLTZ_MACAROON_PATH: /shared
RTL_SSO: 0
RTL_COOKIE_PATH: ''
LOGOUT_REDIRECT_LINK: ''

@ -21,6 +21,7 @@ parameters have `default` values for initial setup and can be updated after RTL
"Authentication": {
"macaroonPath": "<Path for the folder containing 'admin.macaroon' (LND)/'access.macaroon' (CLT) file, Required for LND & CLT>",
"swapMacaroonPath": "<Path for the folder containing 'loop.macaroon' (LND), Required for LND Loop>",
"boltzMacaroonPath": "<Path for the folder containing 'admin.macaroon' (Boltz), Required for Boltz Swaps>",
"configPath": "<Full path of the lnd.conf/c-lightning config/eclair.conf file including the file name, if present locally, Optional, only mandatory for ECL if the lnApiPassword is missing>",
"lnApiPassword": "<Password to be used for ECL API authentication. Mandatory only for ECL if the configPath is missing>"
},
@ -35,6 +36,7 @@ parameters have `default` values for initial setup and can be updated after RTL
"currencyUnit": "<Optional: Fiat current Unit for currency conversion, default 'USD' If fiatConversion is true, Required if fiatConversion is true>",
"lnServerUrl": "<Service url for LND/CLightning REST APIs for the node, e.g. https://192.168.0.1:8080 OR https://192.168.0.1:3001 OR http://192.168.0.1:8080. Default 'https://localhost:8080', Required",
"swapServerUrl": "<Service url for swap server REST APIs for the node, e.g. https://localhost:8081, Optional>",
"boltzServerUrl": "<Service url for boltz server REST APIs for the node, e.g. https://localhost:9003, Optional>"
}
}
]
@ -48,8 +50,11 @@ HOST (host for the rtl node server, default localhost, Optional)
LN_IMPLEMENTATION (LND/CLT/ECL. Default 'LND', Required)
LN_SERVER_URL (LN server URL for LNP REST APIs, default https://localhost:8080) (Required)
SWAP_SERVER_URL (Swap server URL for REST APIs, default http://localhost:8081) (Optional)
BOLTZ_SERVER_URL (Boltz server URL for REST APIs, default http://localhost:9003) (Optional)
CONFIG_PATH (Full path of the LNP .conf file including the file name) (Optional for LND & CLT, Mandatory for ECL if LN_API_PASSWORD is undefined)
MACAROON_PATH (Path for the folder containing 'admin.macaroon' (LND)/'access.macaroon' (CLT) file, Required for LND & CLT)
SWAP_MACAROON_PATH (Path for the folder containing Loop's 'loop.macaroon', optional)
BOLTZ_MACAROON_PATH (Path for the folder containing Boltz's 'admin.macaroon', optional)
RTL_SSO (1 - single sign on via an external cookie, 0 - stand alone RTL authentication, Optional)
RTL_COOKIE_PATH (Full path of the cookie file including the file name, Required if RTL_SSO=1 else Optional)
LOGOUT_REDIRECT_LINK (URL to re-direct to after logout/timeout from RTL, Required if RTL_SSO=1 else Optional)

@ -23,10 +23,13 @@ This step is only required to configure the nodes, which will be remotely connec
5. `SSO` section can be used for single-sign-on from applications like BTCPayserver. If using RTL as a stand-alone app to connect with the nodes, keep the `rtlSSO=0` and ignore the rest of `SSO` section.
6. `nodes` section is a json array, with each element of the array representing the specific parameters for the LND node to connect with. `index` must be a number and start with 1. This number must be unique for each node in the array. For each element, two items need to be configured for each node on the network (`macaroonPath` and `lnServerUrl`).
7. `macaroonPath` should be set to the local path of the folder containing `admin.macaroon` file for each node. Each node must have a different folder for the `admin.macaroon` on the RTL server.
8. `swapMacaroonPath` should be set to the local path of the folder containing `loop.macaroon` file for loop. 9. `lnServerUrl` must be set to the service url for LND/C Lightining REST APIs for each node, with the unique ip address of the node hosting lnd/clightning e.g. https://192.168.0.1:8080 OR https://192.168.0.1:3001. In this case the ip address of the node hosting lnd/clightning is '192.168.0.1'
10. `swapServerUrl` must be set to the swap service url. e.g. https://localhost:8081.
11. `configPath` and `bitcoindConfigPath` are optional parameters which can be set only if the RTL is running locally on the same node. Else it can be set to "" or removed from the conf file all together.
12. `lnApiPassword` is mandatory in the ln implementation is ECL and configPath is missing. It is used to provide password for API authentication. It will be ignored in other ln implementations.
8. `swapMacaroonPath` should be set to the local path of the folder containing `loop.macaroon` file for loop.
9. `boltzMacaroonPath` should be set to the local path of the folder containing `admin.macaroon` file for boltz swaps.
10. `lnServerUrl` must be set to the service url for LND/C Lightining REST APIs for each node, with the unique ip address of the node hosting lnd/clightning e.g. https://192.168.0.1:8080 OR https://192.168.0.1:3001. In this case the ip address of the node hosting lnd/clightning is '192.168.0.1'
11. `swapServerUrl` must be set to the swap service url. e.g. https://localhost:8081.
12. `boltzServerUrl` must be set to the boltz service url. e.g. https://localhost:9003.
13. `configPath` and `bitcoindConfigPath` are optional parameters which can be set only if the RTL is running locally on the same node. Else it can be set to "" or removed from the conf file all together.
14. `lnApiPassword` is mandatory in the ln implementation is ECL and configPath is missing. It is used to provide password for API authentication. It will be ignored in other ln implementations.
#### 3. Restart RTL

@ -28,6 +28,7 @@ If your running RTL and LND on different devices on your local LAN, certain conf
"Authentication": {
"macaroonPath": "<Path of the folder containing 'admin.macaroon' on the device running RTL>",
"swapMacaroonPath": "<Path of the folder containing 'loop.macaroon' on the device running RTL>",
"boltzMacaroonPath": "<Path of the folder containing 'admin.macaroon' on the device running RTL>",
"configPath": "<Optional:Path of the lnd.conf if present locally or empty>"
},
"Settings": {
@ -40,6 +41,7 @@ If your running RTL and LND on different devices on your local LAN, certain conf
"fiatConversion": false,
"lnServerUrl": "<https://<ip-address-of-device-running-lnd>:8080; e.g. https://192.168.0.1:8080>",
"swapServerUrl": "<https://<localhost>:8081>",
"boltzServerUrl": "<https://<localhost>:9003>"
}
}
]

182
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "rtl",
"version": "0.10.0-beta",
"version": "0.10.1-beta",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -2577,15 +2577,6 @@
"tweetnacl": "^0.14.3"
}
},
"better-assert": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
"integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
"dev": true,
"requires": {
"callsite": "1.0.0"
}
},
"big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
@ -3087,12 +3078,6 @@
"caller-callsite": "^2.0.0"
}
},
"callsite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
"integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
"dev": true
},
"callsites": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
@ -4747,23 +4732,23 @@
}
},
"engine.io": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.2.tgz",
"integrity": "sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg==",
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz",
"integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==",
"dev": true,
"requires": {
"accepts": "~1.3.4",
"base64id": "2.0.0",
"cookie": "0.3.1",
"cookie": "~0.4.1",
"debug": "~4.1.0",
"engine.io-parser": "~2.2.0",
"ws": "^7.1.2"
"ws": "~7.4.2"
},
"dependencies": {
"cookie": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
"dev": true
},
"debug": {
@ -4776,17 +4761,17 @@
}
},
"ws": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz",
"integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==",
"version": "7.4.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz",
"integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==",
"dev": true
}
}
},
"engine.io-client": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz",
"integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==",
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.0.tgz",
"integrity": "sha512-12wPRfMrugVw/DNyJk34GQ5vIVArEcVMXWugQGGuw2XxUSztFNmJggZmv8IZlLyEdnpO1QB9LkcjeWewO2vxtA==",
"dev": true,
"requires": {
"component-emitter": "~1.3.0",
@ -4797,7 +4782,7 @@
"indexof": "0.0.1",
"parseqs": "0.0.6",
"parseuri": "0.0.6",
"ws": "~6.1.0",
"ws": "~7.4.2",
"xmlhttprequest-ssl": "~1.5.4",
"yeast": "0.1.2"
},
@ -4817,26 +4802,11 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"parseqs": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
"integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==",
"dev": true
},
"parseuri": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==",
"dev": true
},
"ws": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
"integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
"dev": true,
"requires": {
"async-limiter": "~1.0.0"
}
"version": "7.4.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz",
"integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==",
"dev": true
}
}
},
@ -8516,12 +8486,6 @@
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true
},
"object-component": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
"integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
"dev": true
},
"object-copy": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
@ -9155,22 +9119,16 @@
}
},
"parseqs": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
"integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
"dev": true,
"requires": {
"better-assert": "~1.0.0"
}
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
"integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==",
"dev": true
},
"parseuri": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
"integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
"dev": true,
"requires": {
"better-assert": "~1.0.0"
}
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==",
"dev": true
},
"parseurl": {
"version": "1.3.3",
@ -11750,16 +11708,16 @@
}
},
"socket.io": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz",
"integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==",
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz",
"integrity": "sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w==",
"dev": true,
"requires": {
"debug": "~4.1.0",
"engine.io": "~3.4.0",
"engine.io": "~3.5.0",
"has-binary2": "~1.0.2",
"socket.io-adapter": "~1.1.0",
"socket.io-client": "2.3.0",
"socket.io-client": "2.4.0",
"socket.io-parser": "~3.4.0"
},
"dependencies": {
@ -11781,46 +11739,31 @@
"dev": true
},
"socket.io-client": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz",
"integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz",
"integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==",
"dev": true,
"requires": {
"backo2": "1.0.2",
"base64-arraybuffer": "0.1.5",
"component-bind": "1.0.0",
"component-emitter": "1.2.1",
"debug": "~4.1.0",
"engine.io-client": "~3.4.0",
"component-emitter": "~1.3.0",
"debug": "~3.1.0",
"engine.io-client": "~3.5.0",
"has-binary2": "~1.0.2",
"has-cors": "1.1.0",
"indexof": "0.0.1",
"object-component": "0.0.3",
"parseqs": "0.0.5",
"parseuri": "0.0.5",
"parseqs": "0.0.6",
"parseuri": "0.0.6",
"socket.io-parser": "~3.3.0",
"to-array": "0.1.4"
},
"dependencies": {
"base64-arraybuffer": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
"integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
"dev": true
},
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
"dev": true
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "^2.1.1"
"ms": "2.0.0"
}
},
"isarray": {
@ -11829,38 +11772,21 @@
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
"dev": true
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"socket.io-parser": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz",
"integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==",
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz",
"integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==",
"dev": true,
"requires": {
"component-emitter": "~1.3.0",
"debug": "~3.1.0",
"isarray": "2.0.1"
},
"dependencies": {
"component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
"dev": true
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
}
}
}
}

@ -1,6 +1,6 @@
{
"name": "rtl",
"version": "0.10.0-beta",
"version": "0.10.1-beta",
"license": "MIT",
"scripts": {
"ng": "ng",

@ -1,7 +1,7 @@
const BalanceController = require("../../controllers/c-lightning/balance");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, BalanceController.getBalance);

@ -1,7 +1,7 @@
const ChannelsController = require("../../controllers/c-lightning/channels");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/listChannels", authCheck, ChannelsController.listChannels);
router.post("/", authCheck, ChannelsController.openChannel);

@ -1,7 +1,7 @@
const FeesController = require("../../controllers/c-lightning/fees");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, FeesController.getFees);

@ -1,7 +1,7 @@
const infoController = require("../../controllers/c-lightning/getInfo");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, infoController.getInfo);

@ -1,7 +1,7 @@
const invoicesController = require("../../controllers/c-lightning/invoices");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, invoicesController.listInvoices);
router.post("/", authCheck, invoicesController.addInvoice);

@ -1,7 +1,7 @@
const MessagesController = require("../../controllers/c-lightning/message");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.post("/sign", authCheck, MessagesController.signMessage);
router.post("/verify", authCheck, MessagesController.verifyMessage);

@ -1,7 +1,7 @@
const NetworkController = require("../../controllers/c-lightning/network");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/getRoute/:destPubkey/:amount", authCheck, NetworkController.getRoute);
router.get("/listNode/:id", authCheck, NetworkController.listNode);

@ -1,10 +1,10 @@
const OnChainController = require("../../controllers/c-lightning/onchain");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, OnChainController.getNewAddress);
router.post("/", authCheck, OnChainController.onChainWithdraw);
router.get("/transactions/", authCheck, OnChainController.getTransactions);
router.get("/utxos/", authCheck, OnChainController.getUTXOs);
module.exports = router;

@ -1,7 +1,7 @@
const PaymentsController = require("../../controllers/c-lightning/payments");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, PaymentsController.listPayments);
router.get("/:invoice", authCheck, PaymentsController.decodePayment);

@ -1,7 +1,7 @@
const PeersController = require("../../controllers/c-lightning/peers");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, PeersController.getPeers);
router.post("/", authCheck, PeersController.postPeer);

@ -1,7 +1,7 @@
const ChannelsController = require("../../controllers/eclair/channels");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, ChannelsController.getChannels);
router.get("/stats", authCheck, ChannelsController.getChannelStats);

@ -1,7 +1,7 @@
const FeesController = require("../../controllers/eclair/fees");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/fees", authCheck, FeesController.getFees);
router.get("/payments", authCheck, FeesController.getPayments);

@ -1,7 +1,7 @@
const infoController = require("../../controllers/eclair/getInfo");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, infoController.getInfo);

@ -1,7 +1,7 @@
const invoicesController = require("../../controllers/eclair/invoices");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, invoicesController.listInvoices);
router.post("/", authCheck, invoicesController.createInvoice);

@ -1,7 +1,7 @@
const NetworkController = require("../../controllers/eclair/network");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/nodes/:id", authCheck, NetworkController.getNodes);

@ -1,7 +1,7 @@
const OnChainController = require("../../controllers/eclair/onchain");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, OnChainController.getNewAddress);
router.get("/balance/", authCheck, OnChainController.getBalance);

@ -1,7 +1,7 @@
const PaymentsController = require("../../controllers/eclair/payments");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/route/", authCheck, PaymentsController.queryPaymentRoute);
router.get("/:invoice", authCheck, PaymentsController.decodePayment);

@ -1,7 +1,7 @@
const PeersController = require("../../controllers/eclair/peers");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, PeersController.getPeers);
router.post("/", authCheck, PeersController.connectPeer);

@ -1,7 +1,7 @@
const BalanceController = require("../../controllers/lnd/balance");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/:source", authCheck, BalanceController.getBalance);

@ -1,7 +1,7 @@
const ChannelsController = require("../../controllers/lnd/channels");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, ChannelsController.getAllChannels);
router.get("/pending", authCheck, ChannelsController.getPendingChannels);

@ -1,7 +1,7 @@
const ChannelsBackupController = require("../../controllers/lnd/channelsBackup");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/:channelPoint", authCheck, ChannelsBackupController.getBackup);
router.get("/restore/list", authCheck, ChannelsBackupController.getRestoreList);

@ -1,7 +1,7 @@
const FeesController = require("../../controllers/lnd/fees");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, FeesController.getFees);

@ -1,7 +1,7 @@
const infoController = require("../../controllers/lnd/getInfo");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, infoController.getInfo);

@ -1,7 +1,7 @@
const graphController = require("../../controllers/lnd/graph");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, graphController.getDescribeGraph);
router.get("/info", authCheck, graphController.getGraphInfo);

@ -1,7 +1,7 @@
const invoicesController = require("../../controllers/lnd/invoices");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, invoicesController.listInvoices);
router.get("/:rHashStr", authCheck, invoicesController.getInvoice);

@ -1,7 +1,7 @@
const MessagesController = require("../../controllers/lnd/message");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.post("/sign", authCheck, MessagesController.signMessage);
router.post("/verify", authCheck, MessagesController.verifyMessage);

@ -1,7 +1,7 @@
const NewAddressController = require("../../controllers/lnd/newAddress");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, NewAddressController.getNewAddress);

@ -1,7 +1,7 @@
const PayRequestController = require("../../controllers/lnd/payReq");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/:payRequest", authCheck, PayRequestController.decodePayment);
router.post("/", authCheck, PayRequestController.decodePayments);

@ -1,7 +1,7 @@
const PaymentsController = require("../../controllers/lnd/payments");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, PaymentsController.getPayments);

@ -1,7 +1,7 @@
const PeersController = require("../../controllers/lnd/peers");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, PeersController.getPeers);
router.post("/", authCheck, PeersController.postPeer);

@ -1,7 +1,7 @@
const SwitchController = require("../../controllers/lnd/switch");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.post("/", authCheck, SwitchController.forwardingHistory);

@ -1,7 +1,7 @@
const TransactionsController = require("../../controllers/lnd/transactions");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/", authCheck, TransactionsController.getTransactions);
router.post("/", authCheck, TransactionsController.postTransactions);

@ -1,12 +1,15 @@
const WalletController = require("../../controllers/lnd/wallet");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
const authCheck = require("../shared/authCheck");
router.get("/genseed/:passphrase?", authCheck, WalletController.genSeed);
router.get("/updateSelNodeOptions", authCheck, WalletController.updateSelNodeOptions);
router.get("/getUTXOs", authCheck, WalletController.getUTXOs);
router.post("/wallet/:operation", authCheck, WalletController.operateWallet);
router.post("/bumpfee", authCheck, WalletController.bumpFee);
router.post("/label", authCheck, WalletController.labelTransaction);
router.post("/lease", authCheck, WalletController.leaseUTXO);
router.post("/release", authCheck, WalletController.releaseUTXO);
module.exports = router;

@ -1,4 +1,4 @@
const RTLConfController = require("../controllers/RTLConf");
const RTLConfController = require("../../controllers/shared/RTLConf");
const express = require("express");
const router = express.Router();
const authCheck = require("./authCheck");
@ -10,5 +10,7 @@ router.get("/config/:nodeType", authCheck, RTLConfController.getConfig);
router.get("/file", authCheck, RTLConfController.getFile);
router.post("/updateSelNode", RTLConfController.updateSelectedNode);
router.post("/updateDefaultNode", RTLConfController.updateDefaultNode);
router.post("/updateServiceSettings", RTLConfController.updateServiceSettings);
router.post("/updateSSO", RTLConfController.updateSSO);
router.get("/rates", RTLConfController.getCurrencyRates);
module.exports = router;

@ -1,5 +1,5 @@
const jwt = require("jsonwebtoken");
var common = require('../common');
var common = require('../../common');
module.exports = (req, res, next) => {
try {

@ -1,4 +1,4 @@
const AuthenticateController = require("../controllers/authenticate");
const AuthenticateController = require("../../controllers/shared/authenticate");
const express = require("express");
const router = express.Router();

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save