mempool links for onchain information

pull/1383/head
ShahanaFarooqui 4 weeks ago
parent 062e38628f
commit 3f531369b1

3
.github/README.md vendored

@ -114,7 +114,8 @@ Example RTL-Config.json:
"unannouncedChannels": false, "unannouncedChannels": false,
"lnServerUrl": "<url for LND REST APIs for node #1 e.g. https://192.168.0.1:8080>", "lnServerUrl": "<url for LND REST APIs for node #1 e.g. https://192.168.0.1:8080>",
"swapServerUrl": "<url for swap server REST APIs for the node. e.g. https://127.0.0.1:8081>", "swapServerUrl": "<url for swap server REST APIs for the node. e.g. https://127.0.0.1:8081>",
"boltzServerUrl": "<url for boltz server REST APIs for the node. e.g. https://127.0.0.1:9003>" "boltzServerUrl": "<url for boltz server REST APIs for the node. e.g. https://127.0.0.1:9003>",
"blockExplorerUrl": "<url for local or centralized block explorer. e.g. https://mempool.space>"
} }
} }
] ]

@ -40,7 +40,8 @@ parameters have `default` values for initial setup and can be updated after RTL
"unannouncedChannels": <parameter to turn off/on setting for opening announced Channels, default false, Optional> "unannouncedChannels": <parameter to turn off/on setting for opening announced Channels, default false, Optional>
"lnServerUrl": "<Service url for LND/Core Lightning REST APIs for the node, e.g. https://192.168.0.1:8080 OR https://192.168.0.1:3001 OR http://192.168.0.1:8080. Default 'https://127.0.0.1:8080', Optional> "lnServerUrl": "<Service url for LND/Core Lightning REST APIs for the node, e.g. https://192.168.0.1:8080 OR https://192.168.0.1:3001 OR http://192.168.0.1:8080. Default 'https://127.0.0.1:8080', Optional>
"swapServerUrl": "<Service url for swap server REST APIs for the node, e.g. https://127.0.0.1:8081, Optional>", "swapServerUrl": "<Service url for swap server REST APIs for the node, e.g. https://127.0.0.1:8081, Optional>",
"boltzServerUrl": "<Service url for boltz server REST APIs for the node, e.g. https://127.0.0.1:9003, Optional>" "boltzServerUrl": "<Service url for boltz server REST APIs for the node, e.g. https://127.0.0.1:9003, Optional>",
"blockExplorerUrl": "<url for local or centralized block explorer. e.g. https://mempool.space>"
} }
} }
] ]

@ -89,7 +89,8 @@ Ensure that the follow values are correct per your config:
"logLevel": "INFO", "logLevel": "INFO",
"fiatConversion": false, "fiatConversion": false,
"unannouncedChannels": false, "unannouncedChannels": false,
"lnServerUrl": "https://<CLNRest api server ip address>:3001" "lnServerUrl": "https://<CLNRest api server ip address>:3001",
"blockExplorerUrl": "<Default: https://mempool.space>"
} }
} }
] ]

@ -83,7 +83,8 @@ Ensure that the follow values are correct per your config:
"logLevel": "INFO", "logLevel": "INFO",
"fiatConversion": false, "fiatConversion": false,
"unannouncedChannels": false, "unannouncedChannels": false,
"lnServerUrl": "http://<eclair api server ip address>:port" "lnServerUrl": "http://<eclair api server ip address>:port",
"blockExplorerUrl": "<Default: https://mempool.space>"
} }
} }
] ]

@ -43,7 +43,8 @@ If your running RTL and LND on different devices on your local LAN, certain conf
"unannouncedChannels": false, "unannouncedChannels": false,
"lnServerUrl": "<https://<ip-address-of-device-running-lnd>:8080; e.g. https://192.168.0.1:8080>", "lnServerUrl": "<https://<ip-address-of-device-running-lnd>:8080; e.g. https://192.168.0.1:8080>",
"swapServerUrl": "<https://<localhost>:8081>", "swapServerUrl": "<https://<localhost>:8081>",
"boltzServerUrl": "<https://<localhost>:9003>" "boltzServerUrl": "<https://<localhost>:9003>",
"blockExplorerUrl": "<Default: https://mempool.space>"
} }
} }
] ]

@ -29,7 +29,8 @@
"swapServerUrl": "https://127.0.0.1:8081", "swapServerUrl": "https://127.0.0.1:8081",
"boltzServerUrl": "https://127.0.0.1:9003", "boltzServerUrl": "https://127.0.0.1:9003",
"fiatConversion": false, "fiatConversion": false,
"unannouncedChannels": false "unannouncedChannels": false,
"blockExplorerUrl": "https://mempool.space"
} }
} }
] ]

@ -14,65 +14,6 @@ const logger = Logger;
const common = Common; const common = Common;
const wsServer = WSServer; const wsServer = WSServer;
const databaseService = Database; const databaseService = Database;
export const maskPasswords = (obj) => {
const keys = Object.keys(obj);
const length = keys.length;
if (length !== 0) {
for (let i = 0; i < length; i++) {
if (typeof obj[keys[i]] === 'object') {
keys[keys[i]] = maskPasswords(obj[keys[i]]);
}
if (typeof keys[i] === 'string' &&
((keys[i].toLowerCase().includes('password') && keys[i] !== 'allowPasswordUpdate') || keys[i].toLowerCase().includes('multipass') ||
keys[i].toLowerCase().includes('rpcpass') || keys[i].toLowerCase().includes('rpcpassword') ||
keys[i].toLowerCase().includes('rpcuser'))) {
obj[keys[i]] = '*'.repeat(20);
}
}
}
return obj;
};
export const removeAuthSecureData = (node) => {
delete node.authentication.macaroonPath;
delete node.authentication.runePath;
delete node.authentication.lnApiPassword;
delete node.authentication.options;
return node;
};
export const removeSecureData = (config) => {
delete config.rtlConfFilePath;
delete config.rtlPass;
delete config.multiPass;
delete config.multiPassHashed;
delete config.secret2FA;
config.nodes.map((node) => removeAuthSecureData(node));
return config;
};
export const addSecureData = (config) => {
config.rtlConfFilePath = common.appConfig.rtlConfFilePath;
config.rtlPass = common.appConfig.rtlPass;
config.multiPassHashed = common.appConfig.multiPassHashed;
config.SSO.rtlCookiePath = common.appConfig.SSO.rtlCookiePath;
if (common.appConfig.multiPass) {
config.multiPass = common.appConfig.multiPass;
}
if (config.secret2FA === common.appConfig.secret2FA) {
config.secret2FA = common.appConfig.secret2FA;
}
config.nodes.map((node, i) => {
if (common.appConfig && common.appConfig.nodes && common.appConfig.nodes.length > i && common.appConfig.nodes[i].authentication && common.appConfig.nodes[i].authentication.macaroonPath) {
node.authentication.macaroonPath = common.appConfig.nodes[i].authentication.macaroonPath;
}
if (common.appConfig && common.appConfig.nodes && common.appConfig.nodes.length > i && common.appConfig.nodes[i].authentication && common.appConfig.nodes[i].authentication.runePath) {
node.authentication.runePath = common.appConfig.nodes[i].authentication.runePath;
}
if (common.appConfig && common.appConfig.nodes && common.appConfig.nodes.length > i && common.appConfig.nodes[i].authentication && common.appConfig.nodes[i].authentication.lnApiPassword) {
node.authentication.lnApiPassword = common.appConfig.nodes[i].authentication.lnApiPassword;
}
return node;
});
return config;
};
export const getCurrencyRates = (req, res, next) => { export const getCurrencyRates = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Currency Rates..' }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Currency Rates..' });
options.url = 'https://blockchain.info/ticker'; options.url = 'https://blockchain.info/ticker';
@ -115,7 +56,7 @@ export const getApplicationSettings = (req, res, next) => {
return res.status(err.statusCode).json({ message: err.error, error: err.error }); return res.status(err.statusCode).json({ message: err.error, error: err.error });
} }
else { else {
const appConfData = removeSecureData(JSON.parse(data)); const appConfData = common.removeSecureData(JSON.parse(data));
appConfData.allowPasswordUpdate = common.appConfig.allowPasswordUpdate; appConfData.allowPasswordUpdate = common.appConfig.allowPasswordUpdate;
appConfData.enable2FA = common.appConfig.enable2FA; appConfData.enable2FA = common.appConfig.enable2FA;
appConfData.selectedNodeIndex = (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.selectedNode.index); appConfData.selectedNodeIndex = (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.selectedNode.index);
@ -157,9 +98,8 @@ export const updateSelectedNode = (req, res, next) => {
databaseService.loadDatabase(req.session); databaseService.loadDatabase(req.session);
} }
} }
const responseVal = !req.session.selectedNode.lnNode ? '' : req.session.selectedNode.lnNode; logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Selected Node Updated To ' + req.session.selectedNode.lnNode || '' });
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Selected Node Updated To ' + responseVal }); res.status(200).json(common.removeAuthSecureData(JSON.parse(JSON.stringify(req.session.selectedNode))));
res.status(200).json({ status: 'Selected Node Updated To: ' + JSON.stringify(responseVal) + '!' });
}; };
export const getConfig = (req, res, next) => { export const getConfig = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Reading Configuration File..' }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Reading Configuration File..' });
@ -205,7 +145,7 @@ export const getConfig = (req, res, next) => {
jsonConfig = parseHocon(data); jsonConfig = parseHocon(data);
} }
} }
jsonConfig = maskPasswords(jsonConfig); jsonConfig = common.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 }); 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 }); res.status(200).json({ format: fileFormat, data: responseJSON });
@ -242,7 +182,7 @@ export const updateNodeSettings = (req, res, next) => {
common.replaceNode(req, selectedNode); common.replaceNode(req, selectedNode);
} }
let responseNode = JSON.parse(JSON.stringify(common.selectedNode)); let responseNode = JSON.parse(JSON.stringify(common.selectedNode));
responseNode = removeAuthSecureData(responseNode); responseNode = common.removeAuthSecureData(responseNode);
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Node Settings Updated', data: responseNode }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Node Settings Updated', data: responseNode });
res.status(201).json(responseNode); res.status(201).json(responseNode);
} }
@ -256,7 +196,7 @@ export const updateApplicationSettings = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Application Settings..' }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Application Settings..' });
const RTLConfFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json'; const RTLConfFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json';
try { try {
const config = addSecureData(req.body); const config = common.addSecureData(req.body);
common.appConfig = JSON.parse(JSON.stringify(config)); common.appConfig = JSON.parse(JSON.stringify(config));
delete config.selectedNodeIndex; delete config.selectedNodeIndex;
delete config.enable2FA; delete config.enable2FA;
@ -265,8 +205,8 @@ export const updateApplicationSettings = (req, res, next) => {
delete config.rtlPass; delete config.rtlPass;
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8'); fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
const newConfig = JSON.parse(JSON.stringify(common.appConfig)); const newConfig = JSON.parse(JSON.stringify(common.appConfig));
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: maskPasswords(newConfig) }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: common.maskPasswords(newConfig) });
res.status(201).json(removeSecureData(newConfig)); res.status(201).json(common.removeSecureData(newConfig));
} }
catch (errRes) { catch (errRes) {
const errMsg = 'Update Default Node Error'; const errMsg = 'Update Default Node Error';

@ -7,7 +7,8 @@ export class SSO {
} }
} }
export class Settings { export class Settings {
constructor(lnServerUrl, swapServerUrl, boltzServerUrl, bitcoindConfigPath, channelBackupPath, logLevel, logFile, userPersona, themeMode, themeColor, unannouncedChannels, fiatConversion, currencyUnit, enableOffers, enablePeerswap) { constructor(blockExplorerUrl, lnServerUrl, swapServerUrl, boltzServerUrl, bitcoindConfigPath, channelBackupPath, logLevel, logFile, userPersona, themeMode, themeColor, unannouncedChannels, fiatConversion, currencyUnit, enableOffers, enablePeerswap) {
this.blockExplorerUrl = blockExplorerUrl;
this.lnServerUrl = lnServerUrl; this.lnServerUrl = lnServerUrl;
this.swapServerUrl = swapServerUrl; this.swapServerUrl = swapServerUrl;
this.boltzServerUrl = boltzServerUrl; this.boltzServerUrl = boltzServerUrl;

@ -21,6 +21,68 @@ export class CommonService {
{ name: 'JAN', days: 31 }, { name: 'FEB', days: 28 }, { name: 'MAR', days: 31 }, { name: 'APR', days: 30 }, { name: 'MAY', days: 31 }, { name: 'JUN', days: 30 }, { name: 'JAN', days: 31 }, { name: 'FEB', days: 28 }, { name: 'MAR', days: 31 }, { name: 'APR', days: 30 }, { name: 'MAY', days: 31 }, { name: 'JUN', days: 30 },
{ name: 'JUL', days: 31 }, { name: 'AUG', days: 31 }, { name: 'SEP', days: 30 }, { name: 'OCT', days: 31 }, { name: 'NOV', days: 30 }, { name: 'DEC', days: 31 } { name: 'JUL', days: 31 }, { name: 'AUG', days: 31 }, { name: 'SEP', days: 30 }, { name: 'OCT', days: 31 }, { name: 'NOV', days: 30 }, { name: 'DEC', days: 31 }
]; ];
this.maskPasswords = (obj) => {
const keys = Object.keys(obj);
const length = keys.length;
if (length !== 0) {
for (let i = 0; i < length; i++) {
if (typeof obj[keys[i]] === 'object') {
keys[keys[i]] = this.maskPasswords(obj[keys[i]]);
}
if (typeof keys[i] === 'string' &&
((keys[i].toLowerCase().includes('password') && keys[i] !== 'allowPasswordUpdate') || keys[i].toLowerCase().includes('multipass') ||
keys[i].toLowerCase().includes('rpcpass') || keys[i].toLowerCase().includes('rpcpassword') ||
keys[i].toLowerCase().includes('rpcuser'))) {
obj[keys[i]] = '*'.repeat(20);
}
}
}
return obj;
};
this.removeAuthSecureData = (node) => {
delete node.authentication.macaroonPath;
delete node.authentication.runePath;
delete node.authentication.runeValue;
delete node.authentication.lnApiPassword;
delete node.authentication.options;
return node;
};
this.removeSecureData = (config) => {
delete config.rtlConfFilePath;
delete config.rtlPass;
delete config.multiPass;
delete config.multiPassHashed;
delete config.secret2FA;
config.nodes?.map((node) => this.removeAuthSecureData(node));
return config;
};
this.addSecureData = (config) => {
config.rtlConfFilePath = this.appConfig.rtlConfFilePath;
config.rtlPass = this.appConfig.rtlPass;
config.multiPassHashed = this.appConfig.multiPassHashed;
config.SSO.rtlCookiePath = this.appConfig.SSO.rtlCookiePath;
if (this.appConfig.multiPass) {
config.multiPass = this.appConfig.multiPass;
}
if (config.secret2FA === this.appConfig.secret2FA) {
config.secret2FA = this.appConfig.secret2FA;
}
config.nodes.map((node, i) => {
if (this.appConfig && this.appConfig.nodes && this.appConfig.nodes.length > i && this.appConfig.nodes[i].authentication) {
if (this.appConfig.nodes[i].authentication.macaroonPath) {
node.authentication.macaroonPath = this.appConfig.nodes[i].authentication.macaroonPath;
}
if (this.appConfig.nodes[i].authentication.runePath) {
node.authentication.runePath = this.appConfig.nodes[i].authentication.runePath;
}
if (this.appConfig.nodes[i].authentication.lnApiPassword) {
node.authentication.lnApiPassword = this.appConfig.nodes[i].authentication.lnApiPassword;
}
}
return node;
});
return config;
};
this.setSwapServerOptions = (req) => { this.setSwapServerOptions = (req) => {
const swapOptions = { const swapOptions = {
baseUrl: req.session.selectedNode.settings.swapServerUrl, baseUrl: req.session.selectedNode.settings.swapServerUrl,
@ -470,18 +532,8 @@ export class CommonService {
this.logEnvVariables = (req) => { this.logEnvVariables = (req) => {
const selNode = req.session.selectedNode; const selNode = req.session.selectedNode;
if (selNode && selNode.index) { if (selNode && selNode.index) {
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'PORT: ' + this.port }); this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup:', msg: JSON.stringify(this.removeSecureData(JSON.parse(JSON.stringify(this.appConfig)))) });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'HOST: ' + this.host });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'DB_DIRECTORY_PATH: ' + this.appConfig.dbDirectoryPath });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'SSO: ' + this.appConfig.SSO.rtlSso }); this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'SSO: ' + this.appConfig.SSO.rtlSso });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'DEFAULT NODE INDEX: ' + selNode.index });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'INDEX: ' + selNode.index });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN NODE: ' + selNode.lnNode });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN IMPLEMENTATION: ' + selNode.lnImplementation });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'FIAT CONVERSION: ' + selNode.settings.fiatConversion });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'CURRENCY UNIT: ' + selNode.settings.currencyUnit });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN SERVER URL: ' + selNode.settings.lnServerUrl });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LOGOUT REDIRECT LINK: ' + this.appConfig.SSO.logoutRedirectLink + '\r\n' });
} }
}; };
this.filterData = (dataKey, lnImplementation) => { this.filterData = (dataKey, lnImplementation) => {

@ -73,7 +73,8 @@ export class ConfigService {
logLevel: 'ERROR', logLevel: 'ERROR',
lnServerUrl: 'https://127.0.0.1:8080', lnServerUrl: 'https://127.0.0.1:8080',
fiatConversion: false, fiatConversion: false,
unannouncedChannels: false unannouncedChannels: false,
blockExplorerUrl: 'https://mempool.space'
} }
} }
] ]
@ -142,7 +143,7 @@ export class ConfigService {
config.dbDirectoryPath = (process?.env?.DB_DIRECTORY_PATH) ? process?.env?.DB_DIRECTORY_PATH : (config.dbDirectoryPath) ? config.dbDirectoryPath : join(dirname(fileURLToPath(import.meta.url)), '..', '..'); config.dbDirectoryPath = (process?.env?.DB_DIRECTORY_PATH) ? process?.env?.DB_DIRECTORY_PATH : (config.dbDirectoryPath) ? config.dbDirectoryPath : join(dirname(fileURLToPath(import.meta.url)), '..', '..');
if (config.nodes && config.nodes.length > 0) { if (config.nodes && config.nodes.length > 0) {
config.nodes.forEach((node, idx) => { config.nodes.forEach((node, idx) => {
this.common.nodes[idx] = { settings: {}, authentication: {} }; this.common.nodes[idx] = { settings: { blockExplorerUrl: '' }, authentication: {} };
this.common.nodes[idx].index = node.index; this.common.nodes[idx].index = node.index;
this.common.nodes[idx].lnNode = node.lnNode; this.common.nodes[idx].lnNode = node.lnNode;
this.common.nodes[idx].lnImplementation = (process?.env?.lnImplementation) ? process?.env?.lnImplementation : node.lnImplementation ? node.lnImplementation : 'LND'; this.common.nodes[idx].lnImplementation = (process?.env?.lnImplementation) ? process?.env?.lnImplementation : node.lnImplementation ? node.lnImplementation : 'LND';
@ -269,6 +270,7 @@ export class ConfigService {
this.common.nodes[idx].settings.enablePeerswap = process?.env?.ENABLE_PEERSWAP ? process?.env?.ENABLE_PEERSWAP : (node.settings.enablePeerswap) ? node.settings.enablePeerswap : false; this.common.nodes[idx].settings.enablePeerswap = process?.env?.ENABLE_PEERSWAP ? process?.env?.ENABLE_PEERSWAP : (node.settings.enablePeerswap) ? node.settings.enablePeerswap : false;
this.common.nodes[idx].settings.bitcoindConfigPath = process?.env?.BITCOIND_CONFIG_PATH ? process?.env?.BITCOIND_CONFIG_PATH : (node.settings.bitcoindConfigPath) ? node.settings.bitcoindConfigPath : ''; this.common.nodes[idx].settings.bitcoindConfigPath = process?.env?.BITCOIND_CONFIG_PATH ? process?.env?.BITCOIND_CONFIG_PATH : (node.settings.bitcoindConfigPath) ? node.settings.bitcoindConfigPath : '';
this.common.nodes[idx].settings.channelBackupPath = process?.env?.CHANNEL_BACKUP_PATH ? process?.env?.CHANNEL_BACKUP_PATH : (node.settings.channelBackupPath) ? node.settings.channelBackupPath : this.common.appConfig.rtlConfFilePath + sep + 'channels-backup' + sep + 'node-' + node.index; this.common.nodes[idx].settings.channelBackupPath = process?.env?.CHANNEL_BACKUP_PATH ? process?.env?.CHANNEL_BACKUP_PATH : (node.settings.channelBackupPath) ? node.settings.channelBackupPath : this.common.appConfig.rtlConfFilePath + sep + 'channels-backup' + sep + 'node-' + node.index;
this.common.nodes[idx].settings.blockExplorerUrl = process?.env?.BLOCK_EXPLORER_URL ? process.env.BLOCK_EXPLORER_URL : (node.settings.blockExplorerUrl) ? node.settings.blockExplorerUrl : 'https://mempool.space';
try { try {
this.common.createDirectory(this.common.nodes[idx].settings.channelBackupPath); this.common.createDirectory(this.common.nodes[idx].settings.channelBackupPath);
const exists = fs.existsSync(this.common.nodes[idx].settings.channelBackupPath + sep + 'channel-all.bak'); const exists = fs.existsSync(this.common.nodes[idx].settings.channelBackupPath + sep + 'channel-all.bak');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(()=>{"use strict";var e,v={},m={};function r(e){var d=m[e];if(void 0!==d)return d.exports;var t=m[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=(d,t,i,f)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,f]=e[n],s=!0,o=0;o<t.length;o++)(!1&f||a>=f)&&Object.keys(r.O).every(b=>r.O[b](t[o]))?t.splice(o--,1):(s=!1,f<a&&(a=f));if(s){e.splice(n--,1);var u=i();void 0!==u&&(d=u)}}return d}f=f||0;for(var n=e.length;n>0&&e[n-1][2]>f;n--)e[n]=e[n-1];e[n]=[t,i,f]},r.d=(e,d)=>{for(var t in d)r.o(d,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:d[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((d,t)=>(r.f[t](e,d),d),[])),r.u=e=>e+"."+{125:"cb20f4b15dc644e7",456:"4e5a06b45d3c8f64",570:"255349a168f6c523",758:"db0aa17832e6073d"}[e]+".js",r.miniCssF=e=>{},r.o=(e,d)=>Object.prototype.hasOwnProperty.call(e,d),(()=>{var e={},d="RTLApp:";r.l=(t,i,f,n)=>{if(e[t])e[t].push(i);else{var a,s;if(void 0!==f)for(var o=document.getElementsByTagName("script"),u=0;u<o.length;u++){var l=o[u];if(l.getAttribute("src")==t||l.getAttribute("data-webpack")==d+f){a=l;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",d+f),a.src=r.tu(t)),e[t]=[i];var c=(g,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(y=>y(b)),g)return g(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=>{typeof Symbol<"u"&&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:d=>d},typeof trustedTypes<"u"&&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=(i,f)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)f.push(n[2]);else if(666!=i){var a=new Promise((l,c)=>n=e[i]=[l,c]);f.push(n[2]=a);var s=r.p+r.u(i),o=new Error;r.l(s,l=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var c=l&&("load"===l.type?"missing":l.type),p=l&&l.target&&l.target.src;o.message="Loading chunk "+i+" failed.\n("+c+": "+p+")",o.name="ChunkLoadError",o.type=c,o.request=p,n[1](o)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var d=(i,f)=>{var o,u,[n,a,s]=f,l=0;if(n.some(p=>0!==e[p])){for(o in a)r.o(a,o)&&(r.m[o]=a[o]);if(s)var c=s(r)}for(i&&i(f);l<n.length;l++)r.o(e,u=n[l])&&e[u]&&e[u][0](),e[u]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(d.bind(null,0)),t.push=d.bind(null,t.push.bind(t))})()})();

@ -0,0 +1 @@
(()=>{"use strict";var e,v={},m={};function r(e){var f=m[e];if(void 0!==f)return f.exports;var t=m[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=(f,t,i,o)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,o]=e[n],c=!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):(c=!1,o<a&&(a=o));if(c){e.splice(n--,1);var u=i();void 0!==u&&(f=u)}}return f}o=o||0;for(var n=e.length;n>0&&e[n-1][2]>o;n--)e[n]=e[n-1];e[n]=[t,i,o]},r.d=(e,f)=>{for(var t in f)r.o(f,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:f[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((f,t)=>(r.f[t](e,f),f),[])),r.u=e=>e+"."+{125:"05cbc1feb7174532",456:"a7433b9c5b34e0df",570:"a97682bb2ea30f3d",758:"b6dcd2f2b36dacf0"}[e]+".js",r.miniCssF=e=>{},r.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),(()=>{var e={},f="RTLApp:";r.l=(t,i,o,n)=>{if(e[t])e[t].push(i);else{var a,c;if(void 0!==o)for(var d=document.getElementsByTagName("script"),u=0;u<d.length;u++){var l=d[u];if(l.getAttribute("src")==t||l.getAttribute("data-webpack")==f+o){a=l;break}}a||(c=!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",f+o),a.src=r.tu(t)),e[t]=[i];var s=(g,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(y=>y(b)),g)return g(b)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{typeof Symbol<"u"&&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:f=>f},typeof trustedTypes<"u"&&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=(i,o)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)o.push(n[2]);else if(666!=i){var a=new Promise((l,s)=>n=e[i]=[l,s]);o.push(n[2]=a);var c=r.p+r.u(i),d=new Error;r.l(c,l=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var s=l&&("load"===l.type?"missing":l.type),p=l&&l.target&&l.target.src;d.message="Loading chunk "+i+" failed.\n("+s+": "+p+")",d.name="ChunkLoadError",d.type=s,d.request=p,n[1](d)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var f=(i,o)=>{var d,u,[n,a,c]=o,l=0;if(n.some(p=>0!==e[p])){for(d in a)r.o(a,d)&&(r.m[d]=a[d]);if(c)var s=c(r)}for(i&&i(o);l<n.length;l++)r.o(e,u=n[l])&&e[u]&&e[u][0](),e[u]=0;return r.O(s)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(f.bind(null,0)),t.push=f.bind(null,t.push.bind(t))})()})();

@ -8,7 +8,7 @@ import { Database, DatabaseService } from '../../utils/database.js';
import { Logger, LoggerService } from '../../utils/logger.js'; import { Logger, LoggerService } from '../../utils/logger.js';
import { Common, CommonService } from '../../utils/common.js'; import { Common, CommonService } from '../../utils/common.js';
import { WSServer } from '../../utils/webSocketServer.js'; import { WSServer } from '../../utils/webSocketServer.js';
import { ApplicationConfig, Authentication, SSO, SelectedNode } from '../../models/config.model.js'; import { Authentication, SSO } from '../../models/config.model.js';
const options = { url: '' }; const options = { url: '' };
const logger: LoggerService = Logger; const logger: LoggerService = Logger;
@ -16,70 +16,6 @@ const common: CommonService = Common;
const wsServer = WSServer; const wsServer = WSServer;
const databaseService: DatabaseService = Database; const databaseService: DatabaseService = Database;
export const maskPasswords = (obj) => {
const keys = Object.keys(obj);
const length = keys.length;
if (length !== 0) {
for (let i = 0; i < length; i++) {
if (typeof obj[keys[i]] === 'object') {
keys[keys[i]] = maskPasswords(obj[keys[i]]);
}
if (typeof keys[i] === 'string' &&
((keys[i].toLowerCase().includes('password') && keys[i] !== 'allowPasswordUpdate') || keys[i].toLowerCase().includes('multipass') ||
keys[i].toLowerCase().includes('rpcpass') || keys[i].toLowerCase().includes('rpcpassword') ||
keys[i].toLowerCase().includes('rpcuser'))
) {
obj[keys[i]] = '*'.repeat(20);
}
}
}
return obj;
};
export const removeAuthSecureData = (node: SelectedNode) => {
delete node.authentication.macaroonPath;
delete node.authentication.runePath;
delete node.authentication.lnApiPassword;
delete node.authentication.options;
return node;
};
export const removeSecureData = (config: ApplicationConfig) => {
delete config.rtlConfFilePath;
delete config.rtlPass;
delete config.multiPass;
delete config.multiPassHashed;
delete config.secret2FA;
config.nodes.map((node) => removeAuthSecureData(node));
return config;
};
export const addSecureData = (config: ApplicationConfig) => {
config.rtlConfFilePath = common.appConfig.rtlConfFilePath;
config.rtlPass = common.appConfig.rtlPass;
config.multiPassHashed = common.appConfig.multiPassHashed;
config.SSO.rtlCookiePath = common.appConfig.SSO.rtlCookiePath;
if (common.appConfig.multiPass) {
config.multiPass = common.appConfig.multiPass;
}
if (config.secret2FA === common.appConfig.secret2FA) {
config.secret2FA = common.appConfig.secret2FA;
}
config.nodes.map((node, i) => {
if (common.appConfig && common.appConfig.nodes && common.appConfig.nodes.length > i && common.appConfig.nodes[i].authentication && common.appConfig.nodes[i].authentication.macaroonPath) {
node.authentication.macaroonPath = common.appConfig.nodes[i].authentication.macaroonPath;
}
if (common.appConfig && common.appConfig.nodes && common.appConfig.nodes.length > i && common.appConfig.nodes[i].authentication && common.appConfig.nodes[i].authentication.runePath) {
node.authentication.runePath = common.appConfig.nodes[i].authentication.runePath;
}
if (common.appConfig && common.appConfig.nodes && common.appConfig.nodes.length > i && common.appConfig.nodes[i].authentication && common.appConfig.nodes[i].authentication.lnApiPassword) {
node.authentication.lnApiPassword = common.appConfig.nodes[i].authentication.lnApiPassword;
}
return node;
});
return config;
};
export const getCurrencyRates = (req, res, next) => { export const getCurrencyRates = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Currency Rates..' }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Currency Rates..' });
options.url = 'https://blockchain.info/ticker'; options.url = 'https://blockchain.info/ticker';
@ -120,7 +56,7 @@ export const getApplicationSettings = (req, res, next) => {
const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode); const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode);
return res.status(err.statusCode).json({ message: err.error, error: err.error }); return res.status(err.statusCode).json({ message: err.error, error: err.error });
} else { } else {
const appConfData = removeSecureData(JSON.parse(data)); const appConfData = common.removeSecureData(JSON.parse(data));
appConfData.allowPasswordUpdate = common.appConfig.allowPasswordUpdate; appConfData.allowPasswordUpdate = common.appConfig.allowPasswordUpdate;
appConfData.enable2FA = common.appConfig.enable2FA; appConfData.enable2FA = common.appConfig.enable2FA;
appConfData.selectedNodeIndex = (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.selectedNode.index); appConfData.selectedNodeIndex = (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.selectedNode.index);
@ -163,9 +99,8 @@ export const updateSelectedNode = (req, res, next) => {
databaseService.loadDatabase(req.session); databaseService.loadDatabase(req.session);
} }
} }
const responseVal = !req.session.selectedNode.lnNode ? '' : req.session.selectedNode.lnNode; logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Selected Node Updated To ' + req.session.selectedNode.lnNode || '' });
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Selected Node Updated To ' + responseVal }); res.status(200).json(common.removeAuthSecureData(JSON.parse(JSON.stringify(req.session.selectedNode))));
res.status(200).json({ status: 'Selected Node Updated To: ' + JSON.stringify(responseVal) + '!' });
}; };
export const getConfig = (req, res, next) => { export const getConfig = (req, res, next) => {
@ -210,7 +145,7 @@ export const getConfig = (req, res, next) => {
jsonConfig = parseHocon(data); jsonConfig = parseHocon(data);
} }
} }
jsonConfig = maskPasswords(jsonConfig); jsonConfig = common.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 }); 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 }); res.status(200).json({ format: fileFormat, data: responseJSON });
@ -246,7 +181,7 @@ export const updateNodeSettings = (req, res, next) => {
common.replaceNode(req, selectedNode); common.replaceNode(req, selectedNode);
} }
let responseNode = JSON.parse(JSON.stringify(common.selectedNode)); let responseNode = JSON.parse(JSON.stringify(common.selectedNode));
responseNode = removeAuthSecureData(responseNode); responseNode = common.removeAuthSecureData(responseNode);
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Node Settings Updated', data: responseNode }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Node Settings Updated', data: responseNode });
res.status(201).json(responseNode); res.status(201).json(responseNode);
} catch (errRes) { } catch (errRes) {
@ -260,7 +195,7 @@ export const updateApplicationSettings = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Application Settings..' }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Application Settings..' });
const RTLConfFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json'; const RTLConfFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json';
try { try {
const config = addSecureData(req.body); const config = common.addSecureData(req.body);
common.appConfig = JSON.parse(JSON.stringify(config)); common.appConfig = JSON.parse(JSON.stringify(config));
delete config.selectedNodeIndex; delete config.selectedNodeIndex;
delete config.enable2FA; delete config.enable2FA;
@ -269,8 +204,8 @@ export const updateApplicationSettings = (req, res, next) => {
delete config.rtlPass; delete config.rtlPass;
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8'); fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
const newConfig = JSON.parse(JSON.stringify(common.appConfig)); const newConfig = JSON.parse(JSON.stringify(common.appConfig));
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: maskPasswords(newConfig) }); logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: common.maskPasswords(newConfig) });
res.status(201).json(removeSecureData(newConfig)); res.status(201).json(common.removeSecureData(newConfig));
} catch (errRes) { } catch (errRes) {
const errMsg = 'Update Default Node Error'; const errMsg = 'Update Default Node Error';
const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode); const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode);

@ -12,6 +12,7 @@ export class SSO {
export class Settings { export class Settings {
constructor( constructor(
public blockExplorerUrl: string,
public lnServerUrl?: string, public lnServerUrl?: string,
public swapServerUrl?: string, public swapServerUrl?: string,
public boltzServerUrl?: string, public boltzServerUrl?: string,

@ -26,6 +26,73 @@ export class CommonService {
constructor() {} constructor() {}
public maskPasswords = (obj) => {
const keys = Object.keys(obj);
const length = keys.length;
if (length !== 0) {
for (let i = 0; i < length; i++) {
if (typeof obj[keys[i]] === 'object') {
keys[keys[i]] = this.maskPasswords(obj[keys[i]]);
}
if (typeof keys[i] === 'string' &&
((keys[i].toLowerCase().includes('password') && keys[i] !== 'allowPasswordUpdate') || keys[i].toLowerCase().includes('multipass') ||
keys[i].toLowerCase().includes('rpcpass') || keys[i].toLowerCase().includes('rpcpassword') ||
keys[i].toLowerCase().includes('rpcuser'))
) {
obj[keys[i]] = '*'.repeat(20);
}
}
}
return obj;
};
public removeAuthSecureData = (node: SelectedNode) => {
delete node.authentication.macaroonPath;
delete node.authentication.runePath;
delete node.authentication.runeValue;
delete node.authentication.lnApiPassword;
delete node.authentication.options;
return node;
};
public removeSecureData = (config: ApplicationConfig) => {
delete config.rtlConfFilePath;
delete config.rtlPass;
delete config.multiPass;
delete config.multiPassHashed;
delete config.secret2FA;
config.nodes?.map((node) => this.removeAuthSecureData(node));
return config;
};
public addSecureData = (config: ApplicationConfig) => {
config.rtlConfFilePath = this.appConfig.rtlConfFilePath;
config.rtlPass = this.appConfig.rtlPass;
config.multiPassHashed = this.appConfig.multiPassHashed;
config.SSO.rtlCookiePath = this.appConfig.SSO.rtlCookiePath;
if (this.appConfig.multiPass) {
config.multiPass = this.appConfig.multiPass;
}
if (config.secret2FA === this.appConfig.secret2FA) {
config.secret2FA = this.appConfig.secret2FA;
}
config.nodes.map((node, i) => {
if (this.appConfig && this.appConfig.nodes && this.appConfig.nodes.length > i && this.appConfig.nodes[i].authentication) {
if (this.appConfig.nodes[i].authentication.macaroonPath) {
node.authentication.macaroonPath = this.appConfig.nodes[i].authentication.macaroonPath;
}
if (this.appConfig.nodes[i].authentication.runePath) {
node.authentication.runePath = this.appConfig.nodes[i].authentication.runePath;
}
if (this.appConfig.nodes[i].authentication.lnApiPassword) {
node.authentication.lnApiPassword = this.appConfig.nodes[i].authentication.lnApiPassword;
}
}
return node;
});
return config;
};
public setSwapServerOptions = (req) => { public setSwapServerOptions = (req) => {
const swapOptions = { const swapOptions = {
baseUrl: req.session.selectedNode.settings.swapServerUrl, baseUrl: req.session.selectedNode.settings.swapServerUrl,
@ -478,18 +545,8 @@ export class CommonService {
public logEnvVariables = (req) => { public logEnvVariables = (req) => {
const selNode = <SelectedNode>req.session.selectedNode; const selNode = <SelectedNode>req.session.selectedNode;
if (selNode && selNode.index) { if (selNode && selNode.index) {
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'PORT: ' + this.port }); this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup:', msg: JSON.stringify(this.removeSecureData(JSON.parse(JSON.stringify(this.appConfig)))) });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'HOST: ' + this.host });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'DB_DIRECTORY_PATH: ' + this.appConfig.dbDirectoryPath });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'SSO: ' + this.appConfig.SSO.rtlSso }); this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'SSO: ' + this.appConfig.SSO.rtlSso });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'DEFAULT NODE INDEX: ' + selNode.index });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'INDEX: ' + selNode.index });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN NODE: ' + selNode.lnNode });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN IMPLEMENTATION: ' + selNode.lnImplementation });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'FIAT CONVERSION: ' + selNode.settings.fiatConversion });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'CURRENCY UNIT: ' + selNode.settings.currencyUnit });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN SERVER URL: ' + selNode.settings.lnServerUrl });
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LOGOUT REDIRECT LINK: ' + this.appConfig.SSO.logoutRedirectLink + '\r\n' });
} }
}; };

@ -79,7 +79,8 @@ export class ConfigService {
logLevel: 'ERROR', logLevel: 'ERROR',
lnServerUrl: 'https://127.0.0.1:8080', lnServerUrl: 'https://127.0.0.1:8080',
fiatConversion: false, fiatConversion: false,
unannouncedChannels: false unannouncedChannels: false,
blockExplorerUrl: 'https://mempool.space'
} }
} }
] ]
@ -146,7 +147,7 @@ export class ConfigService {
config.dbDirectoryPath = (process?.env?.DB_DIRECTORY_PATH) ? process?.env?.DB_DIRECTORY_PATH : (config.dbDirectoryPath) ? config.dbDirectoryPath : join(dirname(fileURLToPath(import.meta.url)), '..', '..'); config.dbDirectoryPath = (process?.env?.DB_DIRECTORY_PATH) ? process?.env?.DB_DIRECTORY_PATH : (config.dbDirectoryPath) ? config.dbDirectoryPath : join(dirname(fileURLToPath(import.meta.url)), '..', '..');
if (config.nodes && config.nodes.length > 0) { if (config.nodes && config.nodes.length > 0) {
config.nodes.forEach((node, idx) => { config.nodes.forEach((node, idx) => {
this.common.nodes[idx] = { settings: {}, authentication: {} }; this.common.nodes[idx] = { settings: { blockExplorerUrl: '' }, authentication: {} };
this.common.nodes[idx].index = node.index; this.common.nodes[idx].index = node.index;
this.common.nodes[idx].lnNode = node.lnNode; this.common.nodes[idx].lnNode = node.lnNode;
this.common.nodes[idx].lnImplementation = (process?.env?.lnImplementation) ? process?.env?.lnImplementation : node.lnImplementation ? node.lnImplementation : 'LND'; this.common.nodes[idx].lnImplementation = (process?.env?.lnImplementation) ? process?.env?.lnImplementation : node.lnImplementation ? node.lnImplementation : 'LND';
@ -255,6 +256,7 @@ export class ConfigService {
this.common.nodes[idx].settings.enablePeerswap = process?.env?.ENABLE_PEERSWAP ? process?.env?.ENABLE_PEERSWAP : (node.settings.enablePeerswap) ? node.settings.enablePeerswap : false; this.common.nodes[idx].settings.enablePeerswap = process?.env?.ENABLE_PEERSWAP ? process?.env?.ENABLE_PEERSWAP : (node.settings.enablePeerswap) ? node.settings.enablePeerswap : false;
this.common.nodes[idx].settings.bitcoindConfigPath = process?.env?.BITCOIND_CONFIG_PATH ? process?.env?.BITCOIND_CONFIG_PATH : (node.settings.bitcoindConfigPath) ? node.settings.bitcoindConfigPath : ''; this.common.nodes[idx].settings.bitcoindConfigPath = process?.env?.BITCOIND_CONFIG_PATH ? process?.env?.BITCOIND_CONFIG_PATH : (node.settings.bitcoindConfigPath) ? node.settings.bitcoindConfigPath : '';
this.common.nodes[idx].settings.channelBackupPath = process?.env?.CHANNEL_BACKUP_PATH ? process?.env?.CHANNEL_BACKUP_PATH : (node.settings.channelBackupPath) ? node.settings.channelBackupPath : this.common.appConfig.rtlConfFilePath + sep + 'channels-backup' + sep + 'node-' + node.index; this.common.nodes[idx].settings.channelBackupPath = process?.env?.CHANNEL_BACKUP_PATH ? process?.env?.CHANNEL_BACKUP_PATH : (node.settings.channelBackupPath) ? node.settings.channelBackupPath : this.common.appConfig.rtlConfFilePath + sep + 'channels-backup' + sep + 'node-' + node.index;
this.common.nodes[idx].settings.blockExplorerUrl = process?.env?.BLOCK_EXPLORER_URL ? process.env.BLOCK_EXPLORER_URL : (node.settings.blockExplorerUrl) ? node.settings.blockExplorerUrl : 'https://mempool.space';
try { try {
this.common.createDirectory(this.common.nodes[idx].settings.channelBackupPath); this.common.createDirectory(this.common.nodes[idx].settings.channelBackupPath);
const exists = fs.existsSync(this.common.nodes[idx].settings.channelBackupPath + sep + 'channel-all.bak'); const exists = fs.existsSync(this.common.nodes[idx].settings.channelBackupPath + sep + 'channel-all.bak');

@ -17,6 +17,7 @@ import { getQueryRoutes } from '../../store/cln.actions';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { clnPageSettings } from '../../store/cln.selector'; import { clnPageSettings } from '../../store/cln.selector';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-query-routes', selector: 'rtl-cln-query-routes',
@ -85,7 +86,7 @@ export class CLNQueryRoutesComponent implements OnInit, OnDestroy {
} }
onHopClick(selHop: Routes, event: any) { onHopClick(selHop: Routes, event: any) {
const reorderedHop = [ const reorderedHop: MessageDataField[][] = [
[{ key: 'id', value: selHop.id, title: 'ID', width: 100, type: DataTypeEnum.STRING }], [{ key: 'id', value: selHop.id, title: 'ID', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'channel', value: selHop.channel, title: 'Channel', width: 50, type: DataTypeEnum.STRING }, [{ key: 'channel', value: selHop.channel, title: 'Channel', width: 50, type: DataTypeEnum.STRING },
{ key: 'alias', value: selHop.alias, title: 'Peer Alias', width: 50, type: DataTypeEnum.STRING }], { key: 'alias', value: selHop.alias, title: 'Peer Alias', width: 50, type: DataTypeEnum.STRING }],

@ -6,6 +6,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { faBullhorn, faExclamationTriangle, faUsers } from '@fortawesome/free-solid-svg-icons'; import { faBullhorn, faExclamationTriangle, faUsers } from '@fortawesome/free-solid-svg-icons';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { DataService } from '../../../shared/services/data.service'; import { DataService } from '../../../shared/services/data.service';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
@ -22,7 +23,7 @@ import { clnPageSettings, nodeInfoAndBalance } from '../../store/cln.selector';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-liquidity-ads-list', selector: 'rtl-cln-liquidity-ads-list',
@ -237,7 +238,7 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
} }
}); });
} }
const reorderedLQNode = [ const reorderedLQNode: MessageDataField[][] = [
[{ key: 'alias', value: lqNode.alias, title: 'Node Alias', width: 50, type: DataTypeEnum.STRING }, [{ 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: '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: 'nodeid', value: lqNode.nodeid, title: 'Node ID', width: 100, type: DataTypeEnum.STRING }],

@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Balance, LocalRemoteBalance, UTXO } from '../../../../shared/models/clnModels'; import { Balance, LocalRemoteBalance, UTXO } from '../../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
@ -17,7 +18,7 @@ import { openAlert } from '../../../../store/rtl.actions';
import { clnPageSettings, utxoBalances } from '../../../store/cln.selector'; import { clnPageSettings, utxoBalances } from '../../../store/cln.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-on-chain-utxos', selector: 'rtl-cln-on-chain-utxos',
@ -119,8 +120,8 @@ export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestro
} }
onUTXOClick(selUtxo: UTXO, event: any) { onUTXOClick(selUtxo: UTXO, event: any) {
const reorderedUTXO = [ const reorderedUTXO: MessageDataField[][] = [
[{ key: 'txid', value: selUtxo.txid, title: 'Transaction ID', width: 100 }], [{ key: 'txid', value: selUtxo.txid, title: 'Transaction ID', width: 100, type: DataTypeEnum.STRING, explorerLink: 'tx' }],
[{ key: 'output', value: selUtxo.output, title: 'Output', width: 50, type: DataTypeEnum.NUMBER }, [{ key: 'output', value: selUtxo.output, title: 'Output', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'amount_msat', value: (selUtxo.amount_msat || 0) / 1000, title: 'Value (Sats)', width: 50, type: DataTypeEnum.NUMBER }], { key: 'amount_msat', value: (selUtxo.amount_msat || 0) / 1000, title: 'Value (Sats)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'status', value: this.commonService.titleCase(selUtxo.status || ''), title: 'Status', width: 50, type: DataTypeEnum.STRING }, [{ key: 'status', value: this.commonService.titleCase(selUtxo.status || ''), title: 'Status', width: 50, type: DataTypeEnum.STRING },

@ -5,6 +5,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Channel, ChannelHTLC } from '../../../../../shared/models/clnModels'; import { Channel, ChannelHTLC } from '../../../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
@ -17,7 +18,7 @@ import { RTLState } from '../../../../../store/rtl.state';
import { clnPageSettings, channels } from '../../../../store/cln.selector'; import { clnPageSettings, channels } from '../../../../store/cln.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-channel-active-htlcs-table', selector: 'rtl-cln-channel-active-htlcs-table',
@ -97,7 +98,7 @@ export class CLNChannelActiveHTLCsTableComponent implements OnInit, AfterViewIni
} }
onHTLCClick(selHtlc: ChannelHTLC, selChannel: Channel) { onHTLCClick(selHtlc: ChannelHTLC, selChannel: Channel) {
const reorderedHTLC = [ const reorderedHTLC: MessageDataField[][] = [
[{ key: 'alias', value: selChannel.alias, title: 'Alias', width: 100, type: DataTypeEnum.STRING }], [{ key: 'alias', value: selChannel.alias, title: 'Alias', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'amount_msat', value: ((selHtlc.amount_msat || 0) / 1000), title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER }, [{ key: 'amount_msat', value: ((selHtlc.amount_msat || 0) / 1000), title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'direction', value: this.commonService.titleCase(selHtlc.direction || ''), title: 'Direction', width: 50, type: DataTypeEnum.STRING }], { key: 'direction', value: this.commonService.titleCase(selHtlc.direction || ''), title: 'Direction', width: 50, type: DataTypeEnum.STRING }],

@ -7,6 +7,8 @@ import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Channel, GetInfo, ChannelEdge, Balance, LookupChannelEdge } from '../../../../../shared/models/clnModels'; import { Channel, GetInfo, ChannelEdge, Balance, LookupChannelEdge } from '../../../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, FEE_RATE_TYPES, APICallStatusEnum, UI_MESSAGES, CLN_DEFAULT_PAGE_SETTINGS, SortOrderEnum, CLN_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, FEE_RATE_TYPES, APICallStatusEnum, UI_MESSAGES, CLN_DEFAULT_PAGE_SETTINGS, SortOrderEnum, CLN_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
@ -23,7 +25,7 @@ import { channelLookup, closeChannel, updateChannel } from '../../../../store/cl
import { channels, clnPageSettings, nodeInfoAndBalanceAndNumPeers } from '../../../../store/cln.selector'; import { channels, clnPageSettings, nodeInfoAndBalanceAndNumPeers } from '../../../../store/cln.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-channel-open-table', selector: 'rtl-cln-channel-open-table',
@ -131,7 +133,7 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
} else { } else {
remoteNode = resLookup.channels[1]; remoteNode = resLookup.channels[1];
} }
const reorderedChannelPolicy = [ const reorderedChannelPolicy: MessageDataField[][] = [
[{ key: 'base_fee_millisatoshi', value: remoteNode.base_fee_millisatoshi, title: 'Base Fees (mSats)', width: 34, type: DataTypeEnum.NUMBER }, [{ key: 'base_fee_millisatoshi', value: remoteNode.base_fee_millisatoshi, title: 'Base Fees (mSats)', width: 34, type: DataTypeEnum.NUMBER },
{ key: 'fee_per_millionth', value: remoteNode.fee_per_millionth, title: 'Fee/Millionth', width: 33, type: DataTypeEnum.NUMBER }, { key: 'fee_per_millionth', value: remoteNode.fee_per_millionth, title: 'Fee/Millionth', width: 33, type: DataTypeEnum.NUMBER },
{ key: 'delay', value: remoteNode.delay, title: 'Delay', width: 33, type: DataTypeEnum.NUMBER }] { key: 'delay', value: remoteNode.delay, title: 'Delay', width: 33, type: DataTypeEnum.NUMBER }]

@ -9,6 +9,7 @@ import { faUsers } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Peer, GetInfo, Balance, UTXO, LocalRemoteBalance } from '../../../shared/models/clnModels'; import { Peer, GetInfo, Balance, UTXO, LocalRemoteBalance } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNActions, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNActions, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
@ -24,7 +25,7 @@ import { detachPeer } from '../../store/cln.actions';
import { clnPageSettings, nodeInfoAndBalance, peers, utxoBalances } from '../../store/cln.selector'; import { clnPageSettings, nodeInfoAndBalance, peers, utxoBalances } from '../../store/cln.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-peers', selector: 'rtl-cln-peers',
@ -125,7 +126,7 @@ export class CLNPeersComponent implements OnInit, AfterViewInit, OnDestroy {
} }
onPeerClick(selPeer: Peer, event: any) { onPeerClick(selPeer: Peer, event: any) {
const reorderedPeer = [ const reorderedPeer: MessageDataField[][] = [
[{ key: 'id', value: selPeer.id, title: 'Public Key', width: 100 }], [{ key: 'id', value: selPeer.id, title: 'Public Key', width: 100 }],
[{ key: 'netaddr', value: selPeer.netaddr, title: 'Address', width: 100 }], [{ key: 'netaddr', value: selPeer.netaddr, title: 'Address', width: 100 }],
[{ key: 'alias', value: selPeer.alias, title: 'Alias', width: 50 }, [{ key: 'alias', value: selPeer.alias, title: 'Alias', width: 50 },

@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { ForwardingEvent, ListForwards } from '../../../shared/models/clnModels'; import { ForwardingEvent, ListForwards } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
@ -20,7 +21,7 @@ import { clnPageSettings, failedForwardingHistory } from '../../store/cln.select
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-failed-history', selector: 'rtl-cln-failed-history',
@ -102,7 +103,7 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
} }
onFailedEventClick(selFEvent: ForwardingEvent) { onFailedEventClick(selFEvent: ForwardingEvent) {
const reorderedFHEvent = [ const reorderedFHEvent: MessageDataField[][] = [
[{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME }, [{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME },
{ key: 'resolved_time', value: selFEvent.resolved_time, title: 'Resolved Time', width: 50, type: DataTypeEnum.DATE_TIME }], { key: 'resolved_time', value: selFEvent.resolved_time, title: 'Resolved Time', width: 50, type: DataTypeEnum.DATE_TIME }],
[{ key: 'in_channel_alias', value: selFEvent.in_channel_alias, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING }, [{ key: 'in_channel_alias', value: selFEvent.in_channel_alias, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING },

@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { ForwardingEvent, ListForwards } from '../../../shared/models/clnModels'; import { ForwardingEvent, ListForwards } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
@ -19,7 +20,7 @@ import { clnPageSettings, forwardingHistory } from '../../store/cln.selector';
import { getForwardingHistory } from '../../store/cln.actions'; import { getForwardingHistory } from '../../store/cln.actions';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-forwarding-history', selector: 'rtl-cln-forwarding-history',
@ -128,7 +129,7 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
} }
onForwardingEventClick(selFEvent: ForwardingEvent, event: any) { onForwardingEventClick(selFEvent: ForwardingEvent, event: any) {
const reorderedFHEvent = [ const reorderedFHEvent: MessageDataField[][] = [
[{ key: 'status', value: 'Settled', title: 'Status', width: 50, type: DataTypeEnum.STRING }, [{ key: 'status', value: 'Settled', title: 'Status', width: 50, type: DataTypeEnum.STRING },
{ key: 'fee', value: selFEvent.fee_msat, title: 'Fee (mSats)', width: 50, type: DataTypeEnum.NUMBER }], { key: 'fee', value: selFEvent.fee_msat, title: 'Fee (mSats)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME }, [{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME },

@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { ListForwards, LocalFailedEvent } from '../../../shared/models/clnModels'; import { ListForwards, LocalFailedEvent } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNFailReason, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNFailReason, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
@ -20,7 +21,7 @@ import { clnPageSettings, localFailedForwardingHistory } from '../../store/cln.s
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-local-failed-history', selector: 'rtl-cln-local-failed-history',
@ -103,7 +104,7 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
} }
onFailedLocalEventClick(selFEvent: LocalFailedEvent) { onFailedLocalEventClick(selFEvent: LocalFailedEvent) {
const reorderedFHEvent = [ const reorderedFHEvent: MessageDataField[][] = [
[{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME }, [{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME },
{ key: 'in_channel_alias', value: selFEvent.in_channel_alias, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING }], { key: 'in_channel_alias', value: selFEvent.in_channel_alias, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'in_msatoshi', value: selFEvent.in_msat, title: 'Amount In (mSats)', width: 100, type: DataTypeEnum.NUMBER }], [{ key: 'in_msatoshi', value: selFEvent.in_msat, title: 'Amount In (mSats)', width: 100, type: DataTypeEnum.NUMBER }],

@ -28,6 +28,7 @@ import { clnNodeInformation, clnPageSettings, payments } from '../../store/cln.s
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { ConvertedCurrency } from '../../../shared/models/rtlModels'; import { ConvertedCurrency } from '../../../shared/models/rtlModels';
import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-cln-lightning-payments', selector: 'rtl-cln-lightning-payments',
@ -164,7 +165,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
sendPayment() { sendPayment() {
this.newlyAddedPayment = this.paymentDecoded?.payment_hash || ''; this.newlyAddedPayment = this.paymentDecoded?.payment_hash || '';
if (!this.paymentDecoded.amount_msat || this.paymentDecoded.amount_msat === 0) { if (!this.paymentDecoded.amount_msat || this.paymentDecoded.amount_msat === 0) {
const reorderedPaymentDecoded = [ const reorderedPaymentDecoded: MessageDataField[][] = [
[{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }], [{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }],
[{ key: 'payee', value: this.paymentDecoded.payee, title: 'Payee', width: 100 }], [{ key: 'payee', value: this.paymentDecoded.payee, title: 'Payee', width: 100 }],
[{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }], [{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }],
@ -199,7 +200,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
} }
}); });
} else { } else {
const reorderedPaymentDecoded = [ const reorderedPaymentDecoded: MessageDataField[][] = [
[{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }], [{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }],
[{ key: 'payee', value: this.paymentDecoded.payee, title: 'Payee', width: 100 }], [{ key: 'payee', value: this.paymentDecoded.payee, title: 'Payee', width: 100 }],
[{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }], [{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }],
@ -285,7 +286,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
} }
onPaymentClick(selPayment: Payment) { onPaymentClick(selPayment: Payment) {
const reorderedPayment = [ const reorderedPayment: MessageDataField[][] = [
[{ key: 'payment_preimage', value: selPayment.payment_preimage, title: 'Payment Preimage', width: 100, type: DataTypeEnum.STRING }], [{ key: 'payment_preimage', value: selPayment.payment_preimage, title: 'Payment Preimage', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'id', value: selPayment.id, title: 'ID', width: 20, type: DataTypeEnum.STRING }, [{ key: 'id', value: selPayment.id, title: 'ID', width: 20, type: DataTypeEnum.STRING },
{ key: 'destination', value: selPayment.destination, title: 'Destination', width: 80, type: DataTypeEnum.STRING }], { key: 'destination', value: selPayment.destination, title: 'Destination', width: 80, type: DataTypeEnum.STRING }],

@ -13,6 +13,7 @@ import { ECLEffects } from '../../store/ecl.effects';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { openAlert } from '../../../store/rtl.actions'; import { openAlert } from '../../../store/rtl.actions';
import { getQueryRoutes } from '../../store/ecl.actions'; import { getQueryRoutes } from '../../store/ecl.actions';
import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-ecl-query-routes', selector: 'rtl-ecl-query-routes',
@ -75,7 +76,7 @@ export class ECLQueryRoutesComponent implements OnInit, OnDestroy {
} }
onHopClick(selHop: RouteNode) { onHopClick(selHop: RouteNode) {
const reorderedHop = [ const reorderedHop: MessageDataField[][] = [
[{ key: 'alias', value: selHop.alias, title: 'Alias', width: 100, type: DataTypeEnum.STRING }], [{ key: 'alias', value: selHop.alias, title: 'Alias', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'nodeId', value: selHop.nodeId, title: 'Node ID', width: 100, type: DataTypeEnum.STRING }] [{ key: 'nodeId', value: selHop.nodeId, title: 'Node ID', width: 100, type: DataTypeEnum.STRING }]
]; ];

@ -7,6 +7,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Transaction } from '../../../shared/models/eclModels'; import { Transaction } from '../../../shared/models/eclModels';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
@ -20,7 +21,7 @@ import { fetchTransactions } from '../../store/ecl.actions';
import { eclPageSettings, transactions } from '../../store/ecl.selector'; import { eclPageSettings, transactions } from '../../store/ecl.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithSpacesPipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithSpacesPipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-ecl-on-chain-transaction-history', selector: 'rtl-ecl-on-chain-transaction-history',
@ -121,9 +122,9 @@ export class ECLOnChainTransactionHistoryComponent implements OnInit, OnDestroy
} }
onTransactionClick(selTransaction: Transaction, event: any) { onTransactionClick(selTransaction: Transaction, event: any) {
const reorderedTransactions = [ const reorderedTransactions: MessageDataField[][] = [
[{ key: 'blockHash', value: selTransaction.blockHash, title: 'Block Hash', width: 100 }], [{ key: 'blockHash', value: selTransaction.blockHash || selTransaction.blockId_opt, title: 'Block Hash', width: 100, explorerLink: 'block' }],
[{ key: 'txid', value: selTransaction.txid, title: 'Transaction ID', width: 100 }], [{ key: 'txid', value: selTransaction.txid, title: 'Transaction ID', width: 100, explorerLink: 'tx' }],
[{ key: 'timestamp', value: selTransaction.timestamp, title: 'Date/Time', width: 50, type: DataTypeEnum.DATE_TIME }, [{ key: 'timestamp', value: selTransaction.timestamp, title: 'Date/Time', width: 50, type: DataTypeEnum.DATE_TIME },
{ key: 'confirmations', value: selTransaction.confirmations, title: 'Number of Confirmations', width: 50, type: DataTypeEnum.NUMBER }], { key: 'confirmations', value: selTransaction.confirmations, title: 'Number of Confirmations', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'fees', value: selTransaction.fees, title: 'Fees (Sats)', width: 50, type: DataTypeEnum.NUMBER }, [{ key: 'fees', value: selTransaction.fees, title: 'Fees (Sats)', width: 50, type: DataTypeEnum.NUMBER },

@ -1,14 +1,14 @@
import { Component, OnInit, AfterViewInit, OnDestroy, ViewChild } from '@angular/core'; import { Component, OnInit, AfterViewInit, OnDestroy, ViewChild } from '@angular/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators'; import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects'; import { Actions } from '@ngrx/effects';
import { faUsers } from '@fortawesome/free-solid-svg-icons'; import { faUsers } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Peer, GetInfo, OnChainBalance } from '../../../shared/models/eclModels'; import { Peer, GetInfo, OnChainBalance } from '../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, ScreenSizeEnum, APICallStatusEnum, ECLActions, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, ScreenSizeEnum, APICallStatusEnum, ECLActions, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
@ -24,7 +24,7 @@ import { disconnectPeer } from '../../store/ecl.actions';
import { eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../store/ecl.selector'; import { eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../store/ecl.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithSpacesPipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithSpacesPipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-ecl-peers', selector: 'rtl-ecl-peers',
@ -119,7 +119,7 @@ export class ECLPeersComponent implements OnInit, AfterViewInit, OnDestroy {
} }
onPeerClick(selPeer: Peer, event: any) { onPeerClick(selPeer: Peer, event: any) {
const reorderedPeer = [ const reorderedPeer: MessageDataField[][] = [
[{ key: 'nodeId', value: selPeer.nodeId, title: 'Public Key', width: 100 }], [{ key: 'nodeId', value: selPeer.nodeId, title: 'Public Key', width: 100 }],
[{ key: 'address', value: selPeer.address, title: 'Address', width: 50 }, [{ key: 'address', value: selPeer.address, title: 'Address', width: 50 },
{ key: 'alias', value: selPeer.alias, title: 'Alias', width: 50 }], { key: 'alias', value: selPeer.alias, title: 'Alias', width: 50 }],

@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { PaymentRelayed, Payments } from '../../../shared/models/eclModels'; import { PaymentRelayed, Payments } from '../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
@ -18,7 +19,7 @@ import { openAlert } from '../../../store/rtl.actions';
import { eclPageSettings, payments } from '../../store/ecl.selector'; import { eclPageSettings, payments } from '../../store/ecl.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithSpacesPipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithSpacesPipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-ecl-forwarding-history', selector: 'rtl-ecl-forwarding-history',
@ -115,7 +116,7 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
} }
onForwardingEventClick(selFEvent: PaymentRelayed, event: any) { onForwardingEventClick(selFEvent: PaymentRelayed, event: any) {
const reorderedFHEvent = [ const reorderedFHEvent: MessageDataField[][] = [
[{ key: 'paymentHash', value: selFEvent.paymentHash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }], [{ key: 'paymentHash', value: selFEvent.paymentHash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'timestamp', value: Math.round((selFEvent.timestamp || 0) / 1000), title: 'Date/Time', width: 50, type: DataTypeEnum.DATE_TIME }, [{ 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: 'fee', value: ((selFEvent.amountIn || 0) - (selFEvent.amountOut || 0)), title: 'Fee Earned (Sats)', width: 50, type: DataTypeEnum.NUMBER }],

@ -29,6 +29,7 @@ import { eclNodeInformation, eclPageSettings, payments } from '../../store/ecl.s
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithSpacesPipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithSpacesPipe } from '../../../shared/pipes/app.pipe';
import { ConvertedCurrency } from '../../../shared/models/rtlModels'; import { ConvertedCurrency } from '../../../shared/models/rtlModels';
import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-ecl-lightning-payments', selector: 'rtl-ecl-lightning-payments',
@ -211,7 +212,7 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
sendPayment() { sendPayment() {
this.newlyAddedPayment = this.paymentDecoded.paymentHash || ''; this.newlyAddedPayment = this.paymentDecoded.paymentHash || '';
if (!this.paymentDecoded.amount || this.paymentDecoded.amount === 0) { if (!this.paymentDecoded.amount || this.paymentDecoded.amount === 0) {
const reorderedPaymentDecoded = [ const reorderedPaymentDecoded: MessageDataField[][] = [
[{ key: 'paymentHash', value: this.paymentDecoded.paymentHash, title: 'Payment Hash', width: 100 }], [{ key: 'paymentHash', value: this.paymentDecoded.paymentHash, title: 'Payment Hash', width: 100 }],
[{ key: 'nodeId', value: this.paymentDecoded.nodeId, title: 'Payee', width: 100 }], [{ key: 'nodeId', value: this.paymentDecoded.nodeId, title: 'Payee', width: 100 }],
[{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }], [{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }],
@ -246,7 +247,7 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
} }
}); });
} else { } else {
const reorderedPaymentDecoded = [ const reorderedPaymentDecoded: MessageDataField[][] = [
[{ key: 'paymentHash', value: this.paymentDecoded.paymentHash, title: 'Payment Hash', width: 100 }], [{ key: 'paymentHash', value: this.paymentDecoded.paymentHash, title: 'Payment Hash', width: 100 }],
[{ key: 'nodeId', value: this.paymentDecoded.nodeId, title: 'Payee', width: 100 }], [{ key: 'nodeId', value: this.paymentDecoded.nodeId, title: 'Payee', width: 100 }],
[{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }], [{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }],
@ -380,7 +381,7 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
} }
showPartView(selPart: PaymentSentPart, selPayment: PaymentSent, sentPaymentInfo?: any[]) { showPartView(selPart: PaymentSentPart, selPayment: PaymentSent, sentPaymentInfo?: any[]) {
const reorderedPart = [ const reorderedPart: MessageDataField[][] = [
[{ key: 'paymentHash', value: selPayment.paymentHash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }], [{ key: 'paymentHash', value: selPayment.paymentHash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'paymentPreimage', value: selPayment.paymentPreimage, title: 'Payment Preimage', width: 100, type: DataTypeEnum.STRING }], [{ key: 'paymentPreimage', value: selPayment.paymentPreimage, title: 'Payment Preimage', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'toChannelId', value: selPart.toChannelId, title: 'Channel', width: 100, type: DataTypeEnum.STRING }], [{ key: 'toChannelId', value: selPart.toChannelId, title: 'Channel', width: 100, type: DataTypeEnum.STRING }],

@ -18,6 +18,7 @@ import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'
import { lndPageSettings } from '../../store/lnd.selector'; import { lndPageSettings } from '../../store/lnd.selector';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-query-routes', selector: 'rtl-query-routes',
@ -88,7 +89,7 @@ export class QueryRoutesComponent implements OnInit, OnDestroy {
} }
onHopClick(selHop: Hop, event: any) { onHopClick(selHop: Hop, event: any) {
const reorderedHop = [ const reorderedHop: MessageDataField[][] = [
[{ key: 'hop_sequence', value: selHop.hop_sequence, title: 'Sequence', width: 33, type: DataTypeEnum.NUMBER }, [{ key: 'hop_sequence', value: selHop.hop_sequence, title: 'Sequence', width: 33, type: DataTypeEnum.NUMBER },
{ key: 'amt_to_forward', value: selHop.amt_to_forward, title: 'Amount To Forward (Sats)', width: 33, type: DataTypeEnum.NUMBER }, { key: 'amt_to_forward', value: selHop.amt_to_forward, title: 'Amount To Forward (Sats)', width: 33, type: DataTypeEnum.NUMBER },
{ key: 'fee_msat', value: selHop.fee_msat, title: 'Fee (mSats)', width: 34, type: DataTypeEnum.NUMBER }], { key: 'fee_msat', value: selHop.fee_msat, title: 'Fee (mSats)', width: 34, type: DataTypeEnum.NUMBER }],

@ -8,18 +8,19 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Transaction } from '../../../../shared/models/lndModels'; import { Transaction } from '../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../shared/services/logger.service'; import { LoggerService } from '../../../../shared/services/logger.service';
import { CommonService } from '../../../../shared/services/common.service'; import { CommonService } from '../../../../shared/services/common.service';
import { RTLState } from '../../../../store/rtl.state'; import { RTLState } from '../../../../store/rtl.state';
import { openAlert } from '../../../../store/rtl.actions'; import { openAlert } from '../../../../store/rtl.actions';
import { lndPageSettings, transactions } from '../../../store/lnd.selector'; import { lndPageSettings, transactions } from '../../../store/lnd.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-on-chain-transaction-history', selector: 'rtl-on-chain-transaction-history',
@ -98,9 +99,9 @@ export class OnChainTransactionHistoryComponent implements OnInit, OnChanges, On
} }
onTransactionClick(selTransaction: Transaction) { onTransactionClick(selTransaction: Transaction) {
const reorderedTransactions = [ const reorderedTransactions: MessageDataField[][] = [
[{ key: 'block_hash', value: selTransaction.block_hash, title: 'Block Hash', width: 100 }], [{ key: 'block_hash', value: selTransaction.block_hash, title: 'Block Hash', width: 100, explorerLink: 'block' }],
[{ key: 'tx_hash', value: selTransaction.tx_hash, title: 'Transaction Hash', width: 100 }], [{ key: 'tx_hash', value: selTransaction.tx_hash, title: 'Transaction Hash', width: 100, explorerLink: 'tx' }],
[{ key: 'label', value: selTransaction.label, title: 'Label', width: 100, type: DataTypeEnum.STRING }], [{ key: 'label', value: selTransaction.label, title: 'Label', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'time_stamp', value: selTransaction.time_stamp, title: 'Date/Time', width: 50, type: DataTypeEnum.DATE_TIME }, [{ key: 'time_stamp', value: selTransaction.time_stamp, title: 'Date/Time', width: 50, type: DataTypeEnum.DATE_TIME },
{ key: 'block_height', value: selTransaction.block_height, title: 'Block Height', width: 50, type: DataTypeEnum.NUMBER }], { key: 'block_height', value: selTransaction.block_height, title: 'Block Height', width: 50, type: DataTypeEnum.NUMBER }],

@ -9,6 +9,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { UTXO } from '../../../../shared/models/lndModels'; import { UTXO } from '../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, WALLET_ADDRESS_TYPE, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, WALLET_ADDRESS_TYPE, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions';
@ -24,7 +25,7 @@ import { openAlert, openConfirmation } from '../../../../store/rtl.actions';
import { lndPageSettings, utxos } from '../../../store/lnd.selector'; import { lndPageSettings, utxos } from '../../../store/lnd.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-on-chain-utxos', selector: 'rtl-on-chain-utxos',
@ -158,8 +159,8 @@ export class OnChainUTXOsComponent implements OnInit, OnChanges, OnDestroy {
} }
onUTXOClick(selUTXO: UTXO) { onUTXOClick(selUTXO: UTXO) {
const reorderedUTXOs = [ const reorderedUTXOs: MessageDataField[][] = [
[{ key: 'txid', value: selUTXO.outpoint?.txid_str, title: 'Transaction ID', width: 100, type: DataTypeEnum.STRING }], [{ key: 'txid', value: selUTXO.outpoint?.txid_str, title: 'Transaction ID', width: 100, type: DataTypeEnum.STRING, explorerLink: 'tx' }],
[{ key: 'label', value: selUTXO.label, title: 'Label', width: 100, type: DataTypeEnum.STRING }], [{ key: 'label', value: selUTXO.label, title: 'Label', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'output_index', value: selUTXO.outpoint?.output_index, title: 'Output Index', width: 34, type: DataTypeEnum.NUMBER }, [{ key: 'output_index', value: selUTXO.outpoint?.output_index, title: 'Output Index', width: 34, type: DataTypeEnum.NUMBER },
{ key: 'amount_sat', value: selUTXO.amount_sat, title: 'Amount (Sats)', width: 33, type: DataTypeEnum.NUMBER }, { key: 'amount_sat', value: selUTXO.amount_sat, title: 'Amount (Sats)', width: 33, type: DataTypeEnum.NUMBER },

@ -5,6 +5,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { ChannelInformationComponent } from '../../channel-information-modal/channel-information.component'; import { ChannelInformationComponent } from '../../channel-information-modal/channel-information.component';
import { Channel, ChannelHTLC, ChannelsSummary, LightningBalance } from '../../../../../shared/models/lndModels'; import { Channel, ChannelHTLC, ChannelsSummary, LightningBalance } from '../../../../../shared/models/lndModels';
@ -18,7 +19,7 @@ import { RTLState } from '../../../../../store/rtl.state';
import { channels, lndPageSettings } from '../../../../store/lnd.selector'; import { channels, lndPageSettings } from '../../../../store/lnd.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-channel-active-htlcs-table', selector: 'rtl-channel-active-htlcs-table',
@ -97,7 +98,7 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
} }
onHTLCClick(selHtlc: ChannelHTLC, selChannel: Channel) { onHTLCClick(selHtlc: ChannelHTLC, selChannel: Channel) {
const reorderedHTLC = [ const reorderedHTLC: MessageDataField[][] = [
[{ key: 'remote_alias', value: selChannel.remote_alias, title: 'Alias', width: 100, type: DataTypeEnum.STRING }], [{ key: 'remote_alias', value: selChannel.remote_alias, title: 'Alias', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'amount', value: selHtlc.amount, title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER }, [{ key: 'amount', value: selHtlc.amount, title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'incoming', value: (selHtlc.incoming ? 'Yes' : 'No'), title: 'Incoming', width: 50, type: DataTypeEnum.STRING }], { key: 'incoming', value: (selHtlc.incoming ? 'Yes' : 'No'), title: 'Incoming', width: 50, type: DataTypeEnum.STRING }],

@ -7,6 +7,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { ClosedChannel } from '../../../../../shared/models/lndModels'; import { ClosedChannel } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CHANNEL_CLOSURE_TYPE, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CHANNEL_CLOSURE_TYPE, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
@ -18,7 +19,7 @@ import { RTLState } from '../../../../../store/rtl.state';
import { closedChannels, lndPageSettings } from '../../../../store/lnd.selector'; import { closedChannels, lndPageSettings } from '../../../../store/lnd.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-channel-closed-table', selector: 'rtl-channel-closed-table',
@ -132,7 +133,7 @@ export class ChannelClosedTableComponent implements OnInit, AfterViewInit, OnDes
} }
onClosedChannelClick(selChannel: ClosedChannel, event: any) { onClosedChannelClick(selChannel: ClosedChannel, event: any) {
const reorderedChannel = [ const reorderedChannel: MessageDataField[][] = [
[{ key: 'close_type', value: this.channelClosureType[selChannel.close_type].name, title: 'Close Type', width: 30, type: DataTypeEnum.STRING }, [{ key: 'close_type', value: this.channelClosureType[selChannel.close_type].name, title: 'Close Type', width: 30, type: DataTypeEnum.STRING },
{ key: 'settled_balance', value: selChannel.settled_balance, title: 'Settled Balance', width: 30, type: DataTypeEnum.NUMBER }, { key: 'settled_balance', value: selChannel.settled_balance, title: 'Settled Balance', width: 30, type: DataTypeEnum.NUMBER },
{ key: 'time_locked_balance', value: selChannel.time_locked_balance, title: 'Time Locked Balance', width: 40, type: DataTypeEnum.NUMBER }], { key: 'time_locked_balance', value: selChannel.time_locked_balance, title: 'Time Locked Balance', width: 40, type: DataTypeEnum.NUMBER }],

@ -30,6 +30,7 @@ import { channelLookup, fetchChannels, updateChannel } from '../../../../store/l
import { blockchainBalance, channels, lndNodeInformation, lndPageSettings, peers } from '../../../../store/lnd.selector'; import { blockchainBalance, channels, lndNodeInformation, lndPageSettings, peers } from '../../../../store/lnd.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
import { MessageDataField } from '../../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-channel-open-table', selector: 'rtl-channel-open-table',
@ -156,7 +157,7 @@ export class ChannelOpenTableComponent implements OnInit, AfterViewInit, OnDestr
if (!resLookup.fee_base_msat && !resLookup.fee_rate_milli_msat && !resLookup.time_lock_delta) { if (!resLookup.fee_base_msat && !resLookup.fee_rate_milli_msat && !resLookup.time_lock_delta) {
return false; return false;
} }
const reorderedChannelPolicy = [ const reorderedChannelPolicy: MessageDataField[][] = [
[{ key: 'fee_base_msat', value: resLookup.fee_base_msat, title: 'Base Fees (mSats)', width: 25, type: DataTypeEnum.NUMBER }, [{ key: 'fee_base_msat', value: resLookup.fee_base_msat, title: 'Base Fees (mSats)', width: 25, type: DataTypeEnum.NUMBER },
{ key: 'fee_rate_milli_msat', value: resLookup.fee_rate_milli_msat, title: 'Fee Rate (milli mSats)', width: 25, type: DataTypeEnum.NUMBER }, { key: 'fee_rate_milli_msat', value: resLookup.fee_rate_milli_msat, title: 'Fee Rate (milli mSats)', width: 25, type: DataTypeEnum.NUMBER },
{ key: 'fee_rate_milli_msat', value: resLookup.fee_rate_milli_msat / 10000, title: 'Fee Rate (%)', width: 25, type: DataTypeEnum.NUMBER, digitsInfo: '1.0-8' }, { key: 'fee_rate_milli_msat', value: resLookup.fee_rate_milli_msat / 10000, title: 'Fee Rate (%)', width: 25, type: DataTypeEnum.NUMBER, digitsInfo: '1.0-8' },

@ -21,6 +21,7 @@ import { RTLState } from '../../../../../store/rtl.state';
import { rootSelectedNode } from '../../../../../store/rtl.selector'; import { rootSelectedNode } from '../../../../../store/rtl.selector';
import { lndNodeInformation, lndPageSettings, pendingChannels } from '../../../../store/lnd.selector'; import { lndNodeInformation, lndPageSettings, pendingChannels } from '../../../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { MessageDataField } from '../../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-channel-pending-table', selector: 'rtl-channel-pending-table',
@ -155,7 +156,7 @@ export class ChannelPendingTableComponent implements OnInit, AfterViewInit, OnDe
const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['remote_alias', 'channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2)); const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['remote_alias', 'channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2));
const preOrderedChannel: any = {}; const preOrderedChannel: any = {};
Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2); Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2);
const reorderedChannel = [ const reorderedChannel: MessageDataField[][] = [
[{ key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING }], [{ key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'remote_node_pub', value: preOrderedChannel.remote_node_pub, title: 'Peer Node Pubkey', width: 100, type: DataTypeEnum.STRING }], [{ key: 'remote_node_pub', value: preOrderedChannel.remote_node_pub, title: 'Peer Node Pubkey', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'remote_alias', value: preOrderedChannel.remote_alias, title: 'Peer Alias', width: 100, type: DataTypeEnum.STRING }], [{ key: 'remote_alias', value: preOrderedChannel.remote_alias, title: 'Peer Alias', width: 100, type: DataTypeEnum.STRING }],
@ -194,7 +195,7 @@ export class ChannelPendingTableComponent implements OnInit, AfterViewInit, OnDe
const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['remote_alias', 'channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2)); const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['remote_alias', 'channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2));
const preOrderedChannel: any = {}; const preOrderedChannel: any = {};
Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2); Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2);
const reorderedChannel = [ const reorderedChannel: MessageDataField[][] = [
[{ key: 'closing_txid', value: preOrderedChannel.closing_txid, title: 'Closing Transaction ID', width: 100, type: DataTypeEnum.STRING }], [{ key: 'closing_txid', value: preOrderedChannel.closing_txid, title: 'Closing Transaction ID', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING }], [{ key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'remote_alias', value: preOrderedChannel.remote_alias, title: 'Peer Alias', width: 25, type: DataTypeEnum.STRING }, [{ key: 'remote_alias', value: preOrderedChannel.remote_alias, title: 'Peer Alias', width: 25, type: DataTypeEnum.STRING },
@ -223,7 +224,7 @@ export class ChannelPendingTableComponent implements OnInit, AfterViewInit, OnDe
const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['remote_alias', 'channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2)); const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['remote_alias', 'channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2));
const preOrderedChannel: any = {}; const preOrderedChannel: any = {};
Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2); Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2);
const reorderedChannel = [ const reorderedChannel: MessageDataField[][] = [
[{ key: 'closing_txid', value: preOrderedChannel.closing_txid, title: 'Closing Transaction ID', width: 50, type: DataTypeEnum.STRING }], [{ key: 'closing_txid', value: preOrderedChannel.closing_txid, title: 'Closing Transaction ID', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING }], [{ key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'remote_alias', value: preOrderedChannel.remote_alias, title: 'Peer Alias', width: 25, type: DataTypeEnum.STRING }, [{ key: 'remote_alias', value: preOrderedChannel.remote_alias, title: 'Peer Alias', width: 25, type: DataTypeEnum.STRING },
@ -249,7 +250,7 @@ export class ChannelPendingTableComponent implements OnInit, AfterViewInit, OnDe
const fcChannelObj3 = JSON.parse(JSON.stringify(selChannel.commitments, ['local_txid'], 2)); const fcChannelObj3 = JSON.parse(JSON.stringify(selChannel.commitments, ['local_txid'], 2));
const preOrderedChannel: any = {}; const preOrderedChannel: any = {};
Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2, fcChannelObj3); Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2, fcChannelObj3);
const reorderedChannel = [ const reorderedChannel: MessageDataField[][] = [
[{ key: 'local_txid', value: preOrderedChannel.local_txid, title: 'Transaction ID', width: 100, type: DataTypeEnum.STRING }], [{ key: 'local_txid', value: preOrderedChannel.local_txid, title: 'Transaction ID', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING }], [{ key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'remote_alias', value: preOrderedChannel.remote_alias, title: 'Peer Alias', width: 25, type: DataTypeEnum.STRING }, [{ key: 'remote_alias', value: preOrderedChannel.remote_alias, title: 'Peer Alias', width: 25, type: DataTypeEnum.STRING },

@ -7,6 +7,7 @@ import { faUsers } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Peer, GetInfo, BlockchainBalance } from '../../../shared/models/lndModels'; import { Peer, GetInfo, BlockchainBalance } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
@ -22,7 +23,7 @@ import { detachPeer } from '../../store/lnd.actions';
import { blockchainBalance, lndNodeInformation, lndPageSettings, peers } from '../../store/lnd.selector'; import { blockchainBalance, lndNodeInformation, lndPageSettings, peers } from '../../store/lnd.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-peers', selector: 'rtl-peers',
@ -108,8 +109,7 @@ export class PeersComponent implements OnInit, AfterViewInit, OnDestroy {
} }
onPeerClick(selPeer: Peer, event: any) { onPeerClick(selPeer: Peer, event: any) {
// const encodedStr = encodeURIComponent('&#181;'); const reorderedPeer: MessageDataField[][] = [
const reorderedPeer = [
[{ key: 'pub_key', value: selPeer.pub_key, title: 'Public Key', width: 100 }], [{ key: 'pub_key', value: selPeer.pub_key, title: 'Public Key', width: 100 }],
[{ key: 'address', value: selPeer.address, title: 'Address', width: 100 }], [{ key: 'address', value: selPeer.address, title: 'Address', width: 100 }],
[{ key: 'alias', value: selPeer.alias, title: 'Alias', width: 40 }, { key: 'inbound', value: selPeer.inbound ? 'True' : 'False', title: 'Inbound', width: 30 }, { key: 'ping_time', value: selPeer.ping_time, title: 'Ping Time (\u00B5s)', width: 30, type: DataTypeEnum.NUMBER }], [{ key: 'alias', value: selPeer.alias, title: 'Alias', width: 40 }, { key: 'inbound', value: selPeer.inbound ? 'True' : 'False', title: 'Inbound', width: 30 }, { key: 'ping_time', value: selPeer.ping_time, title: 'Ping Time (\u00B5s)', width: 30, type: DataTypeEnum.NUMBER }],

@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { ForwardingEvent, SwitchRes } from '../../../shared/models/lndModels'; import { ForwardingEvent, SwitchRes } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
@ -18,7 +19,7 @@ import { RTLState } from '../../../store/rtl.state';
import { forwardingHistory, lndPageSettings } from '../../store/lnd.selector'; import { forwardingHistory, lndPageSettings } from '../../store/lnd.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-forwarding-history', selector: 'rtl-forwarding-history',
@ -119,7 +120,7 @@ export class ForwardingHistoryComponent implements OnInit, AfterViewInit, OnChan
} }
onForwardingEventClick(selFEvent: ForwardingEvent, event: any) { onForwardingEventClick(selFEvent: ForwardingEvent, event: any) {
const reorderedFHEvent = [ const reorderedFHEvent: MessageDataField[][] = [
[{ key: 'timestamp', value: selFEvent.timestamp, title: 'Timestamp', width: 25, type: DataTypeEnum.DATE_TIME }, [{ key: 'timestamp', value: selFEvent.timestamp, title: 'Timestamp', width: 25, type: DataTypeEnum.DATE_TIME },
{ key: 'amt_in', value: selFEvent.amt_in, title: 'Inbound Amount (Sats)', width: 25, type: DataTypeEnum.NUMBER }, { key: 'amt_in', value: selFEvent.amt_in, title: 'Inbound Amount (Sats)', width: 25, type: DataTypeEnum.NUMBER },
{ key: 'amt_out', value: selFEvent.amt_out, title: 'Outbound Amount (Sats)', width: 25, type: DataTypeEnum.NUMBER }, { key: 'amt_out', value: selFEvent.amt_out, title: 'Outbound Amount (Sats)', width: 25, type: DataTypeEnum.NUMBER },

@ -164,31 +164,6 @@ export class NonRoutingPeersComponent implements OnInit, AfterViewInit, OnDestro
this.router.navigate(['../../', 'connections', 'channels', 'open'], { relativeTo: this.activatedRoute, state: { filterValue: selNonRoutingChannel.chan_id } }); this.router.navigate(['../../', 'connections', 'channels', 'open'], { relativeTo: this.activatedRoute, state: { filterValue: selNonRoutingChannel.chan_id } });
} }
// groupRoutingPeers(forwardingEvents: ForwardingEvent[]) {
// const results: any[] = [];
// forwardingEvents.forEach((event: ForwardingEvent) => {
// const foundEntryInIdx = results.findIndex((result) => result.chan_id === event.chan_id_in);
// const foundEntryOutIdx = results.findIndex((result) => result.chan_id === event.chan_id_out);
// if (foundEntryInIdx < 0 && foundEntryOutIdx < 0) {
// results.push({ chan_id: event.chan_id_in, alias: event.alias_in, amt_in_msat: +event.amt_in_msat, amt_out_msat: 0 });
// results.push({ chan_id: event.chan_id_out, alias: event.alias_out, amt_out_msat: +event.amt_out_msat, amt_in_msat: 0 });
// }
// if (foundEntryInIdx < 0 && foundEntryOutIdx > -1) {
// results.push({ chan_id: event.chan_id_in, alias: event.alias_in, amt_in_msat: +event.amt_in_msat, amt_out_msat: 0 });
// results[foundEntryOutIdx].amt_out_msat = results[foundEntryOutIdx].amt_out_msat + +event.amt_out_msat;
// }
// if (foundEntryInIdx > -1 && foundEntryOutIdx < 0) {
// results.push({ chan_id: event.chan_id_out, alias: event.alias_out, amt_out_msat: +event.amt_out_msat, amt_in_msat: 0 });
// results[foundEntryInIdx].amt_in_msat = results[foundEntryInIdx].amt_in_msat + +event.amt_in_msat;
// }
// if (foundEntryInIdx > -1 && foundEntryOutIdx > -1) {
// results[foundEntryInIdx].amt_in_msat = results[foundEntryInIdx].amt_in_msat + +event.amt_in_msat;
// results[foundEntryOutIdx].amt_out_msat = results[foundEntryOutIdx].amt_out_msat + +event.amt_out_msat;
// }
// });
// return this.commonService.sortDescByKey(results, 'alias');
// }
applyFilter() { applyFilter() {
this.nonRoutingPeers.filter = this.selFilter.toLowerCase(); this.nonRoutingPeers.filter = this.selFilter.toLowerCase();
} }

@ -16,6 +16,7 @@ import { RTLState } from '../../../store/rtl.state';
import { forwardingHistory, lndPageSettings } from '../../store/lnd.selector'; import { forwardingHistory, lndPageSettings } from '../../store/lnd.selector';
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-routing-peers', selector: 'rtl-routing-peers',
@ -107,7 +108,7 @@ export class RoutingPeersComponent implements OnInit, AfterViewInit, OnDestroy {
} else { } else {
alertTitle = 'Outgoing' + alertTitle; alertTitle = 'Outgoing' + alertTitle;
} }
const reorderedRoutingPeer = [ const reorderedRoutingPeer: MessageDataField[][] = [
[{ key: 'chan_id', value: selRPeer.chan_id, title: 'Channel ID', width: 50, type: DataTypeEnum.STRING }, [{ key: 'chan_id', value: selRPeer.chan_id, title: 'Channel ID', width: 50, type: DataTypeEnum.STRING },
{ key: 'alias', value: selRPeer.alias, title: 'Peer Alias', width: 50, type: DataTypeEnum.STRING }], { key: 'alias', value: selRPeer.alias, title: 'Peer Alias', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'events', value: selRPeer.events, title: 'Events', width: 50, type: DataTypeEnum.NUMBER }, [{ key: 'events', value: selRPeer.events, title: 'Events', width: 50, type: DataTypeEnum.NUMBER },

@ -17,6 +17,8 @@ export const resetLNDStore = createAction(LNDActions.RESET_LND_STORE);
export const fetchPageSettings = createAction(LNDActions.FETCH_PAGE_SETTINGS_LND); export const fetchPageSettings = createAction(LNDActions.FETCH_PAGE_SETTINGS_LND);
export const updateSelectedNodeOptions = createAction(LNDActions.UPDATE_SELECTED_NODE_OPTIONS);
export const setPageSettings = createAction(LNDActions.SET_PAGE_SETTINGS_LND, props<{ payload: PageSettings[] }>()); export const setPageSettings = createAction(LNDActions.SET_PAGE_SETTINGS_LND, props<{ payload: PageSettings[] }>());
export const savePageSettings = createAction(LNDActions.SAVE_PAGE_SETTINGS_LND, props<{ payload: PageSettings[] }>()); export const savePageSettings = createAction(LNDActions.SAVE_PAGE_SETTINGS_LND, props<{ payload: PageSettings[] }>());

@ -940,7 +940,7 @@ export class LNDEffects implements OnDestroy {
); );
updateSelNodeOptions = createEffect(() => this.actions.pipe( updateSelNodeOptions = createEffect(() => this.actions.pipe(
ofType(RTLActions.UPDATE_SELECTED_NODE_OPTIONS), ofType(LNDActions.UPDATE_SELECTED_NODE_OPTIONS),
mergeMap(() => this.httpClient.get(this.CHILD_API_URL + API_END_POINTS.WALLET_API + '/updateSelNodeOptions').pipe( mergeMap(() => this.httpClient.get(this.CHILD_API_URL + API_END_POINTS.WALLET_API + '/updateSelNodeOptions').pipe(
map((postRes: any) => { map((postRes: any) => {
this.logger.info('Update Sel Node Successfull'); this.logger.info('Update Sel Node Successfull');

@ -63,12 +63,6 @@ export class LookupTransactionsComponent implements OnInit, OnDestroy {
break; break;
case 1: case 1:
this.store.dispatch(invoiceLookup({ payload: { openSnackBar: false, paymentHash: Buffer.from(this.lookupKey.trim(), 'hex').toString('base64')?.replace(/\+/g, '-')?.replace(/[/]/g, '_') } })); this.store.dispatch(invoiceLookup({ payload: { openSnackBar: false, paymentHash: Buffer.from(this.lookupKey.trim(), 'hex').toString('base64')?.replace(/\+/g, '-')?.replace(/[/]/g, '_') } }));
// if (this.lookupKey.trim().length < 45) {
// this.store.dispatch(invoiceLookup({ payload: { openSnackBar: false, paymentAddress: this.lookupKey.trim()?.replace(/\+/g, '-')?.replace(/[/]/g, '_') } }));
// }
// if (this.lookupKey.trim().length > 45 && this.lookupKey.trim().length < 70) {
// this.store.dispatch(invoiceLookup({ payload: { openSnackBar: false, paymentHash: Buffer.from(this.lookupKey.trim(), 'hex').toString('base64')?.replace(/\+/g, '-')?.replace(/[/]/g, '_') } }));
// }
break; break;
default: default:
break; break;

@ -28,6 +28,7 @@ import { lndNodeInformation, lndPageSettings, payments, peers } from '../../stor
import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
import { ConvertedCurrency } from '../../../shared/models/rtlModels'; import { ConvertedCurrency } from '../../../shared/models/rtlModels';
import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-lightning-payments', selector: 'rtl-lightning-payments',
@ -164,7 +165,7 @@ export class LightningPaymentsComponent implements OnInit, AfterViewInit, OnDest
this.paymentDecoded.num_satoshis = (+this.paymentDecoded.num_msat / 1000).toString(); this.paymentDecoded.num_satoshis = (+this.paymentDecoded.num_msat / 1000).toString();
} }
if (!this.paymentDecoded.num_satoshis || this.paymentDecoded.num_satoshis === '' || this.paymentDecoded.num_satoshis === '0') { if (!this.paymentDecoded.num_satoshis || this.paymentDecoded.num_satoshis === '' || this.paymentDecoded.num_satoshis === '0') {
const reorderedPaymentDecoded = [ const reorderedPaymentDecoded: MessageDataField[][] = [
[{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }], [{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }],
[{ key: 'destination', value: this.paymentDecoded.destination, title: 'Destination', width: 100 }], [{ key: 'destination', value: this.paymentDecoded.destination, title: 'Destination', width: 100 }],
[{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }], [{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }],
@ -199,7 +200,7 @@ export class LightningPaymentsComponent implements OnInit, AfterViewInit, OnDest
} }
}); });
} else { } else {
const reorderedPaymentDecoded = [ const reorderedPaymentDecoded: MessageDataField[][] = [
[{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }], [{ key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100 }],
[{ key: 'destination', value: this.paymentDecoded.destination, title: 'Destination', width: 100 }], [{ key: 'destination', value: this.paymentDecoded.destination, title: 'Destination', width: 100 }],
[{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }], [{ key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100 }],
@ -403,7 +404,7 @@ export class LightningPaymentsComponent implements OnInit, AfterViewInit, OnDest
} }
showPaymentView(selPayment: Payment, pathAliases: string) { showPaymentView(selPayment: Payment, pathAliases: string) {
const reorderedPayment = [ const reorderedPayment: MessageDataField[][] = [
[{ key: 'payment_hash', value: selPayment.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }], [{ key: 'payment_hash', value: selPayment.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'payment_preimage', value: selPayment.payment_preimage, title: 'Payment Preimage', width: 100, type: DataTypeEnum.STRING }], [{ key: 'payment_preimage', value: selPayment.payment_preimage, title: 'Payment Preimage', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'payment_request', value: selPayment.payment_request, title: 'Payment Request', width: 100, type: DataTypeEnum.STRING }], [{ key: 'payment_request', value: selPayment.payment_request, title: 'Payment Request', width: 100, type: DataTypeEnum.STRING }],

@ -8,8 +8,7 @@ import { MatStepper } from '@angular/material/stepper';
import { LNDEffects } from '../../store/lnd.effects'; import { LNDEffects } from '../../store/lnd.effects';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { updateSelectedNodeOptions } from '../../../store/rtl.actions'; import { fetchInfoLND, genSeed, initWallet, updateSelectedNodeOptions } from '../../store/lnd.actions';
import { fetchInfoLND, genSeed, initWallet } from '../../store/lnd.actions';
export function matchedPasswords(control: UntypedFormGroup): ValidationErrors | null { export function matchedPasswords(control: UntypedFormGroup): ValidationErrors | null {
const initWalletPassword = control.get('initWalletPassword'); const initWalletPassword = control.get('initWalletPassword');

@ -46,12 +46,12 @@ export class CurrencyUnitConverterComponent implements OnInit, OnChanges, OnDest
} }
getCurrencyValues() { getCurrencyValues() {
this.commonService.convertCurrency(this.values[0].dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.BTC, '', true, this.values[0].title). this.commonService.convertCurrency(this.values[0].dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.BTC, '', true).
pipe(takeUntil(this.unSubs[1])). pipe(takeUntil(this.unSubs[1])).
subscribe((data) => { subscribe((data) => {
this.values[0][CurrencyUnitEnum.BTC] = data.BTC; this.values[0][CurrencyUnitEnum.BTC] = data.BTC;
}); });
this.commonService.convertCurrency(this.values[0].dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, this.currencyUnits[2], this.fiatConversion, this.values[0].title). this.commonService.convertCurrency(this.values[0].dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, this.currencyUnits[2], this.fiatConversion).
pipe(takeUntil(this.unSubs[2])). pipe(takeUntil(this.unSubs[2])).
subscribe({ subscribe({
next: (data) => { next: (data) => {
@ -59,12 +59,12 @@ export class CurrencyUnitConverterComponent implements OnInit, OnChanges, OnDest
if (data.unit && data.unit !== '') { if (data.unit && data.unit !== '') {
for (let i = 1; i < this.values.length; i++) { for (let i = 1; i < this.values.length; i++) {
const value = this.values[i]; const value = this.values[i];
this.commonService.convertCurrency(value.dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.BTC, '', true, value.title). this.commonService.convertCurrency(value.dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.BTC, '', true).
pipe(takeUntil(this.unSubs[3])). pipe(takeUntil(this.unSubs[3])).
subscribe((data) => { subscribe((data) => {
this.values[i][CurrencyUnitEnum.BTC] = data.BTC; this.values[i][CurrencyUnitEnum.BTC] = data.BTC;
}); });
this.commonService.convertCurrency(value.dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, this.currencyUnits[2], this.fiatConversion, value.title). this.commonService.convertCurrency(value.dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, this.currencyUnits[2], this.fiatConversion).
pipe(takeUntil(this.unSubs[4])). pipe(takeUntil(this.unSubs[4])).
subscribe({ subscribe({
next: (data) => { next: (data) => {
@ -79,30 +79,6 @@ export class CurrencyUnitConverterComponent implements OnInit, OnChanges, OnDest
this.conversionErrorMsg = 'Conversion Error: ' + err; this.conversionErrorMsg = 'Conversion Error: ' + err;
} }
}); });
// this.values.forEach((value, i) => {
// if (value.dataValue > 0) {
// this.commonService.convertCurrency(value.dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.BTC, '', true, value.title).
// pipe(takeUntil(this.unSubs[1])).
// subscribe((data) => {
// this.values[i][CurrencyUnitEnum.BTC] = data.BTC;
// });
// this.commonService.convertCurrency(value.dataValue, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, this.currencyUnits[2], this.fiatConversion, value.title).
// pipe(takeUntil(this.unSubs[2])).
// subscribe({
// next: (data) => {
// console.log(data);
// this.values[i][CurrencyUnitEnum.OTHER] = data.OTHER;
// }, error: (err) => {
// this.conversionErrorMsg = 'Conversion Error: ' + err;
// }
// });
// } else {
// this.values[i][CurrencyUnitEnum.BTC] = value.dataValue;
// if (this.conversionErrorMsg === '') {
// this.values[i][CurrencyUnitEnum.OTHER] = value.dataValue;
// }
// }
// });
} }
ngOnDestroy() { ngOnDestroy() {

@ -48,7 +48,7 @@
<div *ngFor="let obj of objs; index as j;" fxLayout="column" fxFlex="100" fxFlex.gt-md="{{obj.width}}"> <div *ngFor="let obj of objs; index as j;" fxLayout="column" fxFlex="100" fxFlex.gt-md="{{obj.width}}">
<h4 fxLayoutAlign="start" class="font-bold-500">{{obj.title}}</h4> <h4 fxLayoutAlign="start" class="font-bold-500">{{obj.title}}</h4>
<span *ngIf="obj && (!!obj.value || obj.value === 0); else emptyField"> <span *ngIf="obj && (!!obj.value || obj.value === 0); else emptyField">
<span class="foreground-secondary-text" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" [ngSwitch]="obj.type"> <span class="foreground-secondary-text" fxLayout="row" fxFlex="100" fxLayoutAlign="start stretch" [ngSwitch]="obj.type">
<ng-container *ngSwitchCase="dataTypeEnum.ARRAY"> <ng-container *ngSwitchCase="dataTypeEnum.ARRAY">
<span *ngFor="let arrayObj of obj.value" class="display-block w-100" [innerHTML]="arrayObj"></span> <span *ngFor="let arrayObj of obj.value" class="display-block w-100" [innerHTML]="arrayObj"></span>
</ng-container> </ng-container>
@ -69,6 +69,7 @@
</ng-template> </ng-template>
</ng-template> </ng-template>
</ng-container> </ng-container>
<span><fa-icon *ngIf="obj.explorerLink && obj.explorerLink !== ''" class="ml-1" [icon]="faUpRightFromSquare" (click)="onExplorerClicked(obj)"/></span>
</span> </span>
</span> </span>
<ng-template #emptyField> <ng-template #emptyField>

@ -1,11 +1,19 @@
import { Component, OnInit, AfterViewChecked, Inject, ViewChild, ElementRef, OnDestroy, Renderer2 } from '@angular/core'; import { Component, OnInit, AfterViewChecked, Inject, ViewChild, ElementRef, OnDestroy, Renderer2 } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { faUpRightFromSquare } from '@fortawesome/free-solid-svg-icons';
import { RTLState } from '../../../../store/rtl.state';
import { rootSelectedNode } from '../../../../store/rtl.selector';
import { Node } from '../../../models/RTLconfig';
import { CommonService } from '../../../services/common.service'; import { CommonService } from '../../../services/common.service';
import { LoggerService } from '../../../services/logger.service'; import { LoggerService } from '../../../services/logger.service';
import { AlertData } from '../../../models/alertData'; import { AlertData, MessageDataField } from '../../../models/alertData';
import { AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, LoopStateEnum } from '../../../services/consts-enums-functions'; import { AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, LoopStateEnum } from '../../../services/consts-enums-functions';
@Component({ @Component({
@ -31,6 +39,7 @@ export class AlertMessageComponent implements OnInit, AfterViewChecked, OnDestro
} }
private unlistenStart: () => void; private unlistenStart: () => void;
private unlistenEnd: () => void; private unlistenEnd: () => void;
public faUpRightFromSquare = faUpRightFromSquare;
public LoopStateEnum = LoopStateEnum; public LoopStateEnum = LoopStateEnum;
public goToFieldValue = ''; public goToFieldValue = '';
public goToName = ''; public goToName = '';
@ -47,8 +56,10 @@ export class AlertMessageComponent implements OnInit, AfterViewChecked, OnDestro
public screenSizeEnum = ScreenSizeEnum; public screenSizeEnum = ScreenSizeEnum;
public scrollDirection = 'DOWN'; public scrollDirection = 'DOWN';
public shouldScroll = true; public shouldScroll = true;
public selNode: Node;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(public dialogRef: MatDialogRef<AlertMessageComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService, private snackBar: MatSnackBar, private commonService: CommonService, private renderer: Renderer2, private router: Router) { } constructor(public dialogRef: MatDialogRef<AlertMessageComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService, private snackBar: MatSnackBar, private commonService: CommonService, private renderer: Renderer2, private router: Router, private store: Store<RTLState>) { }
ngOnInit() { ngOnInit() {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
@ -66,6 +77,11 @@ export class AlertMessageComponent implements OnInit, AfterViewChecked, OnDestro
} }
} }
this.logger.info(this.messageObjs); this.logger.info(this.messageObjs);
this.store.select(rootSelectedNode).pipe(takeUntil(this.unSubs[0])).
subscribe((selNode) => {
this.selNode = selNode;
this.logger.info(this.selNode);
});
} }
ngAfterViewChecked() { ngAfterViewChecked() {
@ -96,6 +112,10 @@ export class AlertMessageComponent implements OnInit, AfterViewChecked, OnDestro
this.onClose(); this.onClose();
} }
onExplorerClicked(obj: MessageDataField) {
window.open(this.selNode.settings.blockExplorerUrl + '/' + obj.explorerLink + '/' + obj.value, '_blank');
}
ngOnDestroy() { ngOnDestroy() {
if (this.unlistenStart) { if (this.unlistenStart) {
this.unlistenStart(); this.unlistenStart();
@ -103,6 +123,10 @@ export class AlertMessageComponent implements OnInit, AfterViewChecked, OnDestro
if (this.unlistenEnd) { if (this.unlistenEnd) {
this.unlistenEnd(); this.unlistenEnd();
} }
this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null);
completeSub.complete();
});
} }
} }

@ -7,6 +7,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { Swap, ReverseSwap } from '../../../../models/boltzModels'; import { Swap, ReverseSwap } from '../../../../models/boltzModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, SwapTypeEnum, SwapStateEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, SwapTypeEnum, SwapStateEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../services/consts-enums-functions';
import { LoggerService } from '../../../../services/logger.service'; import { LoggerService } from '../../../../services/logger.service';
@ -19,7 +20,7 @@ import { ColumnDefinition, PageSettings, TableSetting } from '../../../../models
import { lndPageSettings } from '../../../../../lnd/store/lnd.selector'; import { lndPageSettings } from '../../../../../lnd/store/lnd.selector';
import { ApiCallStatusPayload } from '../../../../models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../models/apiCallsPayload';
import { CamelCaseWithReplacePipe } from '../../../../pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-boltz-swaps', selector: 'rtl-boltz-swaps',
@ -147,7 +148,7 @@ export class BoltzSwapsComponent implements OnInit, AfterViewInit, OnChanges, On
this.boltzService.swapInfo(selSwap.id || '').pipe(takeUntil(this.unSubs[1])). this.boltzService.swapInfo(selSwap.id || '').pipe(takeUntil(this.unSubs[1])).
subscribe((fetchedSwap: any) => { subscribe((fetchedSwap: any) => {
fetchedSwap = (this.selectedSwapType === SwapTypeEnum.SWAP_IN) ? fetchedSwap.swap : fetchedSwap.reverseSwap; fetchedSwap = (this.selectedSwapType === SwapTypeEnum.SWAP_IN) ? fetchedSwap.swap : fetchedSwap.reverseSwap;
const reorderedSwap = [ const reorderedSwap: MessageDataField[][] = [
[{ key: 'status', value: SwapStateEnum[fetchedSwap.status], title: 'Status', width: 50, type: DataTypeEnum.STRING }, [{ key: 'status', value: SwapStateEnum[fetchedSwap.status], title: 'Status', width: 50, type: DataTypeEnum.STRING },
{ key: 'id', value: fetchedSwap.id, title: 'ID', width: 50, type: DataTypeEnum.STRING }], { key: 'id', value: fetchedSwap.id, title: 'ID', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'amount', value: fetchedSwap.onchainAmount ? fetchedSwap.onchainAmount : fetchedSwap.expectedAmount ? fetchedSwap.expectedAmount : 0, [{ key: 'amount', value: fetchedSwap.onchainAmount ? fetchedSwap.onchainAmount : fetchedSwap.expectedAmount ? fetchedSwap.expectedAmount : 0,

@ -1,4 +1,5 @@
import { Component, OnChanges, OnDestroy, ViewChild, Input, AfterViewInit, SimpleChanges, OnInit } from '@angular/core'; import { Component, OnChanges, OnDestroy, ViewChild, Input, AfterViewInit, SimpleChanges, OnInit } from '@angular/core';
import { DatePipe } from '@angular/common';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
@ -7,6 +8,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { LoopSwapStatus } from '../../../../models/loopModels'; import { LoopSwapStatus } from '../../../../models/loopModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, LoopTypeEnum, LoopStateEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, LoopTypeEnum, LoopStateEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../services/consts-enums-functions';
import { LoggerService } from '../../../../services/logger.service'; import { LoggerService } from '../../../../services/logger.service';
@ -19,8 +21,7 @@ import { ColumnDefinition, PageSettings, TableSetting } from '../../../../models
import { lndPageSettings } from '../../../../../lnd/store/lnd.selector'; import { lndPageSettings } from '../../../../../lnd/store/lnd.selector';
import { ApiCallStatusPayload } from '../../../../models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../models/apiCallsPayload';
import { CamelCaseWithReplacePipe } from '../../../../pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../../../pipes/app.pipe';
import { DatePipe } from '@angular/common'; import { MessageDataField } from '../../../../../shared/models/alertData';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
@Component({ @Component({
selector: 'rtl-swaps', selector: 'rtl-swaps',
@ -127,7 +128,7 @@ export class SwapsComponent implements OnInit, AfterViewInit, OnChanges, OnDestr
onSwapClick(selSwap: LoopSwapStatus, event: any) { onSwapClick(selSwap: LoopSwapStatus, event: any) {
this.loopService.getSwap(selSwap.id_bytes?.replace(/\//g, '_')?.replace(/\+/g, '-') || '').pipe(takeUntil(this.unSubs[1])). this.loopService.getSwap(selSwap.id_bytes?.replace(/\//g, '_')?.replace(/\+/g, '-') || '').pipe(takeUntil(this.unSubs[1])).
subscribe((fetchedSwap: LoopSwapStatus) => { subscribe((fetchedSwap: LoopSwapStatus) => {
const reorderedSwap = [ const reorderedSwap: MessageDataField[][] = [
[{ key: 'state', value: LoopStateEnum[fetchedSwap.state || ''], title: 'Status', width: 50, type: DataTypeEnum.STRING }, [{ key: 'state', value: LoopStateEnum[fetchedSwap.state || ''], title: 'Status', width: 50, type: DataTypeEnum.STRING },
{ key: 'amt', value: fetchedSwap.amt, title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER }], { key: 'amt', value: fetchedSwap.amt, title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'initiation_time', value: (fetchedSwap.initiation_time || 0) / 1000000000, title: 'Initiation Time', width: 50, type: DataTypeEnum.DATE_TIME }, [{ key: 'initiation_time', value: (fetchedSwap.initiation_time || 0) / 1000000000, title: 'Initiation Time', width: 50, type: DataTypeEnum.DATE_TIME },

@ -41,7 +41,6 @@ export class ExperimentalSettingsComponent implements OnInit, OnDestroy {
public updateMsg: { error?: string } | { data?: string } = {}; public updateMsg: { error?: string } | { data?: string } = {};
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private dataService: DataService, private commonService: CommonService) { } constructor(private logger: LoggerService, private store: Store<RTLState>, private dataService: DataService, private commonService: CommonService) { }
ngOnInit() { ngOnInit() {

@ -64,15 +64,6 @@ export class NodeSettingsComponent implements OnInit, OnDestroy {
}); });
} }
// onCurrencyChange(event: any) {
// if (this.selNode.settings.fiatConversion) {
// this.selNode.settings.currencyUnit = '';
// } else {
// delete this.selNode.settings.currencyUnit;
// }
// this.store.dispatch(updateNodeSettings({ payload: this.selNode }));
// }
toggleSettings(toggleField: string, event?: any) { toggleSettings(toggleField: string, event?: any) {
this.selNode.settings[toggleField] = !this.selNode.settings[toggleField]; this.selNode.settings[toggleField] = !this.selNode.settings[toggleField];
} }

@ -5,6 +5,7 @@ import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { MAT_SELECT_CONFIG } from '@angular/material/select';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, SCROLL_RANGES, SortOrderEnum, LND_PAGE_DEFS, CLN_PAGE_DEFS, ECL_PAGE_DEFS } from '../../services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, SCROLL_RANGES, SortOrderEnum, LND_PAGE_DEFS, CLN_PAGE_DEFS, ECL_PAGE_DEFS } from '../../services/consts-enums-functions';
import { CommonService } from '../../services/common.service'; import { CommonService } from '../../services/common.service';
@ -14,7 +15,7 @@ import { ColumnDefinition, TableSetting } from '../../models/pageSettings';
import { Subject, takeUntil } from 'rxjs'; import { Subject, takeUntil } from 'rxjs';
import { rootSelectedNode } from '../../../store/rtl.selector'; import { rootSelectedNode } from '../../../store/rtl.selector';
import { CamelCaseWithReplacePipe } from '../../pipes/app.pipe'; import { CamelCaseWithReplacePipe } from '../../pipes/app.pipe';
import { MAT_SELECT_CONFIG } from '@angular/material/select'; import { MessageDataField } from '../../../shared/models/alertData';
@Component({ @Component({
selector: 'rtl-transactions-report-table', selector: 'rtl-transactions-report-table',
@ -78,7 +79,7 @@ export class TransactionsReportTableComponent implements OnInit, AfterViewInit,
} }
onTransactionClick(selTransaction: any) { onTransactionClick(selTransaction: any) {
const reorderedTransactions = [ const reorderedTransactions: MessageDataField[][] = [
[{ key: 'date', value: this.dataRange === SCROLL_RANGES[1] ? this.datePipe.transform(selTransaction.date, 'MMM/yyyy') : this.datePipe.transform(selTransaction.date, 'dd/MMM/yyyy'), title: 'Date', width: 100, type: DataTypeEnum.DATE }], [{ key: 'date', value: this.dataRange === SCROLL_RANGES[1] ? this.datePipe.transform(selTransaction.date, 'MMM/yyyy') : this.datePipe.transform(selTransaction.date, 'dd/MMM/yyyy'), title: 'Date', width: 100, type: DataTypeEnum.DATE }],
[{ key: 'amount_paid', value: Math.round(selTransaction.amount_paid), title: 'Amount Paid (Sats)', width: 50, type: DataTypeEnum.NUMBER }, [{ key: 'amount_paid', value: Math.round(selTransaction.amount_paid), title: 'Amount Paid (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'num_payments', value: selTransaction.num_payments, title: '# Payments', width: 50, type: DataTypeEnum.NUMBER }], { key: 'num_payments', value: selTransaction.num_payments, title: '# Payments', width: 50, type: DataTypeEnum.NUMBER }],

@ -27,7 +27,8 @@ export class Settings {
public channelBackupPath?: string, public channelBackupPath?: string,
public currencyUnit?: string, public currencyUnit?: string,
public enableOffers?: boolean, public enableOffers?: boolean,
public enablePeerswap?: boolean public enablePeerswap?: boolean,
public blockExplorerUrl?: string
) { } ) { }
} }

@ -18,6 +18,8 @@ export interface MessageDataField {
title: string; title: string;
width: number; width: number;
type?: DataTypeEnum; type?: DataTypeEnum;
digitsInfo?: string;
explorerLink?: string;
} }
export interface InputData { export interface InputData {

@ -174,6 +174,7 @@ export interface Transaction {
amount?: number; amount?: number;
fees?: number; fees?: number;
blockHash?: string; blockHash?: string;
blockId_opt?: string;
confirmations?: number; confirmations?: number;
txid?: string; txid?: string;
timestamp?: number; timestamp?: number;

@ -8,7 +8,7 @@ export interface OpenSnackBar {
type?: string; type?: string;
} }
export interface SetSelectedNode { export interface UpdateSelectedNode {
uiMessage: string; uiMessage: string;
prevLnNodeIndex: number; prevLnNodeIndex: number;
currentLnNode: Node | null; currentLnNode: Node | null;

@ -91,7 +91,7 @@ export class CommonService implements OnDestroy {
} }
} }
convertCurrency(value: number, from: string, to: string, otherCurrencyUnit: string, fiatConversion: boolean, title?: string): Observable<any> { convertCurrency(value: number, from: string, to: string, otherCurrencyUnit: string, fiatConversion: boolean): Observable<any> {
const latest_date = new Date().valueOf(); const latest_date = new Date().valueOf();
try { try {
if (fiatConversion && otherCurrencyUnit && (from === CurrencyUnitEnum.OTHER || to === CurrencyUnitEnum.OTHER)) { if (fiatConversion && otherCurrencyUnit && (from === CurrencyUnitEnum.OTHER || to === CurrencyUnitEnum.OTHER)) {

@ -396,7 +396,6 @@ export enum ReportBy {
export enum RTLActions { export enum RTLActions {
VOID = 'VOID', VOID = 'VOID',
SET_API_URL_ECL = 'SET_API_URL_ECL', SET_API_URL_ECL = 'SET_API_URL_ECL',
UPDATE_SELECTED_NODE_OPTIONS = 'UPDATE_SELECTED_NODE_OPTIONS',
UPDATE_API_CALL_STATUS_ROOT = 'UPDATE_API_CALL_STATUS_ROOT', UPDATE_API_CALL_STATUS_ROOT = 'UPDATE_API_CALL_STATUS_ROOT',
RESET_ROOT_STORE = 'RESET_ROOT_STORE', RESET_ROOT_STORE = 'RESET_ROOT_STORE',
CLOSE_ALL_DIALOGS = 'CLOSE_ALL_DIALOGS', CLOSE_ALL_DIALOGS = 'CLOSE_ALL_DIALOGS',
@ -436,6 +435,7 @@ export enum LNDActions {
RESET_LND_STORE = 'RESET_LND_STORE', RESET_LND_STORE = 'RESET_LND_STORE',
UPDATE_API_CALL_STATUS_LND = 'UPDATE_API_CALL_STATUS_LND', UPDATE_API_CALL_STATUS_LND = 'UPDATE_API_CALL_STATUS_LND',
SET_CHILD_NODE_SETTINGS_LND = 'SET_CHILD_NODE_SETTINGS_LND', SET_CHILD_NODE_SETTINGS_LND = 'SET_CHILD_NODE_SETTINGS_LND',
UPDATE_SELECTED_NODE_OPTIONS = 'UPDATE_SELECTED_NODE_OPTIONS',
FETCH_PAGE_SETTINGS_LND = 'FETCH_PAGE_SETTINGS_LND', FETCH_PAGE_SETTINGS_LND = 'FETCH_PAGE_SETTINGS_LND',
SET_PAGE_SETTINGS_LND = 'SET_PAGE_SETTINGS_LND', SET_PAGE_SETTINGS_LND = 'SET_PAGE_SETTINGS_LND',
SAVE_PAGE_SETTINGS_LND = 'SAVE_PAGE_SETTINGS_LND', SAVE_PAGE_SETTINGS_LND = 'SAVE_PAGE_SETTINGS_LND',

@ -761,7 +761,8 @@ export const mockActionsData = {
channelBackupPath: '', channelBackupPath: '',
currencyUnit: '', currencyUnit: '',
enableOffers: false, enableOffers: false,
enablePeerswap: false enablePeerswap: false,
blockExplorerUrl: 'https://mempool.space'
}, },
authentication: { authentication: {
swapMacaroonPath: '', swapMacaroonPath: '',
@ -792,7 +793,8 @@ export const mockActionsData = {
channelBackupPath: '', channelBackupPath: '',
currencyUnit: '', currencyUnit: '',
enableOffers: false, enableOffers: false,
enablePeerswap: false enablePeerswap: false,
blockExplorerUrl: 'https://mempool.space'
}, },
authentication: { authentication: {
swapMacaroonPath: '', swapMacaroonPath: '',
@ -863,7 +865,8 @@ export const mockRTLStoreState = {
'Sats', 'Sats',
'BTC', 'BTC',
'USD' 'USD'
] ],
blockExplorerUrl: 'https://mempool.space'
}, },
authentication: { authentication: {
configPath: '../AppData/Local/Lnd/lnd.conf', configPath: '../AppData/Local/Lnd/lnd.conf',
@ -901,7 +904,8 @@ export const mockRTLStoreState = {
'Sats', 'Sats',
'BTC', 'BTC',
'USD' 'USD'
] ],
blockExplorerUrl: 'https://mempool.space'
}, },
authentication: { authentication: {
configPath: '../AppData/Local/Lnd/lnd.conf', configPath: '../AppData/Local/Lnd/lnd.conf',
@ -930,7 +934,8 @@ export const mockRTLStoreState = {
'Sats', 'Sats',
'BTC', 'BTC',
'USD' 'USD'
] ],
blockExplorerUrl: 'https://mempool.space'
}, },
authentication: { authentication: {
configPath: '../Nodes/cln/config', configPath: '../Nodes/cln/config',
@ -959,7 +964,8 @@ export const mockRTLStoreState = {
'Sats', 'Sats',
'BTC', 'BTC',
'USD' 'USD'
] ],
blockExplorerUrl: 'https://mempool.space'
}, },
authentication: { authentication: {
configPath: '../.eclair/eclair.conf', configPath: '../.eclair/eclair.conf',

@ -3,7 +3,7 @@ import { createAction, props } from '@ngrx/store';
import { DialogConfig } from '../shared/models/alertData'; import { DialogConfig } from '../shared/models/alertData';
import { ApiCallStatusPayload } from '../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../shared/models/apiCallsPayload';
import { RTLConfiguration, Node, GetInfoRoot } from '../shared/models/RTLconfig'; import { RTLConfiguration, Node, GetInfoRoot } from '../shared/models/RTLconfig';
import { FetchFile, Login, OpenSnackBar, ResetPassword, SetSelectedNode, VerifyTwoFA } from '../shared/models/rtlModels'; import { FetchFile, Login, OpenSnackBar, ResetPassword, UpdateSelectedNode, VerifyTwoFA } from '../shared/models/rtlModels';
import { RTLActions } from '../shared/services/consts-enums-functions'; import { RTLActions } from '../shared/services/consts-enums-functions';
export const voidAction = createAction(RTLActions.VOID); export const voidAction = createAction(RTLActions.VOID);
@ -34,15 +34,13 @@ export const fetchConfig = createAction(RTLActions.FETCH_CONFIG, props<{ payload
export const showConfig = createAction(RTLActions.SHOW_CONFIG, props<{ payload: any }>()); export const showConfig = createAction(RTLActions.SHOW_CONFIG, props<{ payload: any }>());
export const updateSelectedNodeOptions = createAction(RTLActions.UPDATE_SELECTED_NODE_OPTIONS);
export const resetRootStore = createAction(RTLActions.RESET_ROOT_STORE, props<{ payload: Node }>()); export const resetRootStore = createAction(RTLActions.RESET_ROOT_STORE, props<{ payload: Node }>());
export const fetchRTLConfig = createAction(RTLActions.FETCH_APPLICATION_SETTINGS); export const fetchRTLConfig = createAction(RTLActions.FETCH_APPLICATION_SETTINGS);
export const setApplicationSettings = createAction(RTLActions.SET_APPLICATION_SETTINGS, props<{ payload: RTLConfiguration }>()); export const setApplicationSettings = createAction(RTLActions.SET_APPLICATION_SETTINGS, props<{ payload: RTLConfiguration }>());
export const setSelectedNode = createAction(RTLActions.SET_SELECTED_NODE, props<{ payload: SetSelectedNode }>()); export const setSelectedNode = createAction(RTLActions.SET_SELECTED_NODE, props<{ payload: UpdateSelectedNode }>());
export const updateNodeSettings = createAction(RTLActions.UPDATE_NODE_SETTINGS, props<{ payload: Node }>()); export const updateNodeSettings = createAction(RTLActions.UPDATE_NODE_SETTINGS, props<{ payload: Node }>());

@ -17,7 +17,7 @@ import { DataService } from '../shared/services/data.service';
import { RTLConfiguration, Node, GetInfoRoot } from '../shared/models/RTLconfig'; import { RTLConfiguration, Node, GetInfoRoot } from '../shared/models/RTLconfig';
import { API_URL, API_END_POINTS, RTLActions, APICallStatusEnum, AuthenticateWith, CURRENCY_UNITS, ScreenSizeEnum, UI_MESSAGES } from '../shared/services/consts-enums-functions'; import { API_URL, API_END_POINTS, RTLActions, APICallStatusEnum, AuthenticateWith, CURRENCY_UNITS, ScreenSizeEnum, UI_MESSAGES } from '../shared/services/consts-enums-functions';
import { DialogConfig } from '../shared/models/alertData'; import { DialogConfig } from '../shared/models/alertData';
import { FetchFile, Login, OpenSnackBar, ResetPassword, SetSelectedNode, VerifyTwoFA } from '../shared/models/rtlModels'; import { FetchFile, Login, OpenSnackBar, ResetPassword, UpdateSelectedNode, VerifyTwoFA } from '../shared/models/rtlModels';
import { SpinnerDialogComponent } from '../shared/components/data-modal/spinner-dialog/spinner-dialog.component'; import { SpinnerDialogComponent } from '../shared/components/data-modal/spinner-dialog/spinner-dialog.component';
import { AlertMessageComponent } from '../shared/components/data-modal/alert-message/alert-message.component'; import { AlertMessageComponent } from '../shared/components/data-modal/alert-message/alert-message.component';
@ -468,7 +468,7 @@ export class RTLEffects implements OnDestroy {
setSelectedNode = createEffect( setSelectedNode = createEffect(
() => this.actions.pipe( () => this.actions.pipe(
ofType(RTLActions.SET_SELECTED_NODE), ofType(RTLActions.SET_SELECTED_NODE),
mergeMap((action: { type: string, payload: SetSelectedNode }) => { mergeMap((action: { type: string, payload: UpdateSelectedNode }) => {
this.store.dispatch(openSpinner({ payload: action.payload.uiMessage })); this.store.dispatch(openSpinner({ payload: action.payload.uiMessage }));
this.store.dispatch(updateRootAPICallStatus({ payload: { action: 'UpdateSelNode', status: APICallStatusEnum.INITIATED } })); this.store.dispatch(updateRootAPICallStatus({ payload: { action: 'UpdateSelNode', status: APICallStatusEnum.INITIATED } }));
return this.httpClient.get(API_END_POINTS.CONF_API + '/updateSelNode/' + action.payload.currentLnNode?.index + '/' + action.payload.prevLnNodeIndex).pipe( return this.httpClient.get(API_END_POINTS.CONF_API + '/updateSelNode/' + action.payload.currentLnNode?.index + '/' + action.payload.prevLnNodeIndex).pipe(
@ -476,7 +476,7 @@ export class RTLEffects implements OnDestroy {
this.logger.info(postRes); this.logger.info(postRes);
this.store.dispatch(updateRootAPICallStatus({ payload: { action: 'UpdateSelNode', status: APICallStatusEnum.COMPLETED } })); this.store.dispatch(updateRootAPICallStatus({ payload: { action: 'UpdateSelNode', status: APICallStatusEnum.COMPLETED } }));
this.store.dispatch(closeSpinner({ payload: action.payload.uiMessage })); this.store.dispatch(closeSpinner({ payload: action.payload.uiMessage }));
this.initializeNode(action.payload.currentLnNode!, action.payload.isInitialSetup); this.initializeNode(postRes, action.payload.isInitialSetup);
return { type: RTLActions.VOID }; return { type: RTLActions.VOID };
}), }),
catchError((err: any) => { catchError((err: any) => {

@ -17,7 +17,7 @@ export interface RootState {
const initNodeSettings: Settings = { userPersona: UserPersonaEnum.OPERATOR, themeMode: 'DAY', themeColor: 'PURPLE', const initNodeSettings: Settings = { userPersona: UserPersonaEnum.OPERATOR, themeMode: 'DAY', themeColor: 'PURPLE',
channelBackupPath: '', selCurrencyUnit: 'USD', unannouncedChannels: false, fiatConversion: false, channelBackupPath: '', selCurrencyUnit: 'USD', unannouncedChannels: false, fiatConversion: false,
currencyUnits: ['Sats', 'BTC', 'USD'], bitcoindConfigPath: '', enableOffers: false, enablePeerswap: false, currencyUnits: ['Sats', 'BTC', 'USD'], bitcoindConfigPath: '', enableOffers: false, enablePeerswap: false,
logLevel: 'ERROR', lnServerUrl: '', swapServerUrl: '', boltzServerUrl: '', currencyUnit: 'USD' }; logLevel: 'ERROR', lnServerUrl: '', swapServerUrl: '', boltzServerUrl: '', currencyUnit: 'USD', blockExplorerUrl: 'https://mempool.space' };
const initNodeAuthentication: Authentication = { configPath: '', swapMacaroonPath: '', boltzMacaroonPath: '' }; const initNodeAuthentication: Authentication = { configPath: '', swapMacaroonPath: '', boltzMacaroonPath: '' };
export const initRootState: RootState = { export const initRootState: RootState = {

Loading…
Cancel
Save