CLN Forwarding history filter and lint fixes

CLN Forwarding history filter and lint fixes
pull/1099/head
ShahanaFarooqui 2 years ago
parent 6f13a03ec8
commit 86fd2a7b29

@ -14,7 +14,7 @@
"env": {
"NODE_ENV": "development"
},
"program": "${workspaceFolder}\\rtl.js"
"program": "${workspaceFolder}/rtl.js"
}
]
}

@ -12,7 +12,7 @@ export const listChannels = (req, res, next) => {
}
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listChannels';
request(options).then((body) => {
body.map((channel) => {
body === null || body === void 0 ? void 0 : body.map((channel) => {
if (!channel.alias || channel.alias === '') {
channel.alias = channel.id.substring(0, 20);
}
@ -129,9 +129,10 @@ export const funderUpdatePolicy = (req, res, next) => {
}
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Funder Update Body', data: options.body });
request.post(options).then((body) => {
var _a, _b;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Funder Policy Received', data: body });
body.channel_fee_max_base_msat = (body.channel_fee_max_base_msat && typeof body.channel_fee_max_base_msat === 'string' && body.channel_fee_max_base_msat.includes('msat')) ? +body.channel_fee_max_base_msat.replace('msat', '') : body.channel_fee_max_base_msat;
body.lease_fee_base_msat = (body.lease_fee_base_msat && typeof body.lease_fee_base_msat === 'string' && body.lease_fee_base_msat.includes('msat')) ? +body.lease_fee_base_msat.replace('msat', '') : body.channel_fee_max_base_msat;
body.channel_fee_max_base_msat = (body.channel_fee_max_base_msat && typeof body.channel_fee_max_base_msat === 'string' && body.channel_fee_max_base_msat.includes('msat')) ? +((_a = body.channel_fee_max_base_msat) === null || _a === void 0 ? void 0 : _a.replace('msat', '')) : body.channel_fee_max_base_msat;
body.lease_fee_base_msat = (body.lease_fee_base_msat && typeof body.lease_fee_base_msat === 'string' && body.lease_fee_base_msat.includes('msat')) ? +((_b = body.lease_fee_base_msat) === null || _b === void 0 ? void 0 : _b.replace('msat', '')) : body.channel_fee_max_base_msat;
res.status(200).json(body);
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Funder Policy Error', req.session.selectedNode);

@ -76,9 +76,10 @@ export const listNodes = (req, res, next) => {
request(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'List Nodes Finished', data: body });
body.forEach((node) => {
var _a, _b;
if (node.option_will_fund) {
node.option_will_fund.lease_fee_base_msat = (node.option_will_fund.lease_fee_base_msat && typeof node.option_will_fund.lease_fee_base_msat === 'string' && node.option_will_fund.lease_fee_base_msat.includes('msat')) ? node.option_will_fund.lease_fee_base_msat.replace('msat', '') : node.option_will_fund.lease_fee_base_msat;
node.option_will_fund.channel_fee_max_base_msat = (node.option_will_fund.channel_fee_max_base_msat && typeof node.option_will_fund.channel_fee_max_base_msat === 'string' && node.option_will_fund.channel_fee_max_base_msat.includes('msat')) ? node.option_will_fund.channel_fee_max_base_msat.replace('msat', '') : node.option_will_fund.channel_fee_max_base_msat;
node.option_will_fund.lease_fee_base_msat = (node.option_will_fund.lease_fee_base_msat && typeof node.option_will_fund.lease_fee_base_msat === 'string' && node.option_will_fund.lease_fee_base_msat.includes('msat')) ? (_a = node.option_will_fund.lease_fee_base_msat) === null || _a === void 0 ? void 0 : _a.replace('msat', '') : node.option_will_fund.lease_fee_base_msat;
node.option_will_fund.channel_fee_max_base_msat = (node.option_will_fund.channel_fee_max_base_msat && typeof node.option_will_fund.channel_fee_max_base_msat === 'string' && node.option_will_fund.channel_fee_max_base_msat.includes('msat')) ? (_b = node.option_will_fund.channel_fee_max_base_msat) === null || _b === void 0 ? void 0 : _b.replace('msat', '') : node.option_will_fund.channel_fee_max_base_msat;
}
return node;
});

@ -35,9 +35,10 @@ function summaryReducer(accumulator, mpp) {
return accumulator;
}
function groupBy(payments) {
const paymentsInGroups = payments.reduce(paymentReducer, {});
const paymentsGrpArray = Object.keys(paymentsInGroups).map((key) => ((paymentsInGroups[key].length && paymentsInGroups[key].length > 1) ? common.sortDescByKey(paymentsInGroups[key], 'partid') : paymentsInGroups[key]));
return paymentsGrpArray.reduce((acc, curr) => {
var _a;
const paymentsInGroups = payments === null || payments === void 0 ? void 0 : payments.reduce(paymentReducer, {});
const paymentsGrpArray = (_a = Object.keys(paymentsInGroups)) === null || _a === void 0 ? void 0 : _a.map((key) => ((paymentsInGroups[key].length && paymentsInGroups[key].length > 1) ? common.sortDescByKey(paymentsInGroups[key], 'partid') : paymentsInGroups[key]));
return paymentsGrpArray === null || paymentsGrpArray === void 0 ? void 0 : paymentsGrpArray.reduce((acc, curr) => {
let temp = {};
if (curr.length && curr.length === 1) {
temp = JSON.parse(JSON.stringify(curr[0]));
@ -47,7 +48,7 @@ function groupBy(payments) {
delete temp.partid;
}
else {
const paySummary = curr.reduce(summaryReducer, { msatoshi: 0, msatoshi_sent: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
const paySummary = curr === null || curr === void 0 ? void 0 : curr.reduce(summaryReducer, { msatoshi: 0, msatoshi_sent: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
temp = {
is_group: true, is_expanded: false, total_parts: (curr.length ? curr.length : 0), status: paySummary.status, payment_hash: curr[0].payment_hash,
destination: curr[0].destination, msatoshi: paySummary.msatoshi, msatoshi_sent: paySummary.msatoshi_sent, created_at: curr[0].created_at,

@ -19,7 +19,7 @@ export const decodePayments = (req, res, next) => {
}
if (req.body.payments) {
const paymentsArr = req.body.payments.split(',');
return Promise.all(paymentsArr.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
return Promise.all(paymentsArr === null || paymentsArr === void 0 ? void 0 : paymentsArr.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment List Decoded', data: values });
res.status(200).json(values);

@ -47,8 +47,9 @@ export class CLWebSocketClient {
}
};
this.connectWithClient = (clWsClt) => {
var _a;
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Connecting to the Core Lightning\'s Websocket Server..' });
const WS_LINK = (clWsClt.selectedNode.ln_server_url).replace(/^http/, 'ws') + '/v1/ws';
const WS_LINK = ((_a = (clWsClt.selectedNode.ln_server_url)) === null || _a === void 0 ? void 0 : _a.replace(/^http/, 'ws')) + '/v1/ws';
const mcrnHexEncoded = Buffer.from(fs.readFileSync(join(clWsClt.selectedNode.macaroon_path, 'access.macaroon'))).toString('hex');
clWsClt.webSocketClient = new WebSocket(WS_LINK, [mcrnHexEncoded, 'hex'], { rejectUnauthorized: false });
clWsClt.webSocketClient.onopen = () => {

@ -32,7 +32,7 @@ export const simplifyAllChannels = (selNode, channels) => {
return request.post(options).then((nodes) => {
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Channels', msg: 'Filtered Nodes Received', data: nodes });
let foundPeer = null;
simplifiedChannels.map((channel) => {
simplifiedChannels === null || simplifiedChannels === void 0 ? void 0 : simplifiedChannels.map((channel) => {
foundPeer = nodes.find((channelWithAlias) => channel.nodeId === channelWithAlias.nodeId);
channel.alias = foundPeer ? foundPeer.alias : channel.nodeId.substring(0, 20);
return channel;

@ -70,7 +70,7 @@ export const listInvoices = (req, res, next) => {
return common.getDummyData('Invoices', req.session.selectedNode.ln_implementation).then((body) => {
const invoices = (!body[0] || body[0].length <= 0) ? [] : body[0];
pendingInvoices = (!body[1] || body[1].length <= 0) ? [] : body[1];
return Promise.all(invoices.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
return Promise.all(invoices === null || invoices === void 0 ? void 0 : invoices.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
then((values) => {
body = common.sortDescByKey(invoices, 'expiresAt');
return res.status(200).json(invoices);
@ -84,7 +84,7 @@ export const listInvoices = (req, res, next) => {
const invoices = (!body[0] || body[0].length <= 0) ? [] : body[0];
pendingInvoices = (!body[1] || body[1].length <= 0) ? [] : body[1];
if (invoices && invoices.length > 0) {
return Promise.all(invoices.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
return Promise.all(invoices === null || invoices === void 0 ? void 0 : invoices.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
then((values) => {
body = common.sortDescByKey(invoices, 'expiresAt');
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Sorted Invoices List Received', data: invoices });

@ -22,7 +22,7 @@ export const getSentInfoFromPaymentRequest = (selNode, payment) => {
};
export const getQueryNodes = (selNode, nodeIds) => {
options.url = selNode.ln_server_url + '/nodes';
options.form = { nodeIds: nodeIds.reduce((acc, curr) => acc + ',' + curr) };
options.form = { nodeIds: nodeIds === null || nodeIds === void 0 ? void 0 : nodeIds.reduce((acc, curr) => acc + ',' + curr) };
return request.post(options).then((nodes) => {
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Payments', msg: 'Query Nodes Received', data: nodes });
return nodes;
@ -77,14 +77,16 @@ export const queryPaymentRoute = (req, res, next) => {
};
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Query Payment Route Options', data: options.form });
request.post(options).then((body) => {
var _a;
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Query Payment Route Received', data: body });
if (body && body.routes && body.routes.length) {
let allRoutesNodeIds = [];
allRoutesNodeIds = body.routes.reduce((accRoutes, currRoute) => [...new Set([...accRoutes, ...currRoute.nodeIds])], []);
allRoutesNodeIds = (_a = body.routes) === null || _a === void 0 ? void 0 : _a.reduce((accRoutes, currRoute) => [...new Set([...accRoutes, ...currRoute.nodeIds])], []);
return getQueryNodes(req.session.selectedNode, allRoutesNodeIds).then((nodesWithAlias) => {
let foundPeer = null;
body.routes.forEach((route, i) => {
route.nodeIds.map((node, j) => {
var _a;
(_a = route.nodeIds) === null || _a === void 0 ? void 0 : _a.map((node, j) => {
foundPeer = nodesWithAlias.find((nodeWithAlias) => node === nodeWithAlias.nodeId);
body.routes[i].nodeIds[j] = { nodeId: node, alias: foundPeer ? foundPeer.alias : '' };
return node;
@ -111,7 +113,7 @@ export const getSentPaymentsInformation = (req, res, next) => {
}
if (req.body.payments) {
const paymentsArr = req.body.payments.split(',');
return Promise.all(paymentsArr.map((payment) => getSentInfoFromPaymentRequest(req.session.selectedNode, payment))).
return Promise.all(paymentsArr === null || paymentsArr === void 0 ? void 0 : paymentsArr.map((payment) => getSentInfoFromPaymentRequest(req.session.selectedNode, payment))).
then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Sent Information Received', data: values });
return res.status(200).json(values);

@ -32,7 +32,7 @@ export const getPeers = (req, res, next) => {
peersNodeIds = peersNodeIds.substring(1);
return getFilteredNodes(req.session.selectedNode, peersNodeIds).then((peersWithAlias) => {
let foundPeer = null;
body.map((peer) => {
body === null || body === void 0 ? void 0 : body.map((peer) => {
foundPeer = peersWithAlias.find((peerWithAlias) => peer.nodeId === peerWithAlias.nodeId);
peer.alias = foundPeer ? foundPeer.alias : peer.nodeId.substring(0, 20);
return peer;
@ -85,7 +85,7 @@ export const connectPeer = (req, res, next) => {
peersNodeIds = peersNodeIds.substring(1);
return getFilteredNodes(req.session.selectedNode, peersNodeIds).then((peersWithAlias) => {
let foundPeer = null;
body.map((peer) => {
body === null || body === void 0 ? void 0 : body.map((peer) => {
foundPeer = peersWithAlias.find((peerWithAlias) => peer.nodeId === peerWithAlias.nodeId);
peer.alias = foundPeer ? foundPeer.alias : peer.nodeId.substring(0, 20);
return peer;

@ -45,8 +45,9 @@ export class ECLWebSocketClient {
}
};
this.connectWithClient = (eclWsClt) => {
var _a;
this.logger.log({ selectedNode: eclWsClt.selectedNode, level: 'INFO', fileName: 'ECLWebSocket', msg: 'Connecting to the Eclair\'s Websocket Server..' });
const UpdatedLNServerURL = (eclWsClt.selectedNode.ln_server_url).replace(/^http/, 'ws');
const UpdatedLNServerURL = (_a = (eclWsClt.selectedNode.ln_server_url)) === null || _a === void 0 ? void 0 : _a.replace(/^http/, 'ws');
const firstSubStrIndex = (UpdatedLNServerURL.indexOf('//') + 2);
const WS_LINK = UpdatedLNServerURL.slice(0, firstSubStrIndex) + ':' + eclWsClt.selectedNode.ln_api_password + '@' + UpdatedLNServerURL.slice(firstSubStrIndex) + '/ws';
eclWsClt.webSocketClient = new WebSocket(WS_LINK);

@ -28,9 +28,10 @@ export const getAllChannels = (req, res, next) => {
let remote = 0;
let total = 0;
request(options).then((body) => {
var _a;
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Channels List Received', data: body });
if (body.channels) {
return Promise.all(body.channels.map((channel) => {
return Promise.all((_a = body.channels) === null || _a === void 0 ? void 0 : _a.map((channel) => {
local = (channel.local_balance) ? +channel.local_balance : 0;
remote = (channel.remote_balance) ? +channel.remote_balance : 0;
total = local + remote;
@ -64,21 +65,22 @@ export const getPendingChannels = (req, res, next) => {
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/pending';
options.qs = req.query;
request(options).then((body) => {
var _a, _b, _c, _d;
if (!body.total_limbo_balance) {
body.total_limbo_balance = 0;
}
const promises = [];
if (body.pending_open_channels && body.pending_open_channels.length > 0) {
body.pending_open_channels.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
(_a = body.pending_open_channels) === null || _a === void 0 ? void 0 : _a.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
}
if (body.pending_closing_channels && body.pending_closing_channels.length > 0) {
body.pending_closing_channels.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
(_b = body.pending_closing_channels) === null || _b === void 0 ? void 0 : _b.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
}
if (body.pending_force_closing_channels && body.pending_force_closing_channels.length > 0) {
body.pending_force_closing_channels.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
(_c = body.pending_force_closing_channels) === null || _c === void 0 ? void 0 : _c.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
}
if (body.waiting_close_channels && body.waiting_close_channels.length > 0) {
body.waiting_close_channels.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
(_d = body.waiting_close_channels) === null || _d === void 0 ? void 0 : _d.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
}
return Promise.all(promises).then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Pending Channels List Received', data: body });
@ -102,8 +104,9 @@ export const getClosedChannels = (req, res, next) => {
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/closed';
options.qs = req.query;
request(options).then((body) => {
var _a;
if (body.channels && body.channels.length > 0) {
return Promise.all(body.channels.map((channel) => {
return Promise.all((_a = body.channels) === null || _a === void 0 ? void 0 : _a.map((channel) => {
channel.close_type = (!channel.close_type) ? 'COOPERATIVE_CLOSE' : channel.close_type;
return getAliasForChannel(req.session.selectedNode, channel);
})).then((values) => {
@ -192,6 +195,7 @@ export const postTransactions = (req, res, next) => {
});
};
export const closeChannel = (req, res, next) => {
var _a;
try {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Closing Channel..' });
if (!req.session.selectedNode) {
@ -202,7 +206,7 @@ export const closeChannel = (req, res, next) => {
if (options.error) {
return res.status(options.statusCode).json({ message: options.message, error: options.error });
}
const channelpoint = req.params.channelPoint.replace(':', '/');
const channelpoint = (_a = req.params.channelPoint) === null || _a === void 0 ? void 0 : _a.replace(':', '/');
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/' + channelpoint + '?force=' + req.query.force;
if (req.query.target_conf) {
options.url = options.url + '&target_conf=' + req.query.target_conf;

@ -16,12 +16,13 @@ function getFilesList(channelBackupPath, callback) {
}
if (files && files.length > 0) {
files.forEach((file) => {
var _a;
if (!file.includes('.restored')) {
if (file.toLowerCase() === 'channel-all.bak' || file.toLowerCase() === 'backup-channel-all.bak') {
all_restore_exists = true;
}
else {
files_list.push({ channel_point: file.substring(8, file.length - 4).replace('-', ':') });
files_list.push({ channel_point: (_a = file.substring(8, file.length - 4)) === null || _a === void 0 ? void 0 : _a.replace('-', ':') });
}
}
});
@ -31,6 +32,7 @@ function getFilesList(channelBackupPath, callback) {
});
}
export const getBackup = (req, res, next) => {
var _a, _b;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'ChannelBackup', msg: 'Getting Channel Backup..' });
options = common.getOptions(req);
if (options.error) {
@ -44,9 +46,9 @@ export const getBackup = (req, res, next) => {
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/backup';
}
else {
channel_backup_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.params.channelPoint.replace(':', '-') + '.bak';
channel_backup_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + ((_a = req.params.channelPoint) === null || _a === void 0 ? void 0 : _a.replace(':', '-')) + '.bak';
message = 'Channel Backup Successful.';
const channelpoint = req.params.channelPoint.replace(':', '/');
const channelpoint = (_b = req.params.channelPoint) === null || _b === void 0 ? void 0 : _b.replace(':', '/');
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/backup/' + channelpoint;
const exists = fs.existsSync(channel_backup_file);
if (exists) {
@ -81,6 +83,7 @@ export const getBackup = (req, res, next) => {
});
};
export const postBackupVerify = (req, res, next) => {
var _a;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'ChannelBackup', msg: 'Verifying Channel Backup..' });
options = common.getOptions(req);
if (options.error) {
@ -116,7 +119,7 @@ export const postBackupVerify = (req, res, next) => {
}
else {
message = 'Channel Verify Successful.';
channel_verify_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.params.channelPoint.replace(':', '-') + '.bak';
channel_verify_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + ((_a = req.params.channelPoint) === null || _a === void 0 ? void 0 : _a.replace(':', '-')) + '.bak';
const exists = fs.existsSync(channel_verify_file);
if (exists) {
verify_backup = fs.readFileSync(channel_verify_file, 'utf-8');
@ -141,6 +144,7 @@ export const postBackupVerify = (req, res, next) => {
}
};
export const postRestore = (req, res, next) => {
var _a;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'ChannelBackup', msg: 'Restoring Channel Backup..' });
options = common.getOptions(req);
if (options.error) {
@ -188,7 +192,7 @@ export const postRestore = (req, res, next) => {
}
else {
message = 'Channel Restore Successful.';
channel_restore_file = req.session.selectedNode.channel_backup_path + sep + 'restore' + sep + 'channel-' + req.params.channelPoint.replace(':', '-') + '.bak';
channel_restore_file = req.session.selectedNode.channel_backup_path + sep + 'restore' + sep + 'channel-' + ((_a = req.params.channelPoint) === null || _a === void 0 ? void 0 : _a.replace(':', '-')) + '.bak';
const exists = fs.existsSync(channel_restore_file);
if (exists) {
restore_backup = fs.readFileSync(channel_restore_file, 'utf-8');

@ -21,10 +21,11 @@ export const getFees = (req, res, next) => {
const week_start_time = current_time - 604800;
const day_start_time = current_time - 86400;
return getAllForwardingEvents(req, month_start_time, current_time, 0, 'fees', (history) => {
var _a, _b, _c;
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Forwarding History Received', data: history });
const daily_sum = history.forwarding_events.reduce((acc, curr) => ((curr.timestamp >= day_start_time) ? [(acc[0] + 1), (acc[1] + +curr.fee_msat)] : acc), [0, 0]);
const weekly_sum = history.forwarding_events.reduce((acc, curr) => ((curr.timestamp >= week_start_time) ? [(acc[0] + 1), (acc[1] + +curr.fee_msat)] : acc), [0, 0]);
const monthly_sum = history.forwarding_events.reduce((acc, curr) => [(acc[0] + 1), (acc[1] + +curr.fee_msat)], [0, 0]);
const daily_sum = (_a = history.forwarding_events) === null || _a === void 0 ? void 0 : _a.reduce((acc, curr) => ((curr.timestamp >= day_start_time) ? [(acc[0] + 1), (acc[1] + +curr.fee_msat)] : acc), [0, 0]);
const weekly_sum = (_b = history.forwarding_events) === null || _b === void 0 ? void 0 : _b.reduce((acc, curr) => ((curr.timestamp >= week_start_time) ? [(acc[0] + 1), (acc[1] + +curr.fee_msat)] : acc), [0, 0]);
const monthly_sum = (_c = history.forwarding_events) === null || _c === void 0 ? void 0 : _c.reduce((acc, curr) => [(acc[0] + 1), (acc[1] + +curr.fee_msat)], [0, 0]);
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Daily Sum (Transactions, Fee)', data: daily_sum });
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Weekly Sum (Transactions, Fee)', data: weekly_sum });
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Monthly Sum (Transactions, Fee)', data: monthly_sum });

@ -9,6 +9,7 @@ const common = Common;
const lndWsClient = LNDWSClient;
const databaseService = Database;
export const getInfo = (req, res, next) => {
var _a;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Getting LND Node Information..' });
common.logEnvVariables(req);
common.setOptions(req);
@ -25,7 +26,7 @@ export const getInfo = (req, res, next) => {
return res.status(err.statusCode).json({ message: err.message, error: err.error });
}
else {
common.nodes.map((node) => {
(_a = common.nodes) === null || _a === void 0 ? void 0 : _a.map((node) => {
if (node.ln_implementation === 'LND') {
common.getAllNodeAllChannelBackup(node);
}

@ -84,11 +84,13 @@ export const getQueryRoutes = (req, res, next) => {
}
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Graph', msg: 'Query Routes URL', data: options.url });
request(options).then((body) => {
var _a;
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Graph', msg: 'Query Routes Received', data: body });
if (body.routes && body.routes.length && body.routes.length > 0 && body.routes[0].hops && body.routes[0].hops.length && body.routes[0].hops.length > 0) {
return Promise.all(body.routes[0].hops.map((hop) => getAliasFromPubkey(req.session.selectedNode, hop.pub_key))).
return Promise.all((_a = body.routes[0].hops) === null || _a === void 0 ? void 0 : _a.map((hop) => getAliasFromPubkey(req.session.selectedNode, hop.pub_key))).
then((values) => {
body.routes[0].hops.map((hop, i) => {
var _a;
(_a = body.routes[0].hops) === null || _a === void 0 ? void 0 : _a.map((hop, i) => {
hop.hop_sequence = i + 1;
hop.pubkey_alias = values[i];
return hop;
@ -148,7 +150,7 @@ export const getAliasesForPubkeys = (req, res, next) => {
}
if (req.query.pubkeys) {
const pubkeyArr = req.query.pubkeys.split(',');
return Promise.all(pubkeyArr.map((pubkey) => getAliasFromPubkey(req.session.selectedNode, pubkey))).
return Promise.all(pubkeyArr === null || pubkeyArr === void 0 ? void 0 : pubkeyArr.map((pubkey) => getAliasFromPubkey(req.session.selectedNode, pubkey))).
then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Node Alias', data: values });
res.status(200).json(values);

@ -34,7 +34,7 @@ export const decodePayments = (req, res, next) => {
}
if (req.body.payments) {
const paymentsArr = req.body.payments.split(',');
return Promise.all(paymentsArr.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
return Promise.all(paymentsArr === null || paymentsArr === void 0 ? void 0 : paymentsArr.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'PayRequest', msg: 'Payment List Decoded', data: values });
res.status(200).json(values);

@ -25,7 +25,7 @@ export const getPeers = (req, res, next) => {
request(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers List Received', data: body });
const peers = !body.peers ? [] : body.peers;
return Promise.all(peers.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
return Promise.all(peers === null || peers === void 0 ? void 0 : peers.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers with Alias before Sort', data: body });
if (body.peers) {
body.peers = common.sortDescByStrKey(body.peers, 'alias');
@ -54,7 +54,7 @@ export const postPeer = (req, res, next) => {
options.url = req.session.selectedNode.ln_server_url + '/v1/peers';
request(options).then((body) => {
const peers = (!body.peers) ? [] : body.peers;
return Promise.all(peers.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
return Promise.all(peers === null || peers === void 0 ? void 0 : peers.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
if (body.peers) {
body.peers = common.sortDescByStrKey(body.peers, 'alias');
body.peers = common.newestOnTop(body.peers, 'pub_key', req.body.pubkey);

@ -42,7 +42,8 @@ export class LNDWebSocketClient {
});
};
this.subscribeToInvoice = (options, selectedNode, rHash) => {
rHash = rHash.replace(/\+/g, '-').replace(/[/]/g, '_');
var _a;
rHash = (_a = rHash === null || rHash === void 0 ? void 0 : rHash.replace(/\+/g, '-')) === null || _a === void 0 ? void 0 : _a.replace(/[/]/g, '_');
this.logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'WebSocketClient', msg: 'Subscribing to Invoice ' + rHash + ' ..' });
options.url = selectedNode.ln_server_url + '/v2/invoices/subscribe/' + rHash;
request(options).then((msg) => {

@ -226,6 +226,7 @@ export const getConfig = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'Node Type', data: req.params.nodeType });
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'File Path', data: confFile });
fs.readFile(confFile, 'utf8', (errRes, data) => {
var _a;
if (errRes) {
const errMsg = 'Reading Config Error';
const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode);
@ -238,7 +239,7 @@ export const getConfig = (req, res, next) => {
}
else {
fileFormat = 'INI';
data = data.replace('color=#', 'color=');
data = data === null || data === void 0 ? void 0 : data.replace('color=#', 'color=');
jsonConfig = ini.parse(data);
if (jsonConfig['Application Options'] && jsonConfig['Application Options'].color) {
jsonConfig['Application Options'].color = '#' + jsonConfig['Application Options'].color;
@ -249,15 +250,16 @@ export const getConfig = (req, res, next) => {
}
}
jsonConfig = maskPasswords(jsonConfig);
const responseJSON = (fileFormat === 'JSON') ? jsonConfig : ini.stringify(jsonConfig).replace('color=\\#', 'color=#');
const responseJSON = (fileFormat === 'JSON') ? jsonConfig : (_a = ini.stringify(jsonConfig)) === null || _a === void 0 ? void 0 : _a.replace('color=\\#', 'color=#');
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Configuration File Data Received', data: responseJSON });
res.status(200).json({ format: fileFormat, data: responseJSON });
}
});
};
export const getFile = (req, res, next) => {
var _a;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting File..' });
const file = req.query.path ? req.query.path : (req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.query.channel.replace(':', '-') + '.bak');
const file = req.query.path ? req.query.path : (req.session.selectedNode.channel_backup_path + sep + 'channel-' + ((_a = req.query.channel) === null || _a === void 0 ? void 0 : _a.replace(':', '-')) + '.bak');
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'Channel Point', data: req.query.channel });
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'File Path', data: file });
fs.readFile(file, 'utf8', (errRes, data) => {

@ -18,14 +18,16 @@ export const isAuthenticated = (req, res, next) => {
}
};
export const verifyWSUser = (info, next) => {
var _a;
const headers = JSON.parse(JSON.stringify(info.req.headers));
const protocols = !info.req.headers['sec-websocket-protocol'] ? [] : info.req.headers['sec-websocket-protocol'].split(',').map((s) => s.trim());
const protocols = !info.req.headers['sec-websocket-protocol'] ? [] : (_a = info.req.headers['sec-websocket-protocol'].split(',')) === null || _a === void 0 ? void 0 : _a.map((s) => s.trim());
const jwToken = (protocols && protocols.length > 0) ? protocols[0] : '';
if (!jwToken || jwToken === '') {
next(false, 401, 'Authentication Failed! Please Login First!');
}
else {
jwt.verify(jwToken, common.secret_key, (verificationErr) => {
var _a, _b, _c;
if (verificationErr) {
next(false, 401, 'Authentication Failed! Please Login First!');
}
@ -40,7 +42,7 @@ export const verifyWSUser = (info, next) => {
}
let cookies = null;
try {
cookies = '{"' + headers.cookie.replace(/ /g, '').replace(/;/g, '","').trim().replace(/[=]/g, '":"') + '"}';
cookies = '{"' + ((_c = (_b = (_a = headers.cookie) === null || _a === void 0 ? void 0 : _a.replace(/ /g, '')) === null || _b === void 0 ? void 0 : _b.replace(/;/g, '","').trim()) === null || _c === void 0 ? void 0 : _c.replace(/[=]/g, '":"')) + '"}';
updatedReq['cookies'] = JSON.parse(cookies);
}
catch (err) {

@ -198,17 +198,18 @@ export class CommonService {
};
this.newestOnTop = (array, key, value) => {
const newlyAddedRecord = array.splice(array.findIndex((item) => item[key] === value), 1);
array.unshift(newlyAddedRecord[0]);
array === null || array === void 0 ? void 0 : array.unshift(newlyAddedRecord[0]);
return array;
};
this.camelCase = (str) => str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (word.toUpperCase())).replace(/\s+/g, '').replace(/-/g, ' ');
this.camelCase = (str) => { var _a, _b; return (_b = (_a = str === null || str === void 0 ? void 0 : str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (word.toUpperCase()))) === null || _a === void 0 ? void 0 : _a.replace(/\s+/g, '')) === null || _b === void 0 ? void 0 : _b.replace(/-/g, ' '); };
this.titleCase = (str) => {
var _a, _b;
if (str.indexOf('!\n') > 0 || str.indexOf('.\n') > 0) {
return str.split('\n').reduce((accumulator, currentStr) => accumulator + currentStr.charAt(0).toUpperCase() + currentStr.substring(1).toLowerCase() + '\n', '');
return (_a = str.split('\n')) === null || _a === void 0 ? void 0 : _a.reduce((accumulator, currentStr) => accumulator + currentStr.charAt(0).toUpperCase() + currentStr.substring(1).toLowerCase() + '\n', '');
}
else {
if (str.indexOf(' ') > 0) {
return str.split(' ').reduce((accumulator, currentStr) => accumulator + currentStr.charAt(0).toUpperCase() + currentStr.substring(1).toLowerCase() + ' ', '');
return (_b = str.split(' ')) === null || _b === void 0 ? void 0 : _b.reduce((accumulator, currentStr) => accumulator + currentStr.charAt(0).toUpperCase() + currentStr.substring(1).toLowerCase() + ' ', '');
}
else {
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
@ -328,8 +329,9 @@ export class CommonService {
}
};
this.createDirectory = (directoryName) => {
var _a;
const initDir = isAbsolute(directoryName) ? sep : '';
directoryName.split(sep).reduce((parentDir, childDir) => {
(_a = directoryName.split(sep)) === null || _a === void 0 ? void 0 : _a.reduce((parentDir, childDir) => {
const curDir = resolve(parentDir, childDir);
try {
if (!fs.existsSync(curDir)) {
@ -398,8 +400,9 @@ export class CommonService {
});
};
this.isVersionCompatible = (currentVersion, checkVersion) => {
var _a;
if (currentVersion) {
const versionsArr = currentVersion.trim().replace('v', '').split('-')[0].split('.') || [];
const versionsArr = ((_a = currentVersion.trim()) === null || _a === void 0 ? void 0 : _a.replace('v', '').split('-')[0].split('.')) || [];
const checkVersionsArr = checkVersion.split('.');
return (+versionsArr[0] > +checkVersionsArr[0]) ||
(+versionsArr[0] === +checkVersionsArr[0] && +versionsArr[1] > +checkVersionsArr[1]) ||

@ -31,6 +31,7 @@ export class RTLWebSocketServer {
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Connecting Websocket Server..' });
this.webSocketServer = new WebSocketServer({ noServer: true, path: this.common.baseHref + '/api/ws', verifyClient: (process.env.NODE_ENV === 'development') ? null : verifyWSUser });
httpServer.on('upgrade', (request, socket, head) => {
var _a;
if (request.headers['upgrade'] !== 'websocket') {
socket.end('HTTP/1.1 400 Bad Request');
return;
@ -38,7 +39,7 @@ export class RTLWebSocketServer {
const acceptKey = request.headers['sec-websocket-key'];
const hash = this.generateAcceptValue(acceptKey);
const responseHeaders = ['HTTP/1.1 101 Web Socket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', 'Sec-WebSocket-Accept: ' + hash];
const protocols = !request.headers['sec-websocket-protocol'] ? [] : request.headers['sec-websocket-protocol'].split(',').map((s) => s.trim());
const protocols = !request.headers['sec-websocket-protocol'] ? [] : (_a = request.headers['sec-websocket-protocol'].split(',')) === null || _a === void 0 ? void 0 : _a.map((s) => s.trim());
if (protocols.includes('json')) {
responseHeaders.push('Sec-WebSocket-Protocol: json');
}
@ -52,7 +53,8 @@ export class RTLWebSocketServer {
this.webSocketServer.emit('connection', websocket, request);
};
this.mountEventsOnConnection = (websocket, request) => {
const protocols = !request.headers['sec-websocket-protocol'] ? [] : request.headers['sec-websocket-protocol'].split(',').map((s) => s.trim());
var _a;
const protocols = !request.headers['sec-websocket-protocol'] ? [] : (_a = request.headers['sec-websocket-protocol'].split(',')) === null || _a === void 0 ? void 0 : _a.map((s) => s.trim());
const cookies = parse(request.headers.cookie);
websocket.clientId = Date.now();
websocket.isAlive = true;

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

@ -13,6 +13,6 @@
<style>@font-face{font-family:Roboto;src:url(Roboto-Thin.f7a95c9c5999532c.woff2) format("woff2"),url(Roboto-Thin.c13c157cb81e8ebb.woff) format("woff");font-weight:100;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-ThinItalic.b0e084abf689f393.woff2) format("woff2"),url(Roboto-ThinItalic.1111028df6cea564.woff) format("woff");font-weight:100;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Light.0e01b6cd13b3857f.woff2) format("woff2"),url(Roboto-Light.603ca9a537b88428.woff) format("woff");font-weight:300;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-LightItalic.232ef4b20215f720.woff2) format("woff2"),url(Roboto-LightItalic.1b5e142f787151c8.woff) format("woff");font-weight:300;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Regular.475ba9e4e2d63456.woff2) format("woff2"),url(Roboto-Regular.bcefbfee882bc1cb.woff) format("woff");font-weight:400;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-RegularItalic.e3a9ebdaac06bbc4.woff2) format("woff2"),url(Roboto-RegularItalic.0668fae6af0cf8c2.woff) format("woff");font-weight:400;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Medium.457532032ceb0168.woff2) format("woff2"),url(Roboto-Medium.6e1ae5f0b324a0aa.woff) format("woff");font-weight:500;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-MediumItalic.872f7060602d55d2.woff2) format("woff2"),url(Roboto-MediumItalic.e06fb533801cbb08.woff) format("woff");font-weight:500;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Bold.447291a88c067396.woff2) format("woff2"),url(Roboto-Bold.fc482e6133cf5e26.woff) format("woff");font-weight:700;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BoldItalic.1b15168ef6fa4e16.woff2) format("woff2"),url(Roboto-BoldItalic.e26ba339b06f09f7.woff) format("woff");font-weight:700;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Black.2eaa390d458c877d.woff2) format("woff2"),url(Roboto-Black.b25f67ad8583da68.woff) format("woff");font-weight:900;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BlackItalic.7dc03ee444552bc5.woff2) format("woff2"),url(Roboto-BlackItalic.c8dc642467cb3099.woff) format("woff");font-weight:900;font-style:italic}html{width:100%;height:99%;line-height:1.5;overflow-x:hidden;font-family:Roboto,sans-serif!important;font-size:62.5%}body{box-sizing:border-box;height:100%;margin:0;overflow:hidden}*{margin:0;padding:0}</style><link rel="stylesheet" href="styles.43515fc39338348b.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.43515fc39338348b.css"></noscript></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.5eac349d49d4fc59.js" type="module"></script><script src="polyfills.eddc63f1737a019a.js" type="module"></script><script src="main.228f2037f60782fc.js" type="module"></script>
<script src="runtime.2e2a4c6d6e08e8f6.js" type="module"></script><script src="polyfills.eddc63f1737a019a.js" type="module"></script><script src="main.053a5650605ae39e.js" type="module"></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 +1 @@
(()=>{"use strict";var e,v={},g={};function r(e){var n=g[e];if(void 0!==n)return n.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(n,t,f,o)=>{if(!t){var a=1/0;for(i=0;i<e.length;i++){for(var[t,f,o]=e[i],s=!0,d=0;d<t.length;d++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[d]))?t.splice(d--,1):(s=!1,o<a&&(a=o));if(s){e.splice(i--,1);var l=f();void 0!==l&&(n=l)}}return n}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,f,o]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>e+"."+{564:"df2fbcc9f18685c7",636:"1aa5210b7043b6ea",893:"9a615c46b89a5a79",924:"da19686ce48bdb00"}[e]+".js",r.miniCssF=e=>{},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="RTLApp:";r.l=(t,f,o,i)=>{if(e[t])e[t].push(f);else{var a,s;if(void 0!==o)for(var d=document.getElementsByTagName("script"),l=0;l<d.length;l++){var u=d[l];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==n+o){a=u;break}}a||(s=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+o),a.src=r.tu(t)),e[t]=[f];var c=(m,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(_=>_(b)),m)return m(b)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=c.bind(null,a.onerror),a.onload=c.bind(null,a.onload),s&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:n=>n},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(f,o)=>{var i=r.o(e,f)?e[f]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=f){var a=new Promise((u,c)=>i=e[f]=[u,c]);o.push(i[2]=a);var s=r.p+r.u(f),d=new Error;r.l(s,u=>{if(r.o(e,f)&&(0!==(i=e[f])&&(e[f]=void 0),i)){var c=u&&("load"===u.type?"missing":u.type),p=u&&u.target&&u.target.src;d.message="Loading chunk "+f+" failed.\n("+c+": "+p+")",d.name="ChunkLoadError",d.type=c,d.request=p,i[1](d)}},"chunk-"+f,f)}else e[f]=0},r.O.j=f=>0===e[f];var n=(f,o)=>{var d,l,[i,a,s]=o,u=0;if(i.some(p=>0!==e[p])){for(d in a)r.o(a,d)&&(r.m[d]=a[d]);if(s)var c=s(r)}for(f&&f(o);u<i.length;u++)r.o(e,l=i[u])&&e[l]&&e[l][0](),e[l]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();
(()=>{"use strict";var e,v={},g={};function r(e){var n=g[e];if(void 0!==n)return n.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(n,t,f,o)=>{if(!t){var a=1/0;for(i=0;i<e.length;i++){for(var[t,f,o]=e[i],s=!0,u=0;u<t.length;u++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[u]))?t.splice(u--,1):(s=!1,o<a&&(a=o));if(s){e.splice(i--,1);var l=f();void 0!==l&&(n=l)}}return n}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,f,o]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>e+"."+{564:"fa1444f039e187d7",636:"76f584200eef7ef5",893:"9a615c46b89a5a79",924:"232c129a40707864"}[e]+".js",r.miniCssF=e=>{},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="RTLApp:";r.l=(t,f,o,i)=>{if(e[t])e[t].push(f);else{var a,s;if(void 0!==o)for(var u=document.getElementsByTagName("script"),l=0;l<u.length;l++){var d=u[l];if(d.getAttribute("src")==t||d.getAttribute("data-webpack")==n+o){a=d;break}}a||(s=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+o),a.src=r.tu(t)),e[t]=[f];var c=(m,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(_=>_(b)),m)return m(b)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=c.bind(null,a.onerror),a.onload=c.bind(null,a.onload),s&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:n=>n},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(f,o)=>{var i=r.o(e,f)?e[f]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=f){var a=new Promise((d,c)=>i=e[f]=[d,c]);o.push(i[2]=a);var s=r.p+r.u(f),u=new Error;r.l(s,d=>{if(r.o(e,f)&&(0!==(i=e[f])&&(e[f]=void 0),i)){var c=d&&("load"===d.type?"missing":d.type),p=d&&d.target&&d.target.src;u.message="Loading chunk "+f+" failed.\n("+c+": "+p+")",u.name="ChunkLoadError",u.type=c,u.request=p,i[1](u)}},"chunk-"+f,f)}else e[f]=0},r.O.j=f=>0===e[f];var n=(f,o)=>{var u,l,[i,a,s]=o,d=0;if(i.some(p=>0!==e[p])){for(u in a)r.o(a,u)&&(r.m[u]=a[u]);if(s)var c=s(r)}for(f&&f(o);d<i.length;d++)r.o(e,l=i[d])&&e[l]&&e[l][0](),e[l]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();

@ -11,7 +11,7 @@ export const listChannels = (req, res, next) => {
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listChannels';
request(options).then((body) => {
body.map((channel) => {
body?.map((channel) => {
if (!channel.alias || channel.alias === '') { channel.alias = channel.id.substring(0, 20); }
const local = (channel.msatoshi_to_us) ? channel.msatoshi_to_us : 0;
const remote = (channel.msatoshi_to_them) ? channel.msatoshi_to_them : 0;
@ -117,8 +117,8 @@ export const funderUpdatePolicy = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Funder Update Body', data: options.body });
request.post(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Funder Policy Received', data: body });
body.channel_fee_max_base_msat = (body.channel_fee_max_base_msat && typeof body.channel_fee_max_base_msat === 'string' && body.channel_fee_max_base_msat.includes('msat')) ? +body.channel_fee_max_base_msat.replace('msat', '') : body.channel_fee_max_base_msat;
body.lease_fee_base_msat = (body.lease_fee_base_msat && typeof body.lease_fee_base_msat === 'string' && body.lease_fee_base_msat.includes('msat')) ? +body.lease_fee_base_msat.replace('msat', '') : body.channel_fee_max_base_msat;
body.channel_fee_max_base_msat = (body.channel_fee_max_base_msat && typeof body.channel_fee_max_base_msat === 'string' && body.channel_fee_max_base_msat.includes('msat')) ? +body.channel_fee_max_base_msat?.replace('msat', '') : body.channel_fee_max_base_msat;
body.lease_fee_base_msat = (body.lease_fee_base_msat && typeof body.lease_fee_base_msat === 'string' && body.lease_fee_base_msat.includes('msat')) ? +body.lease_fee_base_msat?.replace('msat', '') : body.channel_fee_max_base_msat;
res.status(200).json(body);
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Funder Policy Error', req.session.selectedNode);

@ -72,8 +72,8 @@ export const listNodes = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'List Nodes Finished', data: body });
body.forEach((node) => {
if (node.option_will_fund) {
node.option_will_fund.lease_fee_base_msat = (node.option_will_fund.lease_fee_base_msat && typeof node.option_will_fund.lease_fee_base_msat === 'string' && node.option_will_fund.lease_fee_base_msat.includes('msat')) ? node.option_will_fund.lease_fee_base_msat.replace('msat', '') : node.option_will_fund.lease_fee_base_msat;
node.option_will_fund.channel_fee_max_base_msat = (node.option_will_fund.channel_fee_max_base_msat && typeof node.option_will_fund.channel_fee_max_base_msat === 'string' && node.option_will_fund.channel_fee_max_base_msat.includes('msat')) ? node.option_will_fund.channel_fee_max_base_msat.replace('msat', '') : node.option_will_fund.channel_fee_max_base_msat;
node.option_will_fund.lease_fee_base_msat = (node.option_will_fund.lease_fee_base_msat && typeof node.option_will_fund.lease_fee_base_msat === 'string' && node.option_will_fund.lease_fee_base_msat.includes('msat')) ? node.option_will_fund.lease_fee_base_msat?.replace('msat', '') : node.option_will_fund.lease_fee_base_msat;
node.option_will_fund.channel_fee_max_base_msat = (node.option_will_fund.channel_fee_max_base_msat && typeof node.option_will_fund.channel_fee_max_base_msat === 'string' && node.option_will_fund.channel_fee_max_base_msat.includes('msat')) ? node.option_will_fund.channel_fee_max_base_msat?.replace('msat', '') : node.option_will_fund.channel_fee_max_base_msat;
}
return node;
});

@ -32,9 +32,9 @@ function summaryReducer(accumulator, mpp) {
}
function groupBy(payments) {
const paymentsInGroups = payments.reduce(paymentReducer, {});
const paymentsGrpArray = Object.keys(paymentsInGroups).map((key) => ((paymentsInGroups[key].length && paymentsInGroups[key].length > 1) ? common.sortDescByKey(paymentsInGroups[key], 'partid') : paymentsInGroups[key]));
return paymentsGrpArray.reduce((acc, curr) => {
const paymentsInGroups = payments?.reduce(paymentReducer, {});
const paymentsGrpArray = Object.keys(paymentsInGroups)?.map((key) => ((paymentsInGroups[key].length && paymentsInGroups[key].length > 1) ? common.sortDescByKey(paymentsInGroups[key], 'partid') : paymentsInGroups[key]));
return paymentsGrpArray?.reduce((acc, curr) => {
let temp: any = {};
if (curr.length && curr.length === 1) {
temp = JSON.parse(JSON.stringify(curr[0]));
@ -43,7 +43,7 @@ function groupBy(payments) {
temp.total_parts = 1;
delete temp.partid;
} else {
const paySummary = curr.reduce(summaryReducer, { msatoshi: 0, msatoshi_sent: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
const paySummary = curr?.reduce(summaryReducer, { msatoshi: 0, msatoshi_sent: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
temp = {
is_group: true, is_expanded: false, total_parts: (curr.length ? curr.length : 0), status: paySummary.status, payment_hash: curr[0].payment_hash,
destination: curr[0].destination, msatoshi: paySummary.msatoshi, msatoshi_sent: paySummary.msatoshi_sent, created_at: curr[0].created_at,

@ -21,7 +21,7 @@ export const decodePayments = (req, res, next) => {
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
if (req.body.payments) {
const paymentsArr = req.body.payments.split(',');
return Promise.all(paymentsArr.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
return Promise.all(paymentsArr?.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment List Decoded', data: values });
res.status(200).json(values);

@ -59,7 +59,7 @@ export class CLWebSocketClient {
public connectWithClient = (clWsClt) => {
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Connecting to the Core Lightning\'s Websocket Server..' });
const WS_LINK = (clWsClt.selectedNode.ln_server_url).replace(/^http/, 'ws') + '/v1/ws';
const WS_LINK = (clWsClt.selectedNode.ln_server_url)?.replace(/^http/, 'ws') + '/v1/ws';
const mcrnHexEncoded = Buffer.from(fs.readFileSync(join(clWsClt.selectedNode.macaroon_path, 'access.macaroon'))).toString('hex');
clWsClt.webSocketClient = new WebSocket(WS_LINK, [mcrnHexEncoded, 'hex'], { rejectUnauthorized: false });

@ -34,7 +34,7 @@ export const simplifyAllChannels = (selNode: CommonSelectedNode, channels) => {
return request.post(options).then((nodes) => {
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Channels', msg: 'Filtered Nodes Received', data: nodes });
let foundPeer = null;
simplifiedChannels.map((channel) => {
simplifiedChannels?.map((channel) => {
foundPeer = nodes.find((channelWithAlias) => channel.nodeId === channelWithAlias.nodeId);
channel.alias = foundPeer ? foundPeer.alias : channel.nodeId.substring(0, 20);
return channel;

@ -66,7 +66,7 @@ export const listInvoices = (req, res, next) => {
return common.getDummyData('Invoices', req.session.selectedNode.ln_implementation).then((body) => {
const invoices = (!body[0] || body[0].length <= 0) ? [] : body[0];
pendingInvoices = (!body[1] || body[1].length <= 0) ? [] : body[1];
return Promise.all(invoices.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
return Promise.all(invoices?.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
then((values) => {
body = common.sortDescByKey(invoices, 'expiresAt');
return res.status(200).json(invoices);
@ -79,7 +79,7 @@ export const listInvoices = (req, res, next) => {
const invoices = (!body[0] || body[0].length <= 0) ? [] : body[0];
pendingInvoices = (!body[1] || body[1].length <= 0) ? [] : body[1];
if (invoices && invoices.length > 0) {
return Promise.all(invoices.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
return Promise.all(invoices?.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
then((values) => {
body = common.sortDescByKey(invoices, 'expiresAt');
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Sorted Invoices List Received', data: invoices });

@ -21,7 +21,7 @@ export const getSentInfoFromPaymentRequest = (selNode: CommonSelectedNode, payme
export const getQueryNodes = (selNode: CommonSelectedNode, nodeIds) => {
options.url = selNode.ln_server_url + '/nodes';
options.form = { nodeIds: nodeIds.reduce((acc, curr) => acc + ',' + curr) };
options.form = { nodeIds: nodeIds?.reduce((acc, curr) => acc + ',' + curr) };
return request.post(options).then((nodes) => {
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Payments', msg: 'Query Nodes Received', data: nodes });
return nodes;
@ -74,11 +74,11 @@ export const queryPaymentRoute = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Query Payment Route Received', data: body });
if (body && body.routes && body.routes.length) {
let allRoutesNodeIds = [];
allRoutesNodeIds = body.routes.reduce((accRoutes, currRoute) => [...new Set([...accRoutes, ...currRoute.nodeIds])], []);
allRoutesNodeIds = body.routes?.reduce((accRoutes, currRoute) => [...new Set([...accRoutes, ...currRoute.nodeIds])], []);
return getQueryNodes(req.session.selectedNode, allRoutesNodeIds).then((nodesWithAlias) => {
let foundPeer = null;
body.routes.forEach((route, i) => {
route.nodeIds.map((node, j) => {
route.nodeIds?.map((node, j) => {
foundPeer = nodesWithAlias.find((nodeWithAlias) => node === nodeWithAlias.nodeId);
body.routes[i].nodeIds[j] = { nodeId: node, alias: foundPeer ? foundPeer.alias : '' };
return node;
@ -103,7 +103,7 @@ export const getSentPaymentsInformation = (req, res, next) => {
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
if (req.body.payments) {
const paymentsArr = req.body.payments.split(',');
return Promise.all(paymentsArr.map((payment) => getSentInfoFromPaymentRequest(req.session.selectedNode, payment))).
return Promise.all(paymentsArr?.map((payment) => getSentInfoFromPaymentRequest(req.session.selectedNode, payment))).
then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Sent Information Received', data: values });
return res.status(200).json(values);

@ -32,7 +32,7 @@ export const getPeers = (req, res, next) => {
peersNodeIds = peersNodeIds.substring(1);
return getFilteredNodes(req.session.selectedNode, peersNodeIds).then((peersWithAlias) => {
let foundPeer = null;
body.map((peer) => {
body?.map((peer) => {
foundPeer = peersWithAlias.find((peerWithAlias) => peer.nodeId === peerWithAlias.nodeId);
peer.alias = foundPeer ? foundPeer.alias : peer.nodeId.substring(0, 20);
return peer;
@ -82,7 +82,7 @@ export const connectPeer = (req, res, next) => {
peersNodeIds = peersNodeIds.substring(1);
return getFilteredNodes(req.session.selectedNode, peersNodeIds).then((peersWithAlias) => {
let foundPeer = null;
body.map((peer) => {
body?.map((peer) => {
foundPeer = peersWithAlias.find((peerWithAlias) => peer.nodeId === peerWithAlias.nodeId);
peer.alias = foundPeer ? foundPeer.alias : peer.nodeId.substring(0, 20);
return peer;

@ -57,7 +57,7 @@ export class ECLWebSocketClient {
public connectWithClient = (eclWsClt) => {
this.logger.log({ selectedNode: eclWsClt.selectedNode, level: 'INFO', fileName: 'ECLWebSocket', msg: 'Connecting to the Eclair\'s Websocket Server..' });
const UpdatedLNServerURL = (eclWsClt.selectedNode.ln_server_url).replace(/^http/, 'ws');
const UpdatedLNServerURL = (eclWsClt.selectedNode.ln_server_url)?.replace(/^http/, 'ws');
const firstSubStrIndex = (UpdatedLNServerURL.indexOf('//') + 2);
const WS_LINK = UpdatedLNServerURL.slice(0, firstSubStrIndex) + ':' + eclWsClt.selectedNode.ln_api_password + '@' + UpdatedLNServerURL.slice(firstSubStrIndex) + '/ws';
eclWsClt.webSocketClient = new WebSocket(WS_LINK);

@ -32,7 +32,7 @@ export const getAllChannels = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Channels List Received', data: body });
if (body.channels) {
return Promise.all(
body.channels.map((channel) => {
body.channels?.map((channel) => {
local = (channel.local_balance) ? +channel.local_balance : 0;
remote = (channel.remote_balance) ? +channel.remote_balance : 0;
total = local + remote;
@ -70,16 +70,16 @@ export const getPendingChannels = (req, res, next) => {
}
const promises = [];
if (body.pending_open_channels && body.pending_open_channels.length > 0) {
body.pending_open_channels.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
body.pending_open_channels?.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
}
if (body.pending_closing_channels && body.pending_closing_channels.length > 0) {
body.pending_closing_channels.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
body.pending_closing_channels?.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
}
if (body.pending_force_closing_channels && body.pending_force_closing_channels.length > 0) {
body.pending_force_closing_channels.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
body.pending_force_closing_channels?.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
}
if (body.waiting_close_channels && body.waiting_close_channels.length > 0) {
body.waiting_close_channels.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
body.waiting_close_channels?.map((channel) => promises.push(getAliasForChannel(req.session.selectedNode, channel.channel)));
}
return Promise.all(promises).then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Pending Channels List Received', data: body });
@ -104,7 +104,7 @@ export const getClosedChannels = (req, res, next) => {
request(options).then((body) => {
if (body.channels && body.channels.length > 0) {
return Promise.all(
body.channels.map((channel) => {
body.channels?.map((channel) => {
channel.close_type = (!channel.close_type) ? 'COOPERATIVE_CLOSE' : channel.close_type;
return getAliasForChannel(req.session.selectedNode, channel);
})
@ -190,7 +190,7 @@ export const closeChannel = (req, res, next) => {
}
options = common.getOptions(req);
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
const channelpoint = req.params.channelPoint.replace(':', '/');
const channelpoint = req.params.channelPoint?.replace(':', '/');
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/' + channelpoint + '?force=' + req.query.force;
if (req.query.target_conf) { options.url = options.url + '&target_conf=' + req.query.target_conf; }
if (req.query.sat_per_byte) { options.url = options.url + '&sat_per_byte=' + req.query.sat_per_byte; }

@ -22,7 +22,7 @@ function getFilesList(channelBackupPath, callback) {
if (file.toLowerCase() === 'channel-all.bak' || file.toLowerCase() === 'backup-channel-all.bak') {
all_restore_exists = true;
} else {
files_list.push({ channel_point: file.substring(8, file.length - 4).replace('-', ':') });
files_list.push({ channel_point: file.substring(8, file.length - 4)?.replace('-', ':') });
}
}
});
@ -43,9 +43,9 @@ export const getBackup = (req, res, next) => {
message = 'All Channels Backup Successful.';
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/backup';
} else {
channel_backup_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.params.channelPoint.replace(':', '-') + '.bak';
channel_backup_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
message = 'Channel Backup Successful.';
const channelpoint = req.params.channelPoint.replace(':', '/');
const channelpoint = req.params.channelPoint?.replace(':', '/');
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/backup/' + channelpoint;
const exists = fs.existsSync(channel_backup_file);
if (exists) {
@ -108,7 +108,7 @@ export const postBackupVerify = (req, res, next) => {
}
} else {
message = 'Channel Verify Successful.';
channel_verify_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.params.channelPoint.replace(':', '-') + '.bak';
channel_verify_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
const exists = fs.existsSync(channel_verify_file);
if (exists) {
verify_backup = fs.readFileSync(channel_verify_file, 'utf-8');
@ -173,7 +173,7 @@ export const postRestore = (req, res, next) => {
}
} else {
message = 'Channel Restore Successful.';
channel_restore_file = req.session.selectedNode.channel_backup_path + sep + 'restore' + sep + 'channel-' + req.params.channelPoint.replace(':', '-') + '.bak';
channel_restore_file = req.session.selectedNode.channel_backup_path + sep + 'restore' + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
const exists = fs.existsSync(channel_restore_file);
if (exists) {
restore_backup = fs.readFileSync(channel_restore_file, 'utf-8');

@ -21,9 +21,9 @@ export const getFees = (req, res, next) => {
const day_start_time = current_time - 86400;
return getAllForwardingEvents(req, month_start_time, current_time, 0, 'fees', (history) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Forwarding History Received', data: history });
const daily_sum = history.forwarding_events.reduce((acc, curr) => ((curr.timestamp >= day_start_time) ? [(acc[0] + 1), (acc[1] + +curr.fee_msat)] : acc), [0, 0]);
const weekly_sum = history.forwarding_events.reduce((acc, curr) => ((curr.timestamp >= week_start_time) ? [(acc[0] + 1), (acc[1] + +curr.fee_msat)] : acc), [0, 0]);
const monthly_sum = history.forwarding_events.reduce((acc, curr) => [(acc[0] + 1), (acc[1] + +curr.fee_msat)], [0, 0]);
const daily_sum = history.forwarding_events?.reduce((acc, curr) => ((curr.timestamp >= day_start_time) ? [(acc[0] + 1), (acc[1] + +curr.fee_msat)] : acc), [0, 0]);
const weekly_sum = history.forwarding_events?.reduce((acc, curr) => ((curr.timestamp >= week_start_time) ? [(acc[0] + 1), (acc[1] + +curr.fee_msat)] : acc), [0, 0]);
const monthly_sum = history.forwarding_events?.reduce((acc, curr) => [(acc[0] + 1), (acc[1] + +curr.fee_msat)], [0, 0]);
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Daily Sum (Transactions, Fee)', data: daily_sum });
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Weekly Sum (Transactions, Fee)', data: weekly_sum });
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Monthly Sum (Transactions, Fee)', data: monthly_sum });

@ -24,7 +24,7 @@ export const getInfo = (req, res, next) => {
const err = common.handleError({ statusCode: 502, message: 'Bad or Missing Macaroon', error: errMsg }, 'GetInfo', errMsg, req.session.selectedNode);
return res.status(err.statusCode).json({ message: err.message, error: err.error });
} else {
common.nodes.map((node: any) => {
common.nodes?.map((node: any) => {
if (node.ln_implementation === 'LND') {
common.getAllNodeAllChannelBackup(node);
}

@ -83,9 +83,9 @@ export const getQueryRoutes = (req, res, next) => {
request(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Graph', msg: 'Query Routes Received', data: body });
if (body.routes && body.routes.length && body.routes.length > 0 && body.routes[0].hops && body.routes[0].hops.length && body.routes[0].hops.length > 0) {
return Promise.all(body.routes[0].hops.map((hop) => getAliasFromPubkey(req.session.selectedNode, hop.pub_key))).
return Promise.all(body.routes[0].hops?.map((hop) => getAliasFromPubkey(req.session.selectedNode, hop.pub_key))).
then((values) => {
body.routes[0].hops.map((hop, i) => {
body.routes[0].hops?.map((hop, i) => {
hop.hop_sequence = i + 1;
hop.pubkey_alias = values[i];
return hop;
@ -141,7 +141,7 @@ export const getAliasesForPubkeys = (req, res, next) => {
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
if (req.query.pubkeys) {
const pubkeyArr = req.query.pubkeys.split(',');
return Promise.all(pubkeyArr.map((pubkey) => getAliasFromPubkey(req.session.selectedNode, pubkey))).
return Promise.all(pubkeyArr?.map((pubkey) => getAliasFromPubkey(req.session.selectedNode, pubkey))).
then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Node Alias', data: values });
res.status(200).json(values);

@ -35,7 +35,7 @@ export const decodePayments = (req, res, next) => {
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
if (req.body.payments) {
const paymentsArr = req.body.payments.split(',');
return Promise.all(paymentsArr.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
return Promise.all(paymentsArr?.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'PayRequest', msg: 'Payment List Decoded', data: values });
res.status(200).json(values);

@ -26,7 +26,7 @@ export const getPeers = (req, res, next) => {
request(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers List Received', data: body });
const peers = !body.peers ? [] : body.peers;
return Promise.all(peers.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
return Promise.all(peers?.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers with Alias before Sort', data: body });
if (body.peers) {
body.peers = common.sortDescByStrKey(body.peers, 'alias');
@ -54,7 +54,7 @@ export const postPeer = (req, res, next) => {
options.url = req.session.selectedNode.ln_server_url + '/v1/peers';
request(options).then((body) => {
const peers = (!body.peers) ? [] : body.peers;
return Promise.all(peers.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
return Promise.all(peers?.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
if (body.peers) {
body.peers = common.sortDescByStrKey(body.peers, 'alias');
body.peers = common.newestOnTop(body.peers, 'pub_key', req.body.pubkey);

@ -56,7 +56,7 @@ export class LNDWebSocketClient {
};
public subscribeToInvoice = (options: any, selectedNode: CommonSelectedNode, rHash: string) => {
rHash = rHash.replace(/\+/g, '-').replace(/[/]/g, '_');
rHash = rHash?.replace(/\+/g, '-')?.replace(/[/]/g, '_');
this.logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'WebSocketClient', msg: 'Subscribing to Invoice ' + rHash + ' ..' });
options.url = selectedNode.ln_server_url + '/v2/invoices/subscribe/' + rHash;
request(options).then((msg) => {

@ -235,7 +235,7 @@ export const getConfig = (req, res, next) => {
jsonConfig = JSON.parse(data);
} else {
fileFormat = 'INI';
data = data.replace('color=#', 'color=');
data = data?.replace('color=#', 'color=');
jsonConfig = ini.parse(data);
if (jsonConfig['Application Options'] && jsonConfig['Application Options'].color) {
jsonConfig['Application Options'].color = '#' + jsonConfig['Application Options'].color;
@ -246,7 +246,7 @@ export const getConfig = (req, res, next) => {
}
}
jsonConfig = maskPasswords(jsonConfig);
const responseJSON = (fileFormat === 'JSON') ? jsonConfig : ini.stringify(jsonConfig).replace('color=\\#', 'color=#');
const responseJSON = (fileFormat === 'JSON') ? jsonConfig : ini.stringify(jsonConfig)?.replace('color=\\#', 'color=#');
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Configuration File Data Received', data: responseJSON });
res.status(200).json({ format: fileFormat, data: responseJSON });
}
@ -255,7 +255,7 @@ export const getConfig = (req, res, next) => {
export const getFile = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting File..' });
const file = req.query.path ? req.query.path : (req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.query.channel.replace(':', '-') + '.bak');
const file = req.query.path ? req.query.path : (req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.query.channel?.replace(':', '-') + '.bak');
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'Channel Point', data: req.query.channel });
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'File Path', data: file });
fs.readFile(file, 'utf8', (errRes, data) => {

@ -21,7 +21,7 @@ export const isAuthenticated = (req, res, next) => {
export const verifyWSUser = (info, next) => {
const headers = JSON.parse(JSON.stringify(info.req.headers));
const protocols = !info.req.headers['sec-websocket-protocol'] ? [] : info.req.headers['sec-websocket-protocol'].split(',').map((s) => s.trim());
const protocols = !info.req.headers['sec-websocket-protocol'] ? [] : info.req.headers['sec-websocket-protocol'].split(',')?.map((s) => s.trim());
const jwToken = (protocols && protocols.length > 0) ? protocols[0] : '';
if (!jwToken || jwToken === '') {
next(false, 401, 'Authentication Failed! Please Login First!');
@ -39,7 +39,7 @@ export const verifyWSUser = (info, next) => {
}
let cookies = null;
try {
cookies = '{"' + headers.cookie.replace(/ /g, '').replace(/;/g, '","').trim().replace(/[=]/g, '":"') + '"}';
cookies = '{"' + headers.cookie?.replace(/ /g, '')?.replace(/;/g, '","').trim()?.replace(/[=]/g, '":"') + '"}';
updatedReq['cookies'] = JSON.parse(cookies);
} catch (err) {
cookies = {};

@ -214,18 +214,18 @@ export class CommonService {
public newestOnTop = (array, key, value) => {
const newlyAddedRecord = array.splice(array.findIndex((item) => item[key] === value), 1);
array.unshift(newlyAddedRecord[0]);
array?.unshift(newlyAddedRecord[0]);
return array;
};
public camelCase = (str: string) => str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (word.toUpperCase())).replace(/\s+/g, '').replace(/-/g, ' ');
public camelCase = (str: string) => str?.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (word.toUpperCase()))?.replace(/\s+/g, '')?.replace(/-/g, ' ');
public titleCase = (str: string) => {
if (str.indexOf('!\n') > 0 || str.indexOf('.\n') > 0) {
return str.split('\n').reduce((accumulator, currentStr) => accumulator + currentStr.charAt(0).toUpperCase() + currentStr.substring(1).toLowerCase() + '\n', '');
return str.split('\n')?.reduce((accumulator, currentStr) => accumulator + currentStr.charAt(0).toUpperCase() + currentStr.substring(1).toLowerCase() + '\n', '');
} else {
if (str.indexOf(' ') > 0) {
return str.split(' ').reduce((accumulator, currentStr) => accumulator + currentStr.charAt(0).toUpperCase() + currentStr.substring(1).toLowerCase() + ' ', '');
return str.split(' ')?.reduce((accumulator, currentStr) => accumulator + currentStr.charAt(0).toUpperCase() + currentStr.substring(1).toLowerCase() + ' ', '');
} else {
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
}
@ -345,7 +345,7 @@ export class CommonService {
public createDirectory = (directoryName) => {
const initDir = isAbsolute(directoryName) ? sep : '';
directoryName.split(sep).reduce((parentDir, childDir) => {
directoryName.split(sep)?.reduce((parentDir, childDir) => {
const curDir = resolve(parentDir, childDir);
try {
if (!fs.existsSync(curDir)) {
@ -412,7 +412,7 @@ export class CommonService {
public isVersionCompatible = (currentVersion, checkVersion) => {
if (currentVersion) {
const versionsArr = currentVersion.trim().replace('v', '').split('-')[0].split('.') || [];
const versionsArr = currentVersion.trim()?.replace('v', '').split('-')[0].split('.') || [];
const checkVersionsArr = checkVersion.split('.');
return (+versionsArr[0] > +checkVersionsArr[0]) ||
(+versionsArr[0] === +checkVersionsArr[0] && +versionsArr[1] > +checkVersionsArr[1]) ||

@ -42,7 +42,7 @@ export class RTLWebSocketServer {
const acceptKey = request.headers['sec-websocket-key'];
const hash = this.generateAcceptValue(acceptKey);
const responseHeaders = ['HTTP/1.1 101 Web Socket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', 'Sec-WebSocket-Accept: ' + hash];
const protocols = !request.headers['sec-websocket-protocol'] ? [] : request.headers['sec-websocket-protocol'].split(',').map((s) => s.trim());
const protocols = !request.headers['sec-websocket-protocol'] ? [] : request.headers['sec-websocket-protocol'].split(',')?.map((s) => s.trim());
if (protocols.includes('json')) { responseHeaders.push('Sec-WebSocket-Protocol: json'); }
this.webSocketServer.handleUpgrade(request, socket, head, this.upgradeCallback);
});
@ -56,7 +56,7 @@ export class RTLWebSocketServer {
};
public mountEventsOnConnection = (websocket, request) => {
const protocols = !request.headers['sec-websocket-protocol'] ? [] : request.headers['sec-websocket-protocol'].split(',').map((s) => s.trim());
const protocols = !request.headers['sec-websocket-protocol'] ? [] : request.headers['sec-websocket-protocol'].split(',')?.map((s) => s.trim());
const cookies = parse(request.headers.cookie);
websocket.clientId = Date.now();
websocket.isAlive = true;

@ -155,8 +155,8 @@ export class CLNHomeComponent implements OnInit, OnDestroy {
this.totalOutboundLiquidity = 0;
this.activeChannels = channelsSeletor.activeChannels;
this.activeChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels, 'balancedness'))) || [];
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels.filter((channel) => (channel.msatoshi_to_them ? channel.msatoshi_to_them > 0 : false)), 'msatoshi_to_them'))) || [];
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels.filter((channel) => (channel.msatoshi_to_us ? channel.msatoshi_to_us > 0 : false)), 'msatoshi_to_us'))) || [];
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels?.filter((channel) => (channel.msatoshi_to_them ? channel.msatoshi_to_them > 0 : false)), 'msatoshi_to_them'))) || [];
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels?.filter((channel) => (channel.msatoshi_to_us ? channel.msatoshi_to_us > 0 : false)), 'msatoshi_to_us'))) || [];
this.activeChannels.forEach((channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + Math.ceil((channel.msatoshi_to_them || 0) / 1000);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + Math.floor((channel.msatoshi_to_us || 0) / 1000);

@ -80,7 +80,7 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
subscribe({
next: ([infoSettingsBalSelector, nodeListRes]) => {
this.information = infoSettingsBalSelector.information;
this.totalBalance = infoSettingsBalSelector.balance.totalBalance;
this.totalBalance = infoSettingsBalSelector.balance.totalBalance || 0;
this.logger.info(infoSettingsBalSelector);
if (nodeListRes && !(<any[]>nodeListRes).length) { nodeListRes = []; }
this.logger.info('Received Liquidity Ads Enabled Nodes: ' + JSON.stringify(nodeListRes));
@ -108,7 +108,7 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
onCalculateOpeningFee() {
this.liquidityNodesData.forEach((lqNode) => {
if (lqNode.option_will_fund) {
lqNode.channelOpeningFee = (+(lqNode.option_will_fund.lease_fee_base_msat) / 1000) + (this.channelAmount * (+lqNode.option_will_fund.lease_fee_basis) / 10000) + ((+lqNode.option_will_fund.funding_weight / 4) * this.channelOpeningFeeRate);
lqNode.channelOpeningFee = (+(lqNode.option_will_fund.lease_fee_base_msat || 0) / 1000) + (this.channelAmount * (+(lqNode.option_will_fund.lease_fee_basis || 0)) / 10000) + ((+(lqNode.option_will_fund.funding_weight || 0) / 4) * this.channelOpeningFeeRate);
}
});
if (this.paginator) { this.paginator.firstPage(); }
@ -124,7 +124,7 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
this.liquidityNodes.sort = this.sort;
this.liquidityNodes.paginator = this.paginator;
if (this.sort) { this.sort.sort({ id: 'channelOpeningFee', start: 'asc', disableClear: true }); }
this.liquidityNodes.filterPredicate = (node: LookupNode, fltr: string) => node.channelCount >= this.channelCount && node.nodeCapacity >= this.nodeCapacity;
this.liquidityNodes.filterPredicate = (node: LookupNode, fltr: string) => (node.channelCount || 0) >= this.channelCount && (node.nodeCapacity || 0) >= this.nodeCapacity;
this.onFilter();
}
@ -156,19 +156,19 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
}
onViewLeaseInfo(lqNode: LookupNode) {
const addArr = lqNode.addresses.reduce((acc, curr) => {
const addArr = lqNode.addresses?.reduce((acc, curr) => {
if (curr.address && curr.address.length > 40) { curr.address = curr.address.substring(0, 39) + '...'; }
return acc.concat(JSON.stringify(curr).replace('{', '').replace('}', '').replace(/:/g, ': ').replace(/,/g, '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;').replace(/"/g, ''));
}, []);
return acc.concat(JSON.stringify(curr)?.replace('{', '')?.replace('}', '')?.replace(/:/g, ': ')?.replace(/,/g, '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')?.replace(/"/g, ''));
}, <any[]>[]);
const reorderedLQNode = [
[{ key: 'alias', value: lqNode.alias, title: 'Node Alias', width: 50, type: DataTypeEnum.STRING },
{ key: 'last_timestamp', value: lqNode.last_timestamp, title: 'Last Timestamp', width: 50, type: DataTypeEnum.DATE_TIME }],
[{ key: 'nodeid', value: lqNode.nodeid, title: 'Node ID', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'base_fee', value: (lqNode.option_will_fund.lease_fee_base_msat / 1000), title: 'Lease Base Fee (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'fee_basis', value: lqNode.option_will_fund.lease_fee_basis, title: 'Lease Base Basis (bps)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'channel_max_base', value: lqNode.option_will_fund.channel_fee_max_base_msat / 1000, title: 'Max Channel Routing Base Fee (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'channel_max_rate', value: lqNode.option_will_fund.channel_fee_max_proportional_thousandths * 1000, title: 'Max Channel Routing Fee Rate (ppm)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'funding_rate', value: lqNode.option_will_fund.funding_weight, title: 'Funding Weight', width: 100, type: DataTypeEnum.NUMBER }],
[{ key: 'base_fee', value: ((lqNode.option_will_fund?.lease_fee_base_msat || 0) / 1000), title: 'Lease Base Fee (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'fee_basis', value: lqNode.option_will_fund?.lease_fee_basis, title: 'Lease Base Basis (bps)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'channel_max_base', value: (lqNode.option_will_fund?.channel_fee_max_base_msat || 0) / 1000, title: 'Max Channel Routing Base Fee (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'channel_max_rate', value: (lqNode.option_will_fund?.channel_fee_max_proportional_thousandths || 0) * 1000, title: 'Max Channel Routing Fee Rate (ppm)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'funding_rate', value: (lqNode.option_will_fund?.funding_weight || 0), title: 'Funding Weight', width: 100, type: DataTypeEnum.NUMBER }],
[{ key: 'address', value: addArr, title: 'Address', width: 100, type: DataTypeEnum.ARRAY }]
];
this.store.dispatch(openConfirmation({

@ -136,7 +136,7 @@ export class CLNOnChainSendModalComponent implements OnInit, OnDestroy {
});
this.store.select(utxos).pipe(takeUntil(this.unSubs[3])).
subscribe((utxosSeletor: { utxos: UTXO[], apiCallStatus: ApiCallStatusPayload }) => {
this.utxos = this.commonService.sortAscByKey(utxosSeletor.utxos.filter((utxo) => utxo.status === 'confirmed'), 'value');
this.utxos = this.commonService.sortAscByKey(utxosSeletor.utxos?.filter((utxo) => utxo.status === 'confirmed'), 'value');
this.logger.info(utxosSeletor);
});
this.actions.pipe(
@ -274,7 +274,7 @@ export class CLNOnChainSendModalComponent implements OnInit, OnDestroy {
onUTXOSelectionChange(event: any) {
const utxoNew = { value: 0 };
if (this.selUTXOs.length && this.selUTXOs.length > 0) {
this.totalSelectedUTXOAmount = this.selUTXOs.reduce((a, b) => {
this.totalSelectedUTXOAmount = this.selUTXOs?.reduce((a, b) => {
utxoNew.value = a.value + b.value;
return utxoNew;
}).value;
@ -307,7 +307,7 @@ export class CLNOnChainSendModalComponent implements OnInit, OnDestroy {
subscribe({
next: (data) => {
this.selAmountUnit = event.value;
self.transaction.satoshis = self.decimalPipe.transform(data[currSelectedUnit], self.currencyUnitFormats[currSelectedUnit]).replace(/,/g, '');
self.transaction.satoshis = self.decimalPipe.transform(data[currSelectedUnit], self.currencyUnitFormats[currSelectedUnit])?.replace(/,/g, '');
}, error: (err) => {
self.transaction.satoshis = null;
this.amountError = 'Conversion Error: ' + err;

@ -33,7 +33,7 @@ export class CLNUTXOTablesComponent implements OnInit, OnDestroy {
if (utxosSeletor.utxos && utxosSeletor.utxos.length > 0) {
this.utxos = utxosSeletor.utxos;
this.numUtxos = this.utxos.length;
this.dustUtxos = utxosSeletor.utxos.filter((utxo) => +utxo.value < 1000);
this.dustUtxos = utxosSeletor.utxos?.filter((utxo) => +utxo.value < 1000);
this.numDustUtxos = this.dustUtxos.length;
}
if (utxosSeletor.utxos && utxosSeletor.utxos.length > 0) {

@ -56,7 +56,7 @@ export class CLNChannelsTablesComponent implements OnInit, OnDestroy {
});
this.store.select(utxos).pipe(takeUntil(this.unSubs[3])).
subscribe((utxosSeletor: { utxos: UTXO[], apiCallStatus: ApiCallStatusPayload }) => {
this.utxos = this.commonService.sortAscByKey(utxosSeletor.utxos.filter((utxo) => utxo.status === 'confirmed'), 'value');
this.utxos = this.commonService.sortAscByKey(utxosSeletor.utxos?.filter((utxo) => utxo.status === 'confirmed'), 'value');
});
this.store.select(channels).pipe(takeUntil(this.unSubs[4])).
subscribe((channelsSeletor: { activeChannels: Channel[], pendingChannels: Channel[], inactiveChannels: Channel[], apiCallStatus: ApiCallStatusPayload }) => {

@ -89,7 +89,7 @@ export class CLNOpenChannelComponent implements OnInit, OnDestroy {
}
private filterPeers(newlySelectedPeer: string): Peer[] {
return this.sortedPeers.filter((peer) => peer.alias.toLowerCase().indexOf(newlySelectedPeer ? newlySelectedPeer.toLowerCase() : '') === 0);
return this.sortedPeers?.filter((peer) => peer.alias.toLowerCase().indexOf(newlySelectedPeer ? newlySelectedPeer.toLowerCase() : '') === 0);
}
displayFn(peer: Peer): string {
@ -100,7 +100,7 @@ export class CLNOpenChannelComponent implements OnInit, OnDestroy {
this.channelConnectionError = '';
this.selectedPubkey = (this.selectedPeer.value && this.selectedPeer.value.id) ? this.selectedPeer.value.id : null;
if (typeof this.selectedPeer.value === 'string') {
const selPeer = this.peers.filter((peer) => peer.alias.length === this.selectedPeer.value.length && peer.alias.toLowerCase().indexOf(this.selectedPeer.value ? this.selectedPeer.value.toLowerCase() : '') === 0);
const selPeer = this.peers?.filter((peer) => peer.alias.length === this.selectedPeer.value.length && peer.alias.toLowerCase().indexOf(this.selectedPeer.value ? this.selectedPeer.value.toLowerCase() : '') === 0);
if (selPeer.length === 1 && selPeer[0].id) {
this.selectedPubkey = selPeer[0].id;
}
@ -152,7 +152,7 @@ export class CLNOpenChannelComponent implements OnInit, OnDestroy {
onUTXOSelectionChange(event: any) {
const utxoNew = { value: 0 };
if (this.selUTXOs.length && this.selUTXOs.length > 0) {
this.totalSelectedUTXOAmount = this.selUTXOs.reduce((a, b) => {
this.totalSelectedUTXOAmount = this.selUTXOs?.reduce((a, b) => {
utxoNew.value = a.value + b.value;
return utxoNew;
}).value;

@ -130,7 +130,7 @@ export class CLNRoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < 12; i++) {
feeReport.push({ name: MONTHS[i].name, value: 0.0, extra: { totalEvents: 0 } });
}
this.filteredEventsBySelectedPeriod.map((event) => {
this.filteredEventsBySelectedPeriod?.map((event) => {
const monthNumber = event.received_time ? new Date((+event.received_time) * 1000).getMonth() : 12;
feeReport[monthNumber].value = event.fee ? feeReport[monthNumber].value + (+event.fee / 1000) : feeReport[monthNumber].value;
feeReport[monthNumber].extra.totalEvents = feeReport[monthNumber].extra.totalEvents + 1;
@ -141,7 +141,7 @@ export class CLNRoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
feeReport.push({ name: i + 1, value: 0.0, extra: { totalEvents: 0 } });
}
this.filteredEventsBySelectedPeriod.map((event) => {
this.filteredEventsBySelectedPeriod?.map((event) => {
const dateNumber = event.received_time ? Math.floor((+event.received_time - startDateInSeconds) / this.secondsInADay) : 0;
feeReport[dateNumber].value = event.fee ? feeReport[dateNumber].value + (+event.fee / 1000) : feeReport[dateNumber].value;
feeReport[dateNumber].extra.totalEvents = feeReport[dateNumber].extra.totalEvents + 1;
@ -160,7 +160,7 @@ export class CLNRoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < 12; i++) {
eventsReport.push({ name: MONTHS[i].name, value: 0, extra: { totalFees: 0.0 } });
}
this.filteredEventsBySelectedPeriod.map((event) => {
this.filteredEventsBySelectedPeriod?.map((event) => {
const monthNumber = event.received_time ? new Date((+event.received_time) * 1000).getMonth() : 12;
eventsReport[monthNumber].value = eventsReport[monthNumber].value + 1;
eventsReport[monthNumber].extra.totalFees = event.fee ? eventsReport[monthNumber].extra.totalFees + (+event.fee / 1000) : eventsReport[monthNumber].extra.totalFees;
@ -171,7 +171,7 @@ export class CLNRoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
eventsReport.push({ name: i + 1, value: 0, extra: { totalFees: 0.0 } });
}
this.filteredEventsBySelectedPeriod.map((event) => {
this.filteredEventsBySelectedPeriod?.map((event) => {
const dateNumber = event.received_time ? Math.floor((+event.received_time - startDateInSeconds) / this.secondsInADay) : 0;
eventsReport[dateNumber].value = eventsReport[dateNumber].value + 1;
eventsReport[dateNumber].extra.totalFees = event.fee ? eventsReport[dateNumber].extra.totalFees + (+event.fee / 1000) : eventsReport[dateNumber].extra.totalFees;

@ -95,22 +95,22 @@ export class CLNTransactionsReportComponent implements OnInit, OnDestroy {
const endDateInSeconds = Math.round(end.getTime() / 1000);
const transactionsReport = [];
this.transactionsReportSummary = { paymentsSelectedPeriod: 0, invoicesSelectedPeriod: 0, amountPaidSelectedPeriod: 0, amountReceivedSelectedPeriod: 0 };
const filteredPayments = this.payments.filter((payment) => payment.status === 'complete' && payment.created_at >= startDateInSeconds && payment.created_at < endDateInSeconds);
const filteredInvoices = this.invoices.filter((invoice) => invoice.status === 'paid' && invoice.paid_at >= startDateInSeconds && invoice.paid_at < endDateInSeconds);
const filteredPayments = this.payments?.filter((payment) => payment.status === 'complete' && payment.created_at >= startDateInSeconds && payment.created_at < endDateInSeconds);
const filteredInvoices = this.invoices?.filter((invoice) => invoice.status === 'paid' && invoice.paid_at >= startDateInSeconds && invoice.paid_at < endDateInSeconds);
this.transactionsReportSummary.paymentsSelectedPeriod = filteredPayments.length;
this.transactionsReportSummary.invoicesSelectedPeriod = filteredInvoices.length;
if (this.reportPeriod === SCROLL_RANGES[1]) {
for (let i = 0; i < 12; i++) {
transactionsReport.push({ name: MONTHS[i].name, date: new Date(start.getFullYear(), i, 1, 0, 0, 0, 0), series: [{ name: 'Paid', value: 0, extra: { total: 0 } }, { name: 'Received', value: 0, extra: { total: 0 } }] });
}
filteredPayments.map((payment) => {
filteredPayments?.map((payment) => {
const monthNumber = new Date((payment.created_at) * 1000).getMonth();
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + payment.msatoshi_sent;
transactionsReport[monthNumber].series[0].value = transactionsReport[monthNumber].series[0].value + (payment.msatoshi_sent / 1000);
transactionsReport[monthNumber].series[0].extra.total = transactionsReport[monthNumber].series[0].extra.total + 1;
return this.transactionsReportSummary;
});
filteredInvoices.map((invoice) => {
filteredInvoices?.map((invoice) => {
const monthNumber = new Date((+invoice.paid_at) * 1000).getMonth();
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + invoice.msatoshi_received;
transactionsReport[monthNumber].series[1].value = transactionsReport[monthNumber].series[1].value + (invoice.msatoshi_received / 1000);
@ -121,14 +121,14 @@ export class CLNTransactionsReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
transactionsReport.push({ name: (i + 1).toString(), date: new Date((((i) * this.secondsInADay) + startDateInSeconds) * 1000), series: [{ name: 'Paid', value: 0, extra: { total: 0 } }, { name: 'Received', value: 0, extra: { total: 0 } }] });
}
filteredPayments.map((payment) => {
filteredPayments?.map((payment) => {
const dateNumber = Math.floor((+payment.created_at - startDateInSeconds) / this.secondsInADay);
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + payment.msatoshi_sent;
transactionsReport[dateNumber].series[0].value = transactionsReport[dateNumber].series[0].value + (payment.msatoshi_sent / 1000);
transactionsReport[dateNumber].series[0].extra.total = transactionsReport[dateNumber].series[0].extra.total + 1;
return this.transactionsReportSummary;
});
filteredInvoices.map((invoice) => {
filteredInvoices?.map((invoice) => {
const dateNumber = Math.floor((+invoice.paid_at - startDateInSeconds) / this.secondsInADay);
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + invoice.msatoshi_received;
transactionsReport[dateNumber].series[1].value = transactionsReport[dateNumber].series[1].value + (invoice.msatoshi_received / 1000);
@ -140,7 +140,7 @@ export class CLNTransactionsReportComponent implements OnInit, OnDestroy {
}
prepareTableData() {
return this.transactionsReportData.reduce((acc, curr) => {
return this.transactionsReportData?.reduce((acc, curr) => {
if (curr.series[0].extra.total > 0 || curr.series[1].extra.total > 0) {
return acc.concat({ date: curr.date, amount_paid: curr.series[0].value, num_payments: curr.series[0].extra.total, amount_received: curr.series[1].value, num_invoices: curr.series[1].extra.total });
}

@ -100,7 +100,7 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
{ key: 'fee', value: selFEvent.fee, title: 'Fee (mSats)', width: 34, type: DataTypeEnum.NUMBER }]
];
if (selFEvent.payment_hash) {
reorderedFHEvent.unshift([{ key: 'payment_hash', value: selFEvent.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }]);
reorderedFHEvent?.unshift([{ key: 'payment_hash', value: selFEvent.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }]);
}
this.store.dispatch(openAlert({
payload: {

@ -66,5 +66,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<mat-paginator *ngIf="errorMessage === ''" [length]="totalForwardedTransactions" (page)="onPageChange($event)" [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
<mat-paginator *ngIf="errorMessage === ''" [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div>

@ -4,7 +4,7 @@ import { DatePipe } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl, PageEvent } from '@angular/material/paginator';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
@ -37,7 +37,6 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
public displayedColumns: any[] = [];
public forwardingHistoryEvents: any;
public flgSticky = false;
private indexOffset = -1;
public totalForwardedTransactions = 0;
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
@ -81,7 +80,7 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
this.totalForwardedTransactions = fhSeletor.forwardingHistory.totalForwards || 0;
this.successfulEvents = fhSeletor.forwardingHistory.listForwards || [];
if (this.successfulEvents.length > 0 && this.sort && this.paginator) {
this.loadForwardingEventsTable(this.successfulEvents.slice(0, this.pageSize));
this.loadForwardingEventsTable(this.successfulEvents);
}
this.logger.info(fhSeletor);
}
@ -90,7 +89,7 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
ngAfterViewInit() {
if (this.successfulEvents.length > 0) {
this.loadForwardingEventsTable(this.successfulEvents.slice(0, this.pageSize));
this.loadForwardingEventsTable(this.successfulEvents);
}
}
@ -99,11 +98,10 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
this.apiCallStatus = { status: APICallStatusEnum.COMPLETED, action: 'FetchForwardingHistory' };
this.eventsData = changes.eventsData.currentValue;
this.successfulEvents = this.eventsData;
this.indexOffset = 0;
this.totalForwardedTransactions = this.eventsData.length;
if (this.paginator) { this.paginator.firstPage(); }
if (!changes.eventsData.firstChange) {
this.loadForwardingEventsTable(this.successfulEvents.slice(0, this.pageSize));
this.loadForwardingEventsTable(this.successfulEvents);
}
}
if (changes.filterValue && !changes.filterValue.firstChange) {
@ -146,6 +144,7 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
(event.in_msatoshi ? (event.in_msatoshi / 1000) + ' ' : '') + (event.out_msatoshi ? (event.out_msatoshi / 1000) + ' ' : '') + (event.fee ? event.fee + ' ' : '');
return newEvent.includes(fltr);
};
this.forwardingHistoryEvents.paginator = this.paginator;
this.logger.info(this.forwardingHistoryEvents);
}
@ -161,16 +160,6 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
}
}
onPageChange(event: PageEvent) {
if (this.pageSize !== event.pageSize) {
this.pageSize = event.pageSize;
this.indexOffset = 0;
} else {
this.indexOffset = event.pageIndex * this.pageSize;
}
this.loadForwardingEventsTable(this.successfulEvents.slice(this.indexOffset, (this.indexOffset + this.pageSize)));
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null);

@ -7,7 +7,7 @@ import { GetInfo, Fees, Peer, Payment, QueryRoutes, Channel, FeeRates, Invoice,
export const updateCLAPICallStatus = createAction(CLNActions.UPDATE_API_CALL_STATUS_CLN, props<{ payload: ApiCallStatusPayload }>());
export const resetCLStore = createAction(CLNActions.RESET_CLN_STORE, props<{ payload: SelNodeChild }>());
export const resetCLStore = createAction(CLNActions.RESET_CLN_STORE, props<{ payload: SelNodeChild | null }>());
export const setChildNodeSettingsCL = createAction(CLNActions.SET_CHILD_NODE_SETTINGS_CLN, props<{ payload: SelNodeChild }>());

@ -950,9 +950,9 @@ export class CLNEffects implements OnDestroy {
this.store.dispatch(setNodeData({ payload: node_data }));
let newRoute = this.location.path();
if (newRoute.includes('/lnd/')) {
newRoute = newRoute.replace('/lnd/', '/cln/');
newRoute = newRoute?.replace('/lnd/', '/cln/');
} else if (newRoute.includes('/ecl/')) {
newRoute = newRoute.replace('/ecl/', '/cln/');
newRoute = newRoute?.replace('/ecl/', '/cln/');
}
if (newRoute.includes('/login') || newRoute.includes('/error') || newRoute === '' || landingPage === 'HOME' || newRoute.includes('?access-key=')) {
newRoute = '/cln/home';

@ -12,7 +12,7 @@ import { CLNForwardingEventsStatusEnum } from '../../shared/services/consts-enum
export const CLNReducer = createReducer(initCLNState,
on(updateCLAPICallStatus, (state, { payload }) => {
const updatedApisCallStatus = JSON.parse(JSON.stringify(state.apisCallStatus));
updatedApisCallStatus[payload.action] = {
updatedApisCallStatus[payload.action || 0] = {
status: payload.status,
statusCode: payload.statusCode,
message: payload.message,
@ -114,7 +114,7 @@ export const CLNReducer = createReducer(initCLNState,
switch (payload.status) {
case CLNForwardingEventsStatusEnum.SETTLED:
const modifiedFeeWithTxCount = state.fees;
modifiedFeeWithTxCount.totalTxCount = payload.totalForwards | 0;
modifiedFeeWithTxCount.totalTxCount = payload.totalForwards || 0;
return {
...state,
fees: modifiedFeeWithTxCount,
@ -136,7 +136,7 @@ export const CLNReducer = createReducer(initCLNState,
}),
on(addInvoice, (state, { payload }) => {
const newInvoices = state.invoices;
newInvoices.invoices.unshift(payload);
newInvoices.invoices?.unshift(payload);
return {
...state,
invoices: newInvoices
@ -148,7 +148,7 @@ export const CLNReducer = createReducer(initCLNState,
})),
on(updateInvoice, (state, { payload }) => {
const modifiedInvoices = state.invoices;
modifiedInvoices.invoices = modifiedInvoices.invoices.map((invoice) => ((invoice.label === payload.label) ? payload : invoice));
modifiedInvoices.invoices = modifiedInvoices.invoices?.map((invoice) => ((invoice.label === payload.label) ? payload : invoice));
return {
...state,
invoices: modifiedInvoices
@ -164,7 +164,7 @@ export const CLNReducer = createReducer(initCLNState,
})),
on(addOffer, (state, { payload }) => {
const newOffers = state.offers;
newOffers.unshift(payload);
newOffers?.unshift(payload);
return {
...state,
offers: newOffers
@ -189,7 +189,7 @@ export const CLNReducer = createReducer(initCLNState,
const newOfferBMs: OfferBookmark[] = [...state.offersBookmarks];
const offerBMExistsIdx = newOfferBMs.findIndex((offer: OfferBookmark) => offer.bolt12 === payload.bolt12);
if (offerBMExistsIdx < 0) {
newOfferBMs.unshift(payload);
newOfferBMs?.unshift(payload);
} else {
const updatedOffer = { ...newOfferBMs[offerBMExistsIdx] };
updatedOffer.title = payload.title;
@ -226,7 +226,7 @@ const mapAliases = (payload: any, storedChannels: Channel[]) => {
fhEvent.in_channel_alias = storedChannels[idx].alias ? storedChannels[idx].alias : fhEvent.in_channel;
if (fhEvent.out_channel_alias) { return; }
}
if (storedChannels[idx].short_channel_id && storedChannels[idx].short_channel_id.toString() === fhEvent.out_channel) {
if (storedChannels[idx].short_channel_id && storedChannels[idx].short_channel_id?.toString() === fhEvent.out_channel) {
fhEvent.out_channel_alias = storedChannels[idx].alias ? storedChannels[idx].alias : fhEvent.out_channel;
if (fhEvent.in_channel_alias) { return; }
}

@ -5,7 +5,7 @@ import { ApiCallsListCL } from '../../shared/models/apiCallsPayload';
export interface CLNState {
apisCallStatus: ApiCallsListCL;
nodeSettings: SelNodeChild;
nodeSettings: SelNodeChild | null;
information: GetInfo;
fees: Fees;
feeRatesPerKB: FeeRates;

@ -214,7 +214,7 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
}
updateInvoicesData(newInvoice: Invoice) {
this.invoiceJSONArr = this.invoiceJSONArr.map((invoice) => ((invoice.label === newInvoice.label) ? newInvoice : invoice));
this.invoiceJSONArr = this.invoiceJSONArr?.map((invoice) => ((invoice.label === newInvoice.label) ? newInvoice : invoice));
}
loadInvoicesTable(invs: Invoice[]) {

@ -41,12 +41,12 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faHistory = faHistory;
public newlyAddedPayment = '';
public selNode: SelNodeChild = {};
public selNode: SelNodeChild | null = {};
public information: GetInfo = {};
public payments: any;
public paymentJSONArr: Payment[] = [];
public displayedColumns: any[] = [];
public mppColumns = [];
public mppColumns: string[] = [];
public paymentDecoded: PayRequest = {};
public paymentRequest = '';
public paymentDecodedHint = '';
@ -83,7 +83,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
}
ngOnInit() {
this.store.select(clnNodeSettings).pipe(takeUntil(this.unSubs[0])).subscribe((nodeSettings: SelNodeChild) => {
this.store.select(clnNodeSettings).pipe(takeUntil(this.unSubs[0])).subscribe((nodeSettings: SelNodeChild | null) => {
this.selNode = nodeSettings;
});
this.store.select(clnNodeInformation).pipe(takeUntil(this.unSubs[1])).subscribe((nodeInfo: GetInfo) => {
@ -111,7 +111,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
}
is_group(index: number, payment: Payment): boolean {
return payment.is_group;
return payment.is_group || false;
}
onSendPayment(): boolean | void {
@ -137,7 +137,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
}
sendPayment() {
this.newlyAddedPayment = this.paymentDecoded.payment_hash;
this.newlyAddedPayment = this.paymentDecoded?.payment_hash || '';
if (!this.paymentDecoded.msatoshi || this.paymentDecoded.msatoshi === 0) {
const reorderedPaymentDecoded = [
[{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }],
@ -213,8 +213,8 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
pipe(takeUntil(this.unSubs[1])).subscribe((decodedPayment: PayRequest) => {
this.paymentDecoded = decodedPayment;
if (this.paymentDecoded.msatoshi) {
if (this.selNode.fiatConversion) {
this.commonService.convertCurrency(this.paymentDecoded.msatoshi ? this.paymentDecoded.msatoshi / 1000 : 0, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, this.selNode.currencyUnits[2], this.selNode.fiatConversion).
if (this.selNode?.fiatConversion) {
this.commonService.convertCurrency(this.paymentDecoded.msatoshi ? this.paymentDecoded.msatoshi / 1000 : 0, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, (this.selNode.currencyUnits && this.selNode.currencyUnits.length > 2 ? this.selNode.currencyUnits[2] : ''), this.selNode.fiatConversion).
pipe(takeUntil(this.unSubs[3])).
subscribe({
next: (data) => {
@ -260,19 +260,19 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
{ key: 'msatoshi_sent', value: selPayment.msatoshi_sent, title: 'Amount Sent (mSats)', width: 50, type: DataTypeEnum.NUMBER }]
];
if (selPayment.bolt11 && selPayment.bolt11 !== '') {
reorderedPayment.unshift([{ key: 'bolt11', value: selPayment.bolt11, title: 'Bolt 11', width: 100, type: DataTypeEnum.STRING }]);
reorderedPayment?.unshift([{ key: 'bolt11', value: selPayment.bolt11, title: 'Bolt 11', width: 100, type: DataTypeEnum.STRING }]);
}
if (selPayment.bolt12 && selPayment.bolt12 !== '') {
reorderedPayment.unshift([{ key: 'bolt12', value: selPayment.bolt12, title: 'Bolt 12', width: 100, type: DataTypeEnum.STRING }]);
reorderedPayment?.unshift([{ key: 'bolt12', value: selPayment.bolt12, title: 'Bolt 12', width: 100, type: DataTypeEnum.STRING }]);
}
if (selPayment.memo && selPayment.memo !== '') {
reorderedPayment.splice(2, 0, [{ key: 'memo', value: selPayment.memo, title: 'Memo', width: 100, type: DataTypeEnum.STRING }]);
reorderedPayment?.splice(2, 0, [{ key: 'memo', value: selPayment.memo, title: 'Memo', width: 100, type: DataTypeEnum.STRING }]);
}
if (selPayment.hasOwnProperty('partid')) {
reorderedPayment.unshift([{ key: 'payment_hash', value: selPayment.payment_hash, title: 'Payment Hash', width: 80, type: DataTypeEnum.STRING },
reorderedPayment?.unshift([{ key: 'payment_hash', value: selPayment.payment_hash, title: 'Payment Hash', width: 80, type: DataTypeEnum.STRING },
{ key: 'partid', value: selPayment.partid, title: 'Part ID', width: 20, type: DataTypeEnum.STRING }]);
} else {
reorderedPayment.unshift([{ key: 'payment_hash', value: selPayment.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }]);
reorderedPayment?.unshift([{ key: 'payment_hash', value: selPayment.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }]);
}
this.store.dispatch(openAlert({
payload: {
@ -295,7 +295,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
this.payments.sort = this.sort;
this.payments.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.payments.filterPredicate = (rowData: Payment, fltr: string) => {
const newRowData = ((rowData.created_at) ? this.datePipe.transform(new Date(rowData.created_at * 1000), 'dd/MMM/YYYY HH:mm').toLowerCase() : '') + ((rowData.bolt12) ? 'bolt12' : (rowData.bolt11) ? 'bolt11' : 'keysend') + JSON.stringify(rowData).toLowerCase();
const newRowData = ((rowData.created_at) ? this.datePipe.transform(new Date(rowData.created_at * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + ((rowData.bolt12) ? 'bolt12' : (rowData.bolt11) ? 'bolt11' : 'keysend') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.payments.paginator = this.paginator;
@ -305,7 +305,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
onDownloadCSV() {
if (this.payments.data && this.payments.data.length > 0) {
const paymentsDataCopy = JSON.parse(JSON.stringify(this.payments.data));
const flattenedPayments = paymentsDataCopy.reduce((acc, curr) => {
const flattenedPayments = paymentsDataCopy?.reduce((acc, curr) => {
if (curr.mpps) {
return acc.concat(curr.mpps);
} else {

@ -167,8 +167,8 @@ export class ECLHomeComponent implements OnInit, OnDestroy {
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.allChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels, 'balancedness')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels.filter((channel) => channel.toRemote > 0), 'toRemote')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels.filter((channel) => channel.toLocal > 0), 'toLocal')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels?.filter((channel) => channel.toRemote > 0), 'toRemote')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels?.filter((channel) => channel.toLocal > 0), 'toLocal')));
this.channels.forEach((channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + Math.ceil(channel.toRemote);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + Math.floor(channel.toLocal);

@ -112,7 +112,7 @@ export class ECLOnChainSendModalComponent implements OnInit, OnDestroy {
subscribe({
next: (data) => {
this.selAmountUnit = event.value;
self.transaction.amount = +self.decimalPipe.transform(data[currSelectedUnit], self.currencyUnitFormats[currSelectedUnit]).replace(/,/g, '');
self.transaction.amount = +self.decimalPipe.transform(data[currSelectedUnit], self.currencyUnitFormats[currSelectedUnit])?.replace(/,/g, '');
}, error: (err) => {
self.transaction.amount = null;
this.amountError = 'Conversion Error: ' + err;

@ -73,7 +73,7 @@ export class ECLOpenChannelComponent implements OnInit, OnDestroy {
}
private filterPeers(newlySelectedPeer: string): Peer[] {
return this.sortedPeers.filter((peer) => peer.alias.toLowerCase().indexOf(newlySelectedPeer ? newlySelectedPeer.toLowerCase() : '') === 0);
return this.sortedPeers?.filter((peer) => peer.alias.toLowerCase().indexOf(newlySelectedPeer ? newlySelectedPeer.toLowerCase() : '') === 0);
}
displayFn(peer: Peer): string {
@ -84,7 +84,7 @@ export class ECLOpenChannelComponent implements OnInit, OnDestroy {
this.channelConnectionError = '';
this.selectedPubkey = (this.selectedPeer.value && this.selectedPeer.value.nodeId) ? this.selectedPeer.value.nodeId : null;
if (typeof this.selectedPeer.value === 'string') {
const selPeer = this.peers.filter((peer) => peer.alias.length === this.selectedPeer.value.length && peer.alias.toLowerCase().indexOf(this.selectedPeer.value ? this.selectedPeer.value.toLowerCase() : '') === 0);
const selPeer = this.peers?.filter((peer) => peer.alias.length === this.selectedPeer.value.length && peer.alias.toLowerCase().indexOf(this.selectedPeer.value ? this.selectedPeer.value.toLowerCase() : '') === 0);
if (selPeer.length === 1 && selPeer[0].nodeId) {
this.selectedPubkey = selPeer[0].nodeId;
}

@ -115,7 +115,7 @@ export class ECLRoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < 12; i++) {
feeReport.push({ name: MONTHS[i].name, value: 0.0, extra: { totalEvents: 0 } });
}
this.filteredEventsBySelectedPeriod.map((event) => {
this.filteredEventsBySelectedPeriod?.map((event) => {
const monthNumber = new Date(event.timestamp).getMonth();
feeReport[monthNumber].value = feeReport[monthNumber].value + (event.amountIn - event.amountOut);
feeReport[monthNumber].extra.totalEvents = feeReport[monthNumber].extra.totalEvents + 1;
@ -126,7 +126,7 @@ export class ECLRoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
feeReport.push({ name: i + 1, value: 0.0, extra: { totalEvents: 0 } });
}
this.filteredEventsBySelectedPeriod.map((event) => {
this.filteredEventsBySelectedPeriod?.map((event) => {
const dateNumber = Math.floor((Math.floor(event.timestamp / 1000) - startDateInSeconds) / this.secondsInADay);
feeReport[dateNumber].value = feeReport[dateNumber].value + (event.amountIn - event.amountOut);
feeReport[dateNumber].extra.totalEvents = feeReport[dateNumber].extra.totalEvents + 1;
@ -147,7 +147,7 @@ export class ECLRoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < 12; i++) {
eventsReport.push({ name: MONTHS[i].name, value: 0, extra: { totalFees: 0.0 } });
}
this.filteredEventsBySelectedPeriod.map((event) => {
this.filteredEventsBySelectedPeriod?.map((event) => {
const monthNumber = new Date(event.timestamp).getMonth();
eventsReport[monthNumber].value = eventsReport[monthNumber].value + 1;
eventsReport[monthNumber].extra.totalFees = eventsReport[monthNumber].extra.totalFees + (event.amountIn - event.amountOut);
@ -158,7 +158,7 @@ export class ECLRoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
eventsReport.push({ name: i + 1, value: 0, extra: { totalFees: 0.0 } });
}
this.filteredEventsBySelectedPeriod.map((event) => {
this.filteredEventsBySelectedPeriod?.map((event) => {
const dateNumber = Math.floor((Math.floor(event.timestamp / 1000) - startDateInSeconds) / this.secondsInADay);
eventsReport[dateNumber].value = eventsReport[dateNumber].value + 1;
eventsReport[dateNumber].extra.totalFees = eventsReport[dateNumber].extra.totalFees + (event.amountIn - event.amountOut);

@ -97,22 +97,22 @@ export class ECLTransactionsReportComponent implements OnInit, OnDestroy {
const endDateInSeconds = Math.round(end.getTime() / 1000);
const transactionsReport = [];
this.transactionsReportSummary = { paymentsSelectedPeriod: 0, invoicesSelectedPeriod: 0, amountPaidSelectedPeriod: 0, amountReceivedSelectedPeriod: 0 };
const filteredPayments = this.payments.filter((payment) => Math.floor(payment.firstPartTimestamp / 1000) >= startDateInSeconds && Math.floor(payment.firstPartTimestamp / 1000) < endDateInSeconds);
const filteredInvoices = this.invoices.filter((invoice) => invoice.status === 'received' && invoice.timestamp >= startDateInSeconds && invoice.timestamp < endDateInSeconds);
const filteredPayments = this.payments?.filter((payment) => Math.floor(payment.firstPartTimestamp / 1000) >= startDateInSeconds && Math.floor(payment.firstPartTimestamp / 1000) < endDateInSeconds);
const filteredInvoices = this.invoices?.filter((invoice) => invoice.status === 'received' && invoice.timestamp >= startDateInSeconds && invoice.timestamp < endDateInSeconds);
this.transactionsReportSummary.paymentsSelectedPeriod = filteredPayments.length;
this.transactionsReportSummary.invoicesSelectedPeriod = filteredInvoices.length;
if (this.reportPeriod === SCROLL_RANGES[1]) {
for (let i = 0; i < 12; i++) {
transactionsReport.push({ name: MONTHS[i].name, date: new Date(start.getFullYear(), i, 1, 0, 0, 0, 0), series: [{ name: 'Paid', value: 0, extra: { total: 0 } }, { name: 'Received', value: 0, extra: { total: 0 } }] });
}
filteredPayments.map((payment) => {
filteredPayments?.map((payment) => {
const monthNumber = new Date(payment.firstPartTimestamp).getMonth();
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + payment.recipientAmount;
transactionsReport[monthNumber].series[0].value = transactionsReport[monthNumber].series[0].value + payment.recipientAmount;
transactionsReport[monthNumber].series[0].extra.total = transactionsReport[monthNumber].series[0].extra.total + 1;
return this.transactionsReportSummary;
});
filteredInvoices.map((invoice) => {
filteredInvoices?.map((invoice) => {
const monthNumber = new Date((invoice.timestamp) * 1000).getMonth();
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + invoice.amountSettled;
transactionsReport[monthNumber].series[1].value = transactionsReport[monthNumber].series[1].value + invoice.amountSettled;
@ -123,14 +123,14 @@ export class ECLTransactionsReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
transactionsReport.push({ name: (i + 1).toString(), date: new Date((((i) * this.secondsInADay) + startDateInSeconds) * 1000), series: [{ name: 'Paid', value: 0, extra: { total: 0 } }, { name: 'Received', value: 0, extra: { total: 0 } }] });
}
filteredPayments.map((payment) => {
filteredPayments?.map((payment) => {
const dateNumber = Math.floor((Math.floor(payment.firstPartTimestamp / 1000) - startDateInSeconds) / this.secondsInADay);
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + payment.recipientAmount;
transactionsReport[dateNumber].series[0].value = transactionsReport[dateNumber].series[0].value + payment.recipientAmount;
transactionsReport[dateNumber].series[0].extra.total = transactionsReport[dateNumber].series[0].extra.total + 1;
return this.transactionsReportSummary;
});
filteredInvoices.map((invoice) => {
filteredInvoices?.map((invoice) => {
const dateNumber = Math.floor((invoice.timestamp - startDateInSeconds) / this.secondsInADay);
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + invoice.amountSettled;
transactionsReport[dateNumber].series[1].value = transactionsReport[dateNumber].series[1].value + invoice.amountSettled;
@ -142,7 +142,7 @@ export class ECLTransactionsReportComponent implements OnInit, OnDestroy {
}
prepareTableData() {
return this.transactionsReportData.reduce((acc, curr) => {
return this.transactionsReportData?.reduce((acc, curr) => {
if (curr.series[0].extra.total > 0 || curr.series[1].extra.total > 0) {
return acc.concat({ date: curr.date, amount_paid: curr.series[0].value, num_payments: curr.series[0].extra.total, amount_received: curr.series[1].value, num_invoices: curr.series[1].extra.total });
}

@ -29,7 +29,7 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
@Input() eventsData = [];
@Input() eventsData: PaymentRelayed[] = [];
@Input() filterValue = '';
public displayedColumns: any[] = [];
public forwardingHistoryEvents: any;
@ -100,8 +100,8 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
onForwardingEventClick(selFEvent: PaymentRelayed, event: any) {
const reorderedFHEvent = [
[{ key: 'paymentHash', value: selFEvent.paymentHash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'timestamp', value: Math.round(selFEvent.timestamp / 1000), title: 'Date/Time', width: 50, type: DataTypeEnum.DATE_TIME },
{ key: 'fee', value: (selFEvent.amountIn - selFEvent.amountOut), title: 'Fee Earned (Sats)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'timestamp', value: Math.round((selFEvent.timestamp || 0) / 1000), title: 'Date/Time', width: 50, type: DataTypeEnum.DATE_TIME },
{ key: 'fee', value: ((selFEvent.amountIn || 0) - (selFEvent.amountOut || 0)), title: 'Fee Earned (Sats)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'amountIn', value: selFEvent.amountIn, title: 'Amount In (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'amountOut', value: selFEvent.amountOut, title: 'Amount Out (Sats)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'fromChannelAlias', value: selFEvent.fromChannelAlias, title: 'From Channel Alias', width: 50, type: DataTypeEnum.STRING },
@ -112,7 +112,7 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
[{ key: 'toChannelId', value: selFEvent.toChannelId, title: 'To Channel Id', width: 100, type: DataTypeEnum.STRING }]
];
if (selFEvent.type !== 'payment-relayed') {
reorderedFHEvent.unshift([{ key: 'type', value: this.commonService.camelCase(selFEvent.type), title: 'Relay Type', width: 100, type: DataTypeEnum.STRING }]);
reorderedFHEvent?.unshift([{ key: 'type', value: this.commonService.camelCase(selFEvent.type), title: 'Relay Type', width: 100, type: DataTypeEnum.STRING }]);
}
this.store.dispatch(openAlert({
payload: {
@ -138,7 +138,7 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
}
};
this.forwardingHistoryEvents.filterPredicate = (rowData: PaymentRelayed, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp), 'dd/MMM/YYYY HH:mm').toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.forwardingHistoryEvents.paginator = this.paginator;

@ -7,7 +7,7 @@ import { GetInfo, Channel, Fees, Peer, LightningBalance, OnChainBalance, Channel
export const updateECLAPICallStatus = createAction(ECLActions.UPDATE_API_CALL_STATUS_ECL, props<{ payload: ApiCallStatusPayload }>());
export const resetECLStore = createAction(ECLActions.RESET_ECL_STORE, props<{ payload: SelNodeChild }>());
export const resetECLStore = createAction(ECLActions.RESET_ECL_STORE, props<{ payload: SelNodeChild | null }>());
export const setChildNodeSettingsECL = createAction(ECLActions.SET_CHILD_NODE_SETTINGS_ECL, props<{ payload: SelNodeChild }>());

@ -86,7 +86,7 @@ export class ECLEffects implements OnDestroy {
break;
case ECLWSEventTypeEnum.CHANNEL_STATE_CHANGED:
if ((<ChannelStateUpdate>newMessage).currentState === 'NORMAL' || (<ChannelStateUpdate>newMessage).currentState === 'CLOSED') {
this.rawChannelsList = this.rawChannelsList.map((channel) => {
this.rawChannelsList = this.rawChannelsList?.map((channel) => {
if (channel.channelId === (<ChannelStateUpdate>newMessage).channelId && channel.nodeId === (<ChannelStateUpdate>newMessage).remoteNodeId) {
channel.state = (<ChannelStateUpdate>newMessage).currentState;
}
@ -663,12 +663,12 @@ export class ECLEffects implements OnDestroy {
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, ' ');
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, ' ');
channel.state = channel.state?.replace(/_/g, ' ');
inactiveChannels.push(channel);
channelStatus.inactive.channels = channelStatus.inactive.channels + 1;
channelStatus.inactive.capacity = channelStatus.inactive.capacity + channel.toLocal;
@ -713,9 +713,9 @@ export class ECLEffects implements OnDestroy {
this.store.dispatch(setNodeData({ payload: node_data }));
let newRoute = this.location.path();
if (newRoute.includes('/lnd/')) {
newRoute = newRoute.replace('/lnd/', '/ecl/');
newRoute = newRoute?.replace('/lnd/', '/ecl/');
} else if (newRoute.includes('/cln/')) {
newRoute = newRoute.replace('/cln/', '/ecl/');
newRoute = newRoute?.replace('/cln/', '/ecl/');
}
if (newRoute.includes('/login') || newRoute.includes('/error') || newRoute === '' || landingPage === 'HOME' || newRoute.includes('?access-key=')) {
newRoute = '/ecl/home';

@ -7,7 +7,7 @@ import { Channel, PaymentReceived, PaymentRelayed } from '../../shared/models/ec
export const ECLReducer = createReducer(initECLState,
on(updateECLAPICallStatus, (state, { payload }) => {
const updatedApisCallStatus = JSON.parse(JSON.stringify(state.apisCallStatus));
updatedApisCallStatus[payload.action] = {
updatedApisCallStatus[payload.action || 0] = {
status: payload.status,
statusCode: payload.statusCode,
message: payload.message,
@ -88,11 +88,11 @@ export const ECLReducer = createReducer(initECLState,
on(setPayments, (state, { payload }) => {
if (payload && payload.sent) {
const storedChannels = [...state.activeChannels, ...state.pendingChannels, ...state.inactiveChannels];
payload.sent.map((sentPayment) => {
payload.sent?.map((sentPayment) => {
const peerFound = state.peers.find((peer) => peer.nodeId === sentPayment.recipientNodeId);
sentPayment.recipientNodeAlias = peerFound ? peerFound.alias : sentPayment.recipientNodeId;
if (sentPayment.parts) {
sentPayment.parts.map((part) => {
sentPayment.parts?.map((part) => {
const channelFound = storedChannels.find((channel) => channel.channelId === part.toChannelId);
part.toChannelAlias = channelFound ? channelFound.alias : part.toChannelId;
return sentPayment.parts;
@ -118,7 +118,7 @@ export const ECLReducer = createReducer(initECLState,
})),
on(addInvoice, (state, { payload }) => {
const newInvoices = state.invoices;
newInvoices.unshift(payload);
newInvoices?.unshift(payload);
return {
...state,
invoices: newInvoices
@ -130,12 +130,12 @@ export const ECLReducer = createReducer(initECLState,
})),
on(updateInvoice, (state, { payload }) => {
let modifiedInvoices = state.invoices;
modifiedInvoices = modifiedInvoices.map((invoice) => {
modifiedInvoices = modifiedInvoices?.map((invoice) => {
if (invoice.paymentHash === payload.paymentHash) {
if (payload.hasOwnProperty('type')) {
const updatedInvoice = JSON.parse(JSON.stringify(invoice));
updatedInvoice.amountSettled = ((<PaymentReceived>payload).parts && (<PaymentReceived>payload).parts.length && (<PaymentReceived>payload).parts.length > 0 && (<PaymentReceived>payload).parts[0].amount) ? (<PaymentReceived>payload).parts[0].amount / 1000 : 0;
updatedInvoice.receivedAt = ((<PaymentReceived>payload).parts && (<PaymentReceived>payload).parts.length && (<PaymentReceived>payload).parts.length > 0 && (<PaymentReceived>payload).parts[0].timestamp) ? Math.round((<PaymentReceived>payload).parts[0].timestamp / 1000) : 0;
updatedInvoice.amountSettled = ((<PaymentReceived>payload).parts && (<PaymentReceived>payload).parts.length && (<PaymentReceived>payload).parts.length > 0 && (<PaymentReceived>payload).parts[0].amount) ? ((<PaymentReceived>payload).parts[0].amount || 0) / 1000 : 0;
updatedInvoice.receivedAt = ((<PaymentReceived>payload).parts && (<PaymentReceived>payload).parts.length && (<PaymentReceived>payload).parts.length > 0 && (<PaymentReceived>payload).parts[0].timestamp) ? Math.round(((<PaymentReceived>payload).parts[0].timestamp || 0) / 1000) : 0;
updatedInvoice.status = 'received';
return updatedInvoice;
} else {
@ -151,9 +151,9 @@ export const ECLReducer = createReducer(initECLState,
}),
on(updateChannelState, (state, { payload }) => {
let modifiedPendingChannels = state.pendingChannels;
modifiedPendingChannels = modifiedPendingChannels.map((pendingChannel) => {
modifiedPendingChannels = modifiedPendingChannels?.map((pendingChannel) => {
if (pendingChannel.channelId === payload.channelId && pendingChannel.nodeId === payload.remoteNodeId) {
payload.currentState = payload.currentState.replace(/_/g, ' ');
payload.currentState = payload.currentState?.replace(/_/g, ' ');
pendingChannel.state = payload.currentState;
}
return pendingChannel;
@ -166,17 +166,19 @@ export const ECLReducer = createReducer(initECLState,
on(updateRelayedPayment, (state, { payload }) => {
const modifiedPayments = state.payments;
const updatedPayload = mapAliases(payload, [...state.activeChannels, ...state.pendingChannels, ...state.inactiveChannels]);
updatedPayload.amountIn = Math.round(payload.amountIn / 1000);
updatedPayload.amountOut = Math.round(payload.amountOut / 1000);
modifiedPayments.relayed.unshift(updatedPayload);
const feeSats = payload.amountIn - payload.amountOut;
updatedPayload.amountIn = Math.round((payload.amountIn || 0) / 1000);
updatedPayload.amountOut = Math.round((payload.amountOut || 0) / 1000);
modifiedPayments.relayed?.unshift(updatedPayload);
const feeSats = (payload.amountIn ||0) - (payload.amountOut || 0);
const modifiedLightningBalance = { localBalance: (state.lightningBalance.localBalance + feeSats), remoteBalance: (state.lightningBalance.remoteBalance - feeSats) };
const modifiedChannelStatus = state.channelsStatus;
modifiedChannelStatus.active.capacity = state.channelsStatus.active.capacity + feeSats;
if (modifiedChannelStatus.active) {
modifiedChannelStatus.active.capacity = (state.channelsStatus?.active?.capacity || 0) + feeSats;
}
const modifiedFees = {
daily_fee: (state.fees.daily_fee + feeSats), daily_txs: (state.fees.daily_txs + 1),
weekly_fee: (state.fees.weekly_fee + feeSats), weekly_txs: (state.fees.weekly_txs + 1),
monthly_fee: (state.fees.monthly_fee + feeSats), monthly_txs: (state.fees.monthly_txs + 1)
daily_fee: ((state.fees.daily_fee || 0) + feeSats), daily_txs: ((state.fees.daily_txs || 0) + 1),
weekly_fee: ((state.fees.weekly_fee || 0) + feeSats), weekly_txs: ((state.fees.weekly_txs || 0) + 1),
monthly_fee: ((state.fees.monthly_fee || 0) + feeSats), monthly_txs: ((state.fees.monthly_txs || 0) + 1)
};
const modifiedActiveChannels = state.activeChannels;
let foundFrom = false;
@ -184,16 +186,16 @@ export const ECLReducer = createReducer(initECLState,
for (const channel of modifiedActiveChannels) {
if (channel.channelId === payload.fromChannelId) {
foundFrom = true;
const channelTotal = channel.toLocal + channel.toRemote;
channel.toLocal = channel.toLocal + updatedPayload.amountIn;
channel.toRemote = channel.toRemote - updatedPayload.amountIn;
const channelTotal = (channel.toLocal || 0) + (channel.toRemote || 0);
channel.toLocal = (channel.toLocal || 0) + updatedPayload.amountIn;
channel.toRemote = (channel.toRemote || 0) - updatedPayload.amountIn;
channel.balancedness = (channelTotal === 0) ? 1 : +(1 - Math.abs((channel.toLocal - channel.toRemote) / channelTotal)).toFixed(3);
}
if (channel.channelId === payload.toChannelId) {
foundTo = true;
const channelTotal = channel.toLocal + channel.toRemote;
channel.toLocal = channel.toLocal - updatedPayload.amountOut;
channel.toRemote = channel.toRemote + updatedPayload.amountOut;
const channelTotal = (channel.toLocal || 0) + (channel.toRemote || 0);
channel.toLocal = (channel.toLocal || 0) - updatedPayload.amountOut;
channel.toRemote = (channel.toRemote || 0) + updatedPayload.amountOut;
channel.balancedness = (channelTotal === 0) ? 1 : +(1 - Math.abs((channel.toLocal - channel.toRemote) / channelTotal)).toFixed(3);
}
if (foundTo && foundFrom) {
@ -215,14 +217,14 @@ const mapAliases = (rlEvent: PaymentRelayed, storedChannels: Channel[]) => {
if (rlEvent.type === 'payment-relayed') {
if (storedChannels && storedChannels.length > 0) {
for (let idx = 0; idx < storedChannels.length; idx++) {
if (storedChannels[idx].channelId.toString() === rlEvent.fromChannelId) {
if (storedChannels[idx].channelId?.toString() === rlEvent.fromChannelId) {
rlEvent.fromChannelAlias = storedChannels[idx].alias ? storedChannels[idx].alias : rlEvent.fromChannelId;
rlEvent.fromShortChannelId = storedChannels[idx].shortChannelId ? storedChannels[idx].shortChannelId : '';
if (rlEvent.toChannelAlias) {
return rlEvent;
}
}
if (storedChannels[idx].channelId.toString() === rlEvent.toChannelId) {
if (storedChannels[idx].channelId?.toString() === rlEvent.toChannelId) {
rlEvent.toChannelAlias = storedChannels[idx].alias ? storedChannels[idx].alias : rlEvent.toChannelId;
rlEvent.toShortChannelId = storedChannels[idx].shortChannelId ? storedChannels[idx].shortChannelId : '';
if (rlEvent.fromChannelAlias) {
@ -231,70 +233,70 @@ const mapAliases = (rlEvent: PaymentRelayed, storedChannels: Channel[]) => {
}
if (idx === storedChannels.length - 1) {
if (!rlEvent.fromChannelAlias) {
rlEvent.fromChannelAlias = rlEvent.fromChannelId.substring(0, 17) + '...';
rlEvent.fromChannelAlias = rlEvent.fromChannelId?.substring(0, 17) + '...';
rlEvent.fromShortChannelId = '';
}
if (!rlEvent.toChannelAlias) {
rlEvent.toChannelAlias = rlEvent.toChannelId.substring(0, 17) + '...';
rlEvent.toChannelAlias = rlEvent.toChannelId?.substring(0, 17) + '...';
rlEvent.toShortChannelId = '';
}
}
}
} else {
rlEvent.fromChannelAlias = rlEvent.fromChannelId.substring(0, 17) + '...';
rlEvent.fromChannelAlias = rlEvent.fromChannelId?.substring(0, 17) + '...';
rlEvent.fromShortChannelId = '';
rlEvent.toChannelAlias = rlEvent.toChannelId.substring(0, 17) + '...';
rlEvent.toChannelAlias = rlEvent.toChannelId?.substring(0, 17) + '...';
rlEvent.toShortChannelId = '';
}
} else if (rlEvent.type = 'trampoline-payment-relayed') {
if (storedChannels && storedChannels.length > 0) {
for (let idx = 0; idx < storedChannels.length; idx++) {
rlEvent.incoming.forEach((incomingEvent) => {
if (storedChannels[idx].channelId.toString() === incomingEvent.channelId) {
rlEvent.incoming?.forEach((incomingEvent) => {
if (storedChannels[idx].channelId?.toString() === incomingEvent.channelId) {
incomingEvent.channelAlias = storedChannels[idx].alias ? storedChannels[idx].alias : incomingEvent.channelId;
incomingEvent.shortChannelId = storedChannels[idx].shortChannelId ? storedChannels[idx].shortChannelId : '';
}
});
rlEvent.outgoing.forEach((outgoingEvent) => {
if (storedChannels[idx].channelId.toString() === outgoingEvent.channelId) {
rlEvent.outgoing?.forEach((outgoingEvent) => {
if (storedChannels[idx].channelId?.toString() === outgoingEvent.channelId) {
outgoingEvent.channelAlias = storedChannels[idx].alias ? storedChannels[idx].alias : outgoingEvent.channelId;
outgoingEvent.shortChannelId = storedChannels[idx].shortChannelId ? storedChannels[idx].shortChannelId : '';
}
});
if (idx === storedChannels.length - 1) {
if (!rlEvent.incoming[0].channelAlias) {
rlEvent.incoming.forEach((incomingEvent) => {
incomingEvent.channelAlias = incomingEvent.channelId.substring(0, 17) + '...';
if (rlEvent.incoming && rlEvent.incoming.length && rlEvent.incoming.length > 0 && !rlEvent.incoming[0].channelAlias) {
rlEvent.incoming?.forEach((incomingEvent) => {
incomingEvent.channelAlias = incomingEvent.channelId?.substring(0, 17) + '...';
incomingEvent.shortChannelId = '';
});
}
if (!rlEvent.outgoing[0].channelAlias) {
rlEvent.outgoing.forEach((outgoingEvent) => {
outgoingEvent.channelAlias = outgoingEvent.channelId.substring(0, 17) + '...';
if (rlEvent.outgoing && rlEvent.outgoing.length && rlEvent.outgoing.length > 0 && !rlEvent.outgoing[0].channelAlias) {
rlEvent.outgoing?.forEach((outgoingEvent) => {
outgoingEvent.channelAlias = outgoingEvent.channelId?.substring(0, 17) + '...';
outgoingEvent.shortChannelId = '';
});
}
}
}
} else {
rlEvent.incoming.forEach((incomingEvent) => {
incomingEvent.channelAlias = incomingEvent.channelId.substring(0, 17) + '...';
rlEvent.incoming?.forEach((incomingEvent) => {
incomingEvent.channelAlias = incomingEvent.channelId?.substring(0, 17) + '...';
incomingEvent.shortChannelId = '';
});
rlEvent.outgoing.forEach((outgoingEvent) => {
outgoingEvent.channelAlias = outgoingEvent.channelId.substring(0, 17) + '...';
rlEvent.outgoing?.forEach((outgoingEvent) => {
outgoingEvent.channelAlias = outgoingEvent.channelId?.substring(0, 17) + '...';
outgoingEvent.shortChannelId = '';
});
}
rlEvent.amountIn = rlEvent.incoming.reduce((acc, curr) => acc + curr.amount, 0);
rlEvent.fromChannelId = rlEvent.incoming[0].channelId;
rlEvent.fromChannelAlias = rlEvent.incoming[0].channelAlias;
rlEvent.fromShortChannelId = rlEvent.incoming[0].shortChannelId;
rlEvent.amountIn = rlEvent.incoming?.reduce((acc, curr) => acc + curr.amount, 0);
rlEvent.fromChannelId = rlEvent.incoming && rlEvent.incoming.length ? rlEvent.incoming[0].channelId : '';
rlEvent.fromChannelAlias = rlEvent.incoming && rlEvent.incoming.length ? rlEvent.incoming[0].channelAlias : '';
rlEvent.fromShortChannelId = rlEvent.incoming && rlEvent.incoming.length ? rlEvent.incoming[0].shortChannelId : '';
rlEvent.amountOut = rlEvent.outgoing.reduce((acc, curr) => acc + curr.amount, 0);
rlEvent.toChannelId = rlEvent.outgoing[0].channelId;
rlEvent.toChannelAlias = rlEvent.outgoing[0].channelAlias;
rlEvent.toShortChannelId = rlEvent.outgoing[0].shortChannelId;
rlEvent.amountOut = rlEvent.outgoing?.reduce((acc, curr) => acc + curr.amount, 0);
rlEvent.toChannelId = rlEvent.outgoing && rlEvent.outgoing.length ? rlEvent.outgoing[0].channelId : '';
rlEvent.toChannelAlias = rlEvent.outgoing && rlEvent.outgoing.length ? rlEvent.outgoing[0].channelAlias : '';
rlEvent.toShortChannelId = rlEvent.outgoing && rlEvent.outgoing.length ? rlEvent.outgoing[0].shortChannelId : '';
}
return rlEvent;
};

@ -5,7 +5,7 @@ import { APICallStatusEnum, UserPersonaEnum } from '../../shared/services/consts
export interface ECLState {
apisCallStatus: ApiCallsListECL;
nodeSettings: SelNodeChild;
nodeSettings: SelNodeChild | null;
information: GetInfo;
fees: Fees;
activeChannels: Channel[];

@ -162,7 +162,7 @@ export class ECLLightningInvoicesComponent implements OnInit, AfterViewInit, OnD
}
updateInvoicesData(newInvoice: Invoice) {
this.invoiceJSONArr = this.invoiceJSONArr.map((invoice) => ((invoice.paymentHash === newInvoice.paymentHash) ? newInvoice : invoice));
this.invoiceJSONArr = this.invoiceJSONArr?.map((invoice) => ((invoice.paymentHash === newInvoice.paymentHash) ? newInvoice : invoice));
}
loadInvoicesTable(invs: Invoice[]) {

@ -379,7 +379,7 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
onDownloadCSV() {
if (this.payments.data && this.payments.data.length > 0) {
const paymentsDataCopy: PaymentSent[] = JSON.parse(JSON.stringify(this.payments.data));
const paymentRequests = paymentsDataCopy.reduce((paymentReqs, payment) => {
const paymentRequests = paymentsDataCopy?.reduce((paymentReqs, payment) => {
if (payment.paymentHash && payment.paymentHash.trim() !== '') {
paymentReqs = (paymentReqs === '') ? payment.paymentHash : paymentReqs + ',' + payment.paymentHash;
}
@ -393,7 +393,7 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
paymentsDataCopy[idx].description = decodedPayment[0].paymentRequest.description;
}
});
const flattenedPayments = paymentsDataCopy.reduce((acc, curr) => acc.concat(curr), []);
const flattenedPayments = paymentsDataCopy?.reduce((acc, curr) => acc.concat(curr), []);
this.commonService.downloadFile(flattenedPayments, 'Payments');
});
}

@ -207,10 +207,10 @@ export class HomeComponent implements OnInit, OnDestroy {
this.channelsStatus.inactive = channelsSelector.channelsSummary.inactive;
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.allChannels = channelsSelector.channels.filter((channel) => channel.active === true);
this.allChannels = channelsSelector.channels?.filter((channel) => channel.active === true);
this.allChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels, 'balancedness')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels.filter((channel) => channel.remote_balance > 0), 'remote_balance')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels.filter((channel) => channel.local_balance > 0), 'local_balance')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels?.filter((channel) => channel.remote_balance > 0), 'remote_balance')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels?.filter((channel) => channel.local_balance > 0), 'local_balance')));
this.allChannels.forEach((channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + +channel.remote_balance;
this.totalOutboundLiquidity = this.totalOutboundLiquidity + +channel.local_balance;

@ -167,7 +167,7 @@ export class OnChainSendModalComponent implements OnInit, OnDestroy {
subscribe({
next: (data) => {
this.selAmountUnit = CurrencyUnitEnum.SATS;
postTransaction.amount = +this.decimalPipe.transform(data[this.amountUnits[0]], this.currencyUnitFormats[this.amountUnits[0]]).replace(/,/g, '');
postTransaction.amount = +this.decimalPipe.transform(data[this.amountUnits[0]], this.currencyUnitFormats[this.amountUnits[0]])?.replace(/,/g, '');
this.store.dispatch(setChannelTransaction({ payload: postTransaction }));
}, error: (err) => {
this.transactionAmount = null;
@ -245,7 +245,7 @@ export class OnChainSendModalComponent implements OnInit, OnDestroy {
subscribe({
next: (data) => {
this.selAmountUnit = event.value;
self.transactionAmount = +self.decimalPipe.transform(data[currSelectedUnit], self.currencyUnitFormats[currSelectedUnit]).replace(/,/g, '');
self.transactionAmount = +self.decimalPipe.transform(data[currSelectedUnit], self.currencyUnitFormats[currSelectedUnit])?.replace(/,/g, '');
}, error: (err) => {
self.transactionAmount = null;
this.amountError = 'Conversion Error: ' + err;

@ -34,7 +34,7 @@ export class UTXOTablesComponent implements OnInit, OnDestroy {
subscribe((utxosSelector: { utxos: UTXO[], apiCallStatus: ApiCallStatusPayload }) => {
if (utxosSelector.utxos && utxosSelector.utxos.length > 0) {
this.numUtxos = utxosSelector.utxos.length;
this.numDustUtxos = utxosSelector.utxos.filter((utxo) => +utxo.amount_sat < 1000).length;
this.numDustUtxos = utxosSelector.utxos?.filter((utxo) => +utxo.amount_sat < 1000).length;
}
this.logger.info(utxosSelector);
});

@ -77,7 +77,7 @@ export class OnChainUTXOsComponent implements OnInit, OnChanges, OnDestroy {
this.errorMessage = !this.apiCallStatus.message ? '' : (typeof (this.apiCallStatus.message) === 'object') ? JSON.stringify(this.apiCallStatus.message) : this.apiCallStatus.message;
}
if (utxosSelector.utxos && utxosSelector.utxos.length > 0) {
this.dustUtxos = utxosSelector.utxos.filter((utxo) => +utxo.amount_sat < 1000);
this.dustUtxos = utxosSelector.utxos?.filter((utxo) => +utxo.amount_sat < 1000);
this.utxos = utxosSelector.utxos;
this.loadUTXOsTable((this.isDustUTXO) ? this.dustUtxos : this.utxos);
}

@ -62,7 +62,7 @@ export class ChannelRebalanceComponent implements OnInit, OnDestroy {
let x = '';
let y = '';
this.selChannel = this.data.message.selChannel;
this.activeChannels = this.data.message.channels.filter((channel) => channel.active && channel.chan_id !== this.selChannel.chan_id && channel.remote_balance > 0);
this.activeChannels = this.data.message.channels?.filter((channel) => channel.active && channel.chan_id !== this.selChannel.chan_id && channel.remote_balance > 0);
this.activeChannels = this.activeChannels.sort((c1: Channel, c2: Channel) => {
x = c1.remote_alias ? c1.remote_alias.toLowerCase() : c1.chan_id ? c1.chan_id.toLowerCase() : '';
y = c2.remote_alias ? c2.remote_alias.toLowerCase() : c1.chan_id.toLowerCase();
@ -231,13 +231,13 @@ export class ChannelRebalanceComponent implements OnInit, OnDestroy {
}
filterActiveChannels() {
return this.activeChannels.filter((channel) => channel.remote_balance >= this.inputFormGroup.controls.rebalanceAmount.value &&
return this.activeChannels?.filter((channel) => channel.remote_balance >= this.inputFormGroup.controls.rebalanceAmount.value &&
channel.chan_id !== this.selChannel.chan_id && ((channel.remote_alias.toLowerCase().indexOf(this.inputFormGroup.controls.selRebalancePeer.value ? this.inputFormGroup.controls.selRebalancePeer.value.toLowerCase() : '') === 0) || (channel.chan_id.toLowerCase().indexOf(this.inputFormGroup.controls.selRebalancePeer.value ? this.inputFormGroup.controls.selRebalancePeer.value.toLowerCase() : '') === 0)));
}
onSelectedPeerChanged() {
if (this.inputFormGroup.controls.selRebalancePeer.value && this.inputFormGroup.controls.selRebalancePeer.value.length > 0 && typeof this.inputFormGroup.controls.selRebalancePeer.value === 'string') {
const foundChannels = this.activeChannels.filter((channel) => channel.remote_alias.length === this.inputFormGroup.controls.selRebalancePeer.value.length && channel.remote_alias.toLowerCase().indexOf(this.inputFormGroup.controls.selRebalancePeer.value ? this.inputFormGroup.controls.selRebalancePeer.value.toLowerCase() : '') === 0);
const foundChannels = this.activeChannels?.filter((channel) => channel.remote_alias.length === this.inputFormGroup.controls.selRebalancePeer.value.length && channel.remote_alias.toLowerCase().indexOf(this.inputFormGroup.controls.selRebalancePeer.value ? this.inputFormGroup.controls.selRebalancePeer.value.toLowerCase() : '') === 0);
if (foundChannels && foundChannels.length > 0) {
this.inputFormGroup.controls.selRebalancePeer.setValue(foundChannels[0]);
this.inputFormGroup.controls.selRebalancePeer.setErrors(null);

@ -69,7 +69,7 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
if (this.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessage = !this.apiCallStatus.message ? '' : (typeof (this.apiCallStatus.message) === 'object') ? JSON.stringify(this.apiCallStatus.message) : this.apiCallStatus.message;
}
this.channelsJSONArr = channelsSelector.channels.filter((channel) => channel.pending_htlcs && channel.pending_htlcs.length > 0) || [];
this.channelsJSONArr = channelsSelector.channels?.filter((channel) => channel.pending_htlcs && channel.pending_htlcs.length > 0) || [];
this.loadHTLCsTable(this.channelsJSONArr);
this.logger.info(channelsSelector);
});
@ -142,7 +142,7 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
this.channels.paginator = this.paginator;
this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = (channel.remote_alias ? channel.remote_alias.toLowerCase() : '') +
channel.pending_htlcs.map((htlc) => JSON.stringify(htlc) + (htlc.incoming ? 'yes' : 'no'));
channel.pending_htlcs?.map((htlc) => JSON.stringify(htlc) + (htlc.incoming ? 'yes' : 'no'));
return newChannel.includes(fltr);
};
this.applyFilter();
@ -156,7 +156,7 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
flattenHTLCs() {
const channelsDataCopy = JSON.parse(JSON.stringify(this.channels.data));
const flattenedHTLCs = channelsDataCopy.reduce((acc, curr) => {
const flattenedHTLCs = channelsDataCopy?.reduce((acc, curr) => {
if (curr.pending_htlcs) {
return acc.concat(curr.pending_htlcs);
} else {

@ -45,7 +45,7 @@ export class ChannelsTablesComponent implements OnInit, OnDestroy {
this.store.select(channels).pipe(takeUntil(this.unSubs[2])).
subscribe((channelsSelector: { channels: Channel[], channelsSummary: ChannelsSummary, lightningBalance: LightningBalance, apiCallStatus: ApiCallStatusPayload }) => {
this.numOpenChannels = (channelsSelector.channels && channelsSelector.channels.length) ? channelsSelector.channels.length : 0;
this.numActiveHTLCs = channelsSelector.channels.reduce((totalHTLCs, channel) => totalHTLCs + (channel.pending_htlcs && channel.pending_htlcs.length > 0 ? channel.pending_htlcs.length : 0), 0);
this.numActiveHTLCs = channelsSelector.channels?.reduce((totalHTLCs, channel) => totalHTLCs + (channel.pending_htlcs && channel.pending_htlcs.length > 0 ? channel.pending_htlcs.length : 0), 0);
this.logger.info(channelsSelector);
});
this.store.select(pendingChannels).pipe(takeUntil(this.unSubs[3])).

@ -77,7 +77,7 @@ export class OpenChannelComponent implements OnInit, OnDestroy {
}
private filterPeers(newlySelectedPeer: string): Peer[] {
return this.sortedPeers.filter((peer) => peer.alias.toLowerCase().indexOf(newlySelectedPeer ? newlySelectedPeer.toLowerCase() : '') === 0);
return this.sortedPeers?.filter((peer) => peer.alias.toLowerCase().indexOf(newlySelectedPeer ? newlySelectedPeer.toLowerCase() : '') === 0);
}
displayFn(peer: Peer): string {
@ -88,7 +88,7 @@ export class OpenChannelComponent implements OnInit, OnDestroy {
this.channelConnectionError = '';
this.selectedPubkey = (this.selectedPeer.value && this.selectedPeer.value.pub_key) ? this.selectedPeer.value.pub_key : null;
if (typeof this.selectedPeer.value === 'string') {
const selPeer = this.peers.filter((peer) => peer.alias.length === this.selectedPeer.value.length && peer.alias.toLowerCase().indexOf(this.selectedPeer.value ? this.selectedPeer.value.toLowerCase() : '') === 0);
const selPeer = this.peers?.filter((peer) => peer.alias.length === this.selectedPeer.value.length && peer.alias.toLowerCase().indexOf(this.selectedPeer.value ? this.selectedPeer.value.toLowerCase() : '') === 0);
if (selPeer.length === 1 && selPeer[0].pub_key) {
this.selectedPubkey = selPeer[0].pub_key;
}

@ -118,7 +118,7 @@ export class RoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < 12; i++) {
feeReport.push({ name: MONTHS[i].name, value: 0.0, extra: { totalEvents: 0 } });
}
this.events.forwarding_events.map((event) => {
this.events.forwarding_events?.map((event) => {
const monthNumber = new Date((+event.timestamp) * 1000).getMonth();
feeReport[monthNumber].value = feeReport[monthNumber].value + (+event.fee_msat / 1000);
feeReport[monthNumber].extra.totalEvents = feeReport[monthNumber].extra.totalEvents + 1;
@ -129,7 +129,7 @@ export class RoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
feeReport.push({ name: i + 1, value: 0.0, extra: { totalEvents: 0 } });
}
this.events.forwarding_events.map((event) => {
this.events.forwarding_events?.map((event) => {
const dateNumber = Math.floor((+event.timestamp - startDateInSeconds) / this.secondsInADay);
feeReport[dateNumber].value = feeReport[dateNumber].value + (+event.fee_msat / 1000);
feeReport[dateNumber].extra.totalEvents = feeReport[dateNumber].extra.totalEvents + 1;
@ -148,7 +148,7 @@ export class RoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < 12; i++) {
eventsReport.push({ name: MONTHS[i].name, value: 0, extra: { totalFees: 0.0 } });
}
this.events.forwarding_events.map((event) => {
this.events.forwarding_events?.map((event) => {
const monthNumber = new Date((+event.timestamp) * 1000).getMonth();
eventsReport[monthNumber].value = eventsReport[monthNumber].value + 1;
eventsReport[monthNumber].extra.totalFees = eventsReport[monthNumber].extra.totalFees + (+event.fee_msat / 1000);
@ -159,7 +159,7 @@ export class RoutingReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
eventsReport.push({ name: i + 1, value: 0, extra: { totalFees: 0.0 } });
}
this.events.forwarding_events.map((event) => {
this.events.forwarding_events?.map((event) => {
const dateNumber = Math.floor((+event.timestamp - startDateInSeconds) / this.secondsInADay);
eventsReport[dateNumber].value = eventsReport[dateNumber].value + 1;
eventsReport[dateNumber].extra.totalFees = eventsReport[dateNumber].extra.totalFees + (+event.fee_msat / 1000);

@ -110,22 +110,22 @@ export class TransactionsReportComponent implements OnInit, OnDestroy {
const transactionsReport = [];
this.transactionsNonZeroReportData = [];
this.transactionsReportSummary = { paymentsSelectedPeriod: 0, invoicesSelectedPeriod: 0, amountPaidSelectedPeriod: 0, amountReceivedSelectedPeriod: 0 };
const filteredPayments = this.payments.filter((payment) => payment.status === 'SUCCEEDED' && payment.creation_date >= startDateInSeconds && payment.creation_date < endDateInSeconds);
const filteredInvoices = this.invoices.filter((invoice) => invoice.settled && +invoice.creation_date >= startDateInSeconds && +invoice.creation_date < endDateInSeconds);
const filteredPayments = this.payments?.filter((payment) => payment.status === 'SUCCEEDED' && payment.creation_date >= startDateInSeconds && payment.creation_date < endDateInSeconds);
const filteredInvoices = this.invoices?.filter((invoice) => invoice.settled && +invoice.creation_date >= startDateInSeconds && +invoice.creation_date < endDateInSeconds);
this.transactionsReportSummary.paymentsSelectedPeriod = filteredPayments.length;
this.transactionsReportSummary.invoicesSelectedPeriod = filteredInvoices.length;
if (this.reportPeriod === SCROLL_RANGES[1]) {
for (let i = 0; i < 12; i++) {
transactionsReport.push({ name: MONTHS[i].name, date: new Date(start.getFullYear(), i, 1, 0, 0, 0, 0), series: [{ name: 'Paid', value: 0, extra: { total: 0 } }, { name: 'Received', value: 0, extra: { total: 0 } }] });
}
filteredPayments.map((payment) => {
filteredPayments?.map((payment) => {
const monthNumber = new Date((+payment.creation_date) * 1000).getMonth();
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + (+payment.value_msat) + (+payment.fee_msat);
transactionsReport[monthNumber].series[0].value = transactionsReport[monthNumber].series[0].value + ((+payment.value_msat + +payment.fee_msat) / 1000);
transactionsReport[monthNumber].series[0].extra.total = transactionsReport[monthNumber].series[0].extra.total + 1;
return this.transactionsReportSummary;
});
filteredInvoices.map((invoice) => {
filteredInvoices?.map((invoice) => {
const monthNumber = new Date((+invoice.creation_date) * 1000).getMonth();
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + (+invoice.amt_paid_msat);
transactionsReport[monthNumber].series[1].value = transactionsReport[monthNumber].series[1].value + (+invoice.amt_paid_msat / 1000);
@ -136,14 +136,14 @@ export class TransactionsReportComponent implements OnInit, OnDestroy {
for (let i = 0; i < this.getMonthDays(start.getMonth(), start.getFullYear()); i++) {
transactionsReport.push({ name: (i + 1).toString(), date: new Date((((i) * this.secondsInADay) + startDateInSeconds) * 1000), series: [{ name: 'Paid', value: 0, extra: { total: 0 } }, { name: 'Received', value: 0, extra: { total: 0 } }] });
}
filteredPayments.map((payment) => {
filteredPayments?.map((payment) => {
const dateNumber = Math.floor((+payment.creation_date - startDateInSeconds) / this.secondsInADay);
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + (+payment.value_msat) + (+payment.fee_msat);
transactionsReport[dateNumber].series[0].value = transactionsReport[dateNumber].series[0].value + ((+payment.value_msat + +payment.fee_msat) / 1000);
transactionsReport[dateNumber].series[0].extra.total = transactionsReport[dateNumber].series[0].extra.total + 1;
return this.transactionsReportSummary;
});
filteredInvoices.map((invoice) => {
filteredInvoices?.map((invoice) => {
const dateNumber = Math.floor((+invoice.creation_date - startDateInSeconds) / this.secondsInADay);
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + (+invoice.amt_paid_msat);
transactionsReport[dateNumber].series[1].value = transactionsReport[dateNumber].series[1].value + (+invoice.amt_paid_msat / 1000);
@ -155,7 +155,7 @@ export class TransactionsReportComponent implements OnInit, OnDestroy {
}
prepareTableData() {
return this.transactionsReportData.reduce((acc, curr) => {
return this.transactionsReportData?.reduce((acc, curr) => {
if (curr.series[0].extra.total > 0 || curr.series[1].extra.total > 0) {
return acc.concat({ date: curr.date, amount_paid: curr.series[0].value, num_payments: curr.series[0].extra.total, amount_received: curr.series[1].value, num_invoices: curr.series[1].extra.total });
}

@ -128,7 +128,7 @@ export class NonRoutingPeersComponent implements OnInit, AfterViewInit, OnDestro
loadNonRoutingPeersTable(forwardingEvents: ForwardingEvent[]) {
if (forwardingEvents.length > 0) {
// const grpdRoutingPeers = this.groupRoutingPeers(forwardingEvents);
const filteredNonRoutingChannels = this.activeChannels.filter((actvChnl) => forwardingEvents.findIndex((evnt) => (evnt.chan_id_in === actvChnl.chan_id || evnt.chan_id_out === actvChnl.chan_id)) < 0);
const filteredNonRoutingChannels = this.activeChannels?.filter((actvChnl) => forwardingEvents.findIndex((evnt) => (evnt.chan_id_in === actvChnl.chan_id || evnt.chan_id_out === actvChnl.chan_id)) < 0);
this.NonRoutingPeers = new MatTableDataSource<Channel>(filteredNonRoutingChannels);
this.NonRoutingPeers.sort = this.sort;
this.NonRoutingPeers.filterPredicate = (nrchnl: Channel, fltr: string) => JSON.stringify(nrchnl).toLowerCase().includes(fltr);

@ -10,7 +10,7 @@ import {
export const updateLNDAPICallStatus = createAction(LNDActions.UPDATE_API_CALL_STATUS_LND, props<{ payload: ApiCallStatusPayload }>());
export const resetLNDStore = createAction(LNDActions.RESET_LND_STORE, props<{ payload: SelNodeChild }>());
export const resetLNDStore = createAction(LNDActions.RESET_LND_STORE, props<{ payload: SelNodeChild | null }>());
export const setChildNodeSettingsLND = createAction(LNDActions.SET_CHILD_NODE_SETTINGS_LND, props<{ payload: SelNodeChild }>());

@ -1202,9 +1202,9 @@ export class LNDEffects implements OnDestroy {
this.store.dispatch(setNodeData({ payload: node_data }));
let newRoute = this.location.path();
if (newRoute.includes('/cln/')) {
newRoute = newRoute.replace('/cln/', '/lnd/');
newRoute = newRoute?.replace('/cln/', '/lnd/');
} else if (newRoute.includes('/ecl/')) {
newRoute = newRoute.replace('/ecl/', '/lnd/');
newRoute = newRoute?.replace('/ecl/', '/lnd/');
}
if (newRoute.includes('/unlock') || newRoute.includes('/login') || newRoute.includes('/error') || newRoute === '' || landingPage === 'HOME' || newRoute.includes('?access-key=')) {
newRoute = '/lnd/home';

@ -10,7 +10,7 @@ let flgUTXOsSet = false;
export const LNDReducer = createReducer(initLNDState,
on(updateLNDAPICallStatus, (state, { payload }) => {
const updatedApisCallStatus = JSON.parse(JSON.stringify(state.apisCallStatus));
updatedApisCallStatus[payload.action] = {
updatedApisCallStatus[payload.action || 0] = {
status: payload.status,
statusCode: payload.statusCode,
message: payload.message,
@ -51,7 +51,7 @@ export const LNDReducer = createReducer(initLNDState,
}),
on(addInvoice, (state, { payload }) => {
const newListInvoices = state.listInvoices;
newListInvoices.invoices.unshift(payload);
newListInvoices.invoices?.unshift(payload);
return {
...state,
listInvoices: newListInvoices
@ -59,7 +59,7 @@ export const LNDReducer = createReducer(initLNDState,
}),
on(updateInvoice, (state, { payload }) => {
const modifiedListInvoices = state.listInvoices;
modifiedListInvoices.invoices = modifiedListInvoices.invoices.map((invoice) => ((invoice.payment_request === payload.payment_request) ? payload : invoice));
modifiedListInvoices.invoices = modifiedListInvoices.invoices?.map((invoice) => ((invoice.payment_request === payload.payment_request) ? payload : invoice));
return {
...state,
listInvoices: modifiedListInvoices
@ -67,7 +67,7 @@ export const LNDReducer = createReducer(initLNDState,
}),
on(updatePayment, (state, { payload }) => {
const modifiedListPayments = state.listPayments;
modifiedListPayments.payments = modifiedListPayments.payments.map((payment) => ((payment.payment_hash === payload.payment_hash) ? payload : payment));
modifiedListPayments.payments = modifiedListPayments.payments?.map((payment) => ((payment.payment_hash === payload.payment_hash) ? payload : payment));
return {
...state,
listPayments: modifiedListPayments
@ -157,7 +157,7 @@ export const LNDReducer = createReducer(initLNDState,
if (payload.length && flgUTXOsSet) {
const modifiedUTXOs = [...state.utxos];
modifiedUTXOs.forEach((utxo) => {
const foundTransaction = payload.find((transaction) => transaction.tx_hash === utxo.outpoint.txid_str);
const foundTransaction = payload.find((transaction) => transaction.tx_hash === utxo.outpoint?.txid_str);
utxo.label = foundTransaction && foundTransaction.label ? foundTransaction.label : '';
});
return {
@ -176,7 +176,7 @@ export const LNDReducer = createReducer(initLNDState,
if (payload.length && flgTransactionsSet) {
const transactions = [...state.transactions];
payload.forEach((utxo) => {
const foundTransaction = transactions.find((transaction) => transaction.tx_hash === utxo.outpoint.txid_str);
const foundTransaction = transactions.find((transaction) => transaction.tx_hash === utxo.outpoint?.txid_str);
utxo.label = foundTransaction && foundTransaction.label ? foundTransaction.label : '';
});
}
@ -225,13 +225,13 @@ const mapAliases = (payload: any, storedChannels: (Channel | ClosedChannel)[]) =
payload.forwarding_events.forEach((fhEvent) => {
if (storedChannels && storedChannels.length > 0) {
for (let idx = 0; idx < storedChannels.length; idx++) {
if (storedChannels[idx].chan_id.toString() === fhEvent.chan_id_in) {
if (storedChannels[idx].chan_id?.toString() === fhEvent.chan_id_in) {
fhEvent.alias_in = storedChannels[idx].remote_alias ? storedChannels[idx].remote_alias : fhEvent.chan_id_in;
if (fhEvent.alias_out) {
return;
}
}
if (storedChannels[idx].chan_id.toString() === fhEvent.chan_id_out) {
if (storedChannels[idx].chan_id?.toString() === fhEvent.chan_id_out) {
fhEvent.alias_out = storedChannels[idx].remote_alias ? storedChannels[idx].remote_alias : fhEvent.chan_id_out;
if (fhEvent.alias_in) {
return;

@ -5,7 +5,7 @@ import { GetInfo, Peer, Fees, NetworkInfo, BlockchainBalance, Channel, ListInvoi
export interface LNDState {
apisCallStatus: ApiCallsListLND;
nodeSettings: SelNodeChild;
nodeSettings: SelNodeChild | null;
information: GetInfo;
peers: Peer[];
fees: Fees;

@ -145,11 +145,11 @@ export class LightningInvoicesComponent implements OnInit, AfterViewInit, OnDest
}
onRefreshInvoice(selInvoice: Invoice) {
this.store.dispatch(invoiceLookup({ payload: { openSnackBar: true, paymentHash: Buffer.from(selInvoice.r_hash.trim(), 'hex').toString('base64').replace(/\+/g, '-').replace(/[/]/g, '_') } }));
this.store.dispatch(invoiceLookup({ payload: { openSnackBar: true, paymentHash: Buffer.from(selInvoice.r_hash.trim(), 'hex').toString('base64')?.replace(/\+/g, '-')?.replace(/[/]/g, '_') } }));
}
updateInvoicesData(newInvoice: Invoice) {
this.invoicesData = this.invoicesData.map((invoice) => ((invoice.r_hash === newInvoice.r_hash) ? newInvoice : invoice));
this.invoicesData = this.invoicesData?.map((invoice) => ((invoice.r_hash === newInvoice.r_hash) ? newInvoice : invoice));
}
loadInvoicesTable(invoices) {

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

Loading…
Cancel
Save