Release 0.10.2 (#666)

High CPU usage by browser when session inactivity dialog is showing #624
Block Altcoins #627
Remove slide right animation on route change #642
Update the initiator field for Loop APIs #643
Filter Bug fix #623
Transaction id for pending waiting channel #603
Empty cookie security risk bug fix #610
Material container repositions on Mac Firefox #268 & #619 
Mask config file passwords #636
Downloaded all channels backup fails to restore #614
CLT Routing list disappears on navigation #652
Update Bump Fee modal #628
LND Paying zero amount invoice fails #657
Open channel fails after adding peer with uri #662
Update Fee Policy Bug Fix #659
Changed default password from `changeme` to `password` (#653) (Contributed By: Andrew Leschinsky <andrew@leschinsky.com>)
pull/671/head v0.10.2
ShahanaFarooqui 3 years ago committed by GitHub
parent de0e8294b1
commit e4d6256803
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
!function(e){function r(r){for(var n,a,c=r[0],i=r[1],f=r[2],p=0,s=[];p<c.length;p++)a=c[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,c=1;c<t.length;c++)0!==o[t[c]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise(function(r,n){t=o[e]=[r,n]});r.push(t[2]=n);var u,c=document.createElement("script");c.charset="utf-8",c.timeout=120,a.nc&&c.setAttribute("nonce",a.nc),c.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"731a8de203edc88f38d8",5:"3cc9f14aefc4012c6f28",6:"d59c34ac7722c1fea6aa",7:"3f5e1768ebd105934cfb"}[e]+".js"}(e);var i=new Error;u=function(r){c.onerror=c.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;i.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",i.name="ChunkLoadError",i.type=n,i.request=u,t[1](i)}o[e]=void 0}};var f=setTimeout(function(){u({type:"timeout",target:c})},12e4);c.onerror=c.onload=u,document.head.appendChild(c)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var c=window.webpackJsonp=window.webpackJsonp||[],i=c.push.bind(c);c.push=r,c=c.slice();for(var f=0;f<c.length;f++)r(c[f]);var l=i;t()}([]);

@ -0,0 +1 @@
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],l=r[2],p=0,s=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,l||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise(function(r,n){t=o[e]=[r,n]});r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"237c2154eb3e4109a251",5:"25446aaee9f74a416633",6:"eee0e0f329ec52d3bce7",7:"e4068d65b9329bce7749"}[e]+".js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(l);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var l=setTimeout(function(){u({type:"timeout",target:i})},12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var l=0;l<i.length;l++)r(i[l]);var f=c;t()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -194,7 +194,7 @@ common.sortAscByKey = (array, key) => {
common.sortDescByKey = (array, key) => { common.sortDescByKey = (array, key) => {
const temp = array.sort(function (a, b) { const temp = array.sort(function (a, b) {
var x = +a[key]; var y = +b[key]; var x = +a[key] ? +a[key] : 0; var y = +b[key] ? +b[key] : 0;
return (x > y) ? -1 : ((x < y) ? 1 : 0); return (x > y) ? -1 : ((x < y) ? 1 : 0);
}); });
return temp; return temp;

@ -96,7 +96,7 @@ exports.connectPeer = (req, res, next) => {
peer.alias = foundPeer ? foundPeer.alias : peer.nodeId.substring(0, 20); peer.alias = foundPeer ? foundPeer.alias : peer.nodeId.substring(0, 20);
}); });
let peers = (body) ? common.sortDescByStrKey(body, 'alias') : []; let peers = (body) ? common.sortDescByStrKey(body, 'alias') : [];
peers = common.newestOnTop(peers, 'nodeId', req.query.nodeId ? req.query.nodeId : ''); peers = common.newestOnTop(peers, 'nodeId', req.query.nodeId ? req.query.nodeId : req.query.uri ? req.query.uri.substring(0, req.query.uri.indexOf('@')) : '');
logger.info({fileName: 'Peers', msg: 'Peer with Newest On Top: ' + JSON.stringify(peers)}); logger.info({fileName: 'Peers', msg: 'Peer with Newest On Top: ' + JSON.stringify(peers)});
logger.info({fileName: 'Peers', msg: 'Peer Added Successfully'}); logger.info({fileName: 'Peers', msg: 'Peer Added Successfully'});
res.status(201).json(peers); res.status(201).json(peers);

@ -235,17 +235,9 @@ exports.postChannel = (req, res, next) => {
exports.postTransactions = (req, res, next) => { exports.postTransactions = (req, res, next) => {
options = common.getOptions(); options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/v1/channels/transactions'; options.url = common.getSelLNServerUrl() + '/v1/channels/transactions';
if(req.body.paymentReq) { options.form = { payment_request: req.body.paymentReq };
options.form = { if(req.body.paymentAmount) {
payment_request: req.body.paymentReq options.form.amt = req.body.paymentAmount;
};
} else if(req.body.paymentDecoded) {
options.form = {
payment_hash_string: req.body.paymentDecoded.payment_hash,
final_cltv_delta: parseInt(req.body.paymentDecoded.cltv_expiry),
amt: req.body.paymentDecoded.num_satoshis,
dest_string: req.body.paymentDecoded.destination
};
} }
if (req.body.feeLimit) { options.form.fee_limit = req.body.feeLimit; } if (req.body.feeLimit) { options.form.fee_limit = req.body.feeLimit; }
if (req.body.outgoingChannel) { options.form.outgoing_chan_id = req.body.outgoingChannel; } if (req.body.outgoingChannel) { options.form.outgoing_chan_id = req.body.outgoingChannel; }

@ -13,7 +13,7 @@ function getFilesList(callback) {
if( files && files.length > 0) { if( files && files.length > 0) {
files.forEach(file => { files.forEach(file => {
if (!file.includes('.restored')) { if (!file.includes('.restored')) {
if (file === 'channel-all.bak') { if (file.toLowerCase() === 'channel-all.bak' || file.toLowerCase() === 'backup-channel-all.bak') {
all_restore_exists = true; all_restore_exists = true;
} else { } else {
files_list.push({channel_point: file.substring(8, file.length - 4).replace('-', ':')}); files_list.push({channel_point: file.substring(8, file.length - 4).replace('-', ':')});
@ -159,10 +159,19 @@ exports.postRestore = (req, res, next) => {
let restore_backup = ''; let restore_backup = '';
if (req.params.channelPoint === 'ALL') { if (req.params.channelPoint === 'ALL') {
message = 'All Channels Restore Successful.'; message = 'All Channels Restore Successful.';
channel_restore_file = common.selectedNode.channel_backup_path + common.path_separator + 'restore' + common.path_separator + 'channel-all.bak'; channel_restore_file = common.selectedNode.channel_backup_path + common.path_separator + 'restore' + common.path_separator;
let exists = fs.existsSync(channel_restore_file); let exists = fs.existsSync(channel_restore_file + 'channel-all.bak');
let downloaded_exists = fs.existsSync(channel_restore_file + 'backup-channel-all.bak');
if (exists) { if (exists) {
restore_backup = fs.readFileSync(channel_restore_file, 'utf-8'); restore_backup = fs.readFileSync(channel_restore_file + 'channel-all.bak', 'utf-8');
if (restore_backup !== '') {
restore_backup = JSON.parse(restore_backup);
options.form = JSON.stringify({multi_chan_backup: restore_backup.multi_chan_backup.multi_chan_backup});
} else {
res.status(404).json({ message: 'Channels backup to restore does not Exist!' });
}
} else if (downloaded_exists) {
restore_backup = fs.readFileSync(channel_restore_file + 'backup-channel-all.bak', 'utf-8');
if (restore_backup !== '') { if (restore_backup !== '') {
restore_backup = JSON.parse(restore_backup); restore_backup = JSON.parse(restore_backup);
options.form = JSON.stringify({multi_chan_backup: restore_backup.multi_chan_backup.multi_chan_backup}); options.form = JSON.stringify({multi_chan_backup: restore_backup.multi_chan_backup.multi_chan_backup});

@ -165,7 +165,7 @@ exports.getConfig = (req, res, next) => {
logger.info({fileName: 'RTLConf', msg: 'Node Type: ' + req.params.nodeType + ', File Path: ' + confFile}); logger.info({fileName: 'RTLConf', msg: 'Node Type: ' + req.params.nodeType + ', File Path: ' + confFile});
fs.readFile(confFile, 'utf8', function(err, data) { fs.readFile(confFile, 'utf8', function(err, data) {
if (err) { if (err) {
logger.error({fileName: 'Conf', lineNum: 171, msg: 'Reading Conf Failed!'}); logger.error({fileName: 'Conf', lineNum: 168, msg: 'Reading Conf Failed!'});
res.status(500).json({ res.status(500).json({
message: "Reading Config File Failed!", message: "Reading Config File Failed!",
error: err error: err
@ -175,45 +175,14 @@ exports.getConfig = (req, res, next) => {
if (fileFormat === 'JSON') { if (fileFormat === 'JSON') {
jsonConfig = JSON.parse(data); jsonConfig = JSON.parse(data);
} else { } else {
fileFormat = 'INI';
jsonConfig = ini.parse(data); jsonConfig = ini.parse(data);
switch (common.selectedNode.ln_implementation) { if (common.selectedNode.ln_implementation === 'ECL' && !jsonConfig['eclair.api.password']) {
case 'ECL': fileFormat = 'HOCON';
if (jsonConfig['eclair.api.password']) { jsonConfig = parseHocon(data);
if (jsonConfig['eclair.api.password']) {
jsonConfig['eclair.api.password'] = jsonConfig['eclair.api.password'].replace(/./g, '*');
}
if (jsonConfig['eclair.bitcoind.rpcpassword']) {
jsonConfig['eclair.bitcoind.rpcpassword'] = jsonConfig['eclair.bitcoind.rpcpassword'].replace(/./g, '*');
}
} else {
fileFormat = 'HOCON';
jsonConfig = parseHocon(data);
if (jsonConfig.eclair && jsonConfig.eclair.api && jsonConfig.eclair.api.password) {
jsonConfig.eclair.api.password = jsonConfig.eclair.api.password.replace(/./g, '*');
}
if (jsonConfig.eclair && jsonConfig.eclair.bitcoind && jsonConfig.eclair.bitcoind.rpcpassword) {
jsonConfig.eclair.bitcoind.rpcpassword = jsonConfig.eclair.bitcoind.rpcpassword.replace(/./g, '*');
}
}
break;
default:
fileFormat = 'INI';
break;
} }
} }
if (jsonConfig.Bitcoind && jsonConfig.Bitcoind['bitcoind.rpcpass']) { jsonConfig = maskPasswords(jsonConfig);
jsonConfig.Bitcoind['bitcoind.rpcpass'] = jsonConfig.Bitcoind['bitcoind.rpcpass'].replace(/./g, '*');
}
if (jsonConfig['bitcoind.rpcpass']) {
jsonConfig['bitcoind.rpcpass'] = jsonConfig['bitcoind.rpcpass'].replace(/./g, '*');
}
if (jsonConfig['rpcpassword']) {
jsonConfig['rpcpassword'] = jsonConfig['rpcpassword'].replace(/./g, '*');
}
if (jsonConfig.multiPass) {
jsonConfig.multiPass = jsonConfig.multiPass.replace(/./g, '*');
}
const responseJSON = (fileFormat === 'JSON') ? jsonConfig : ini.stringify(jsonConfig); const responseJSON = (fileFormat === 'JSON') ? jsonConfig : ini.stringify(jsonConfig);
res.status(200).json({format: fileFormat, data: responseJSON}); res.status(200).json({format: fileFormat, data: responseJSON});
} }
@ -335,3 +304,22 @@ exports.updateServiceSettings = (req, res, next) => {
}); });
} }
}; };
var maskPasswords = function(obj) {
var keys = Object.keys(obj);
var length = keys.length;
if (length !== 0) {
for (var 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].toLowerCase().includes('multipass')
|| keys[i].toLowerCase().includes('rpcpass') || keys[i].toLowerCase().includes('rpcpassword'))
) {
obj[keys[i]] = obj[keys[i]].replace(/./g, '*');
}
}
}
return obj;
};

@ -50,7 +50,7 @@ exports.authenticateUser = (req, res, next) => {
if(+common.rtl_sso) { if(+common.rtl_sso) {
if(req.body.authenticateWith === 'JWT' && jwt.verify(req.body.authenticationValue, common.secret_key)) { if(req.body.authenticateWith === 'JWT' && jwt.verify(req.body.authenticationValue, common.secret_key)) {
res.status(200).json({ token: token }); res.status(200).json({ token: token });
} else if (req.body.authenticateWith === 'PASSWORD' && crypto.createHash('sha256').update(common.cookie).digest('hex') === req.body.authenticationValue) { } else if (req.body.authenticateWith === 'PASSWORD' && common.cookie.trim().length >= 32 && crypto.timingSafeEqual(Buffer.from(crypto.createHash('sha256').update(common.cookie).digest('hex'), 'utf-8'), Buffer.from(req.body.authenticationValue, 'utf-8'))) {
connect.refreshCookie(common.rtl_cookie_path); connect.refreshCookie(common.rtl_cookie_path);
const token = jwt.sign( const token = jwt.sign(
{ user: 'SSO_USER', configPath: common.nodes[0].config_path, macaroonPath: common.nodes[0].macaroon_path }, { user: 'SSO_USER', configPath: common.nodes[0].config_path, macaroonPath: common.nodes[0].macaroon_path },
@ -58,10 +58,10 @@ exports.authenticateUser = (req, res, next) => {
); );
res.status(200).json({ token: token }); res.status(200).json({ token: token });
} else { } else {
logger.error({fileName: 'Authenticate', lineNum: 20, msg: 'SSO Authentication Failed!'}); logger.error({fileName: 'Authenticate', lineNum: 61, msg: 'SSO Authentication Failed! Access key too short or does not match.'});
res.status(406).json({ res.status(406).json({
message: "Login Failure!", message: "SSO Authentication Failed!",
error: "SSO Authentication Failed!" error: "SSO failed. Access key too short or does not match."
}); });
} }
} else { } else {
@ -72,7 +72,7 @@ exports.authenticateUser = (req, res, next) => {
if (common.rtl_pass === password && failed.count < ALLOWED_LOGIN_ATTEMPTS) { if (common.rtl_pass === password && failed.count < ALLOWED_LOGIN_ATTEMPTS) {
if (req.body.twoFAToken && req.body.twoFAToken !== '') { if (req.body.twoFAToken && req.body.twoFAToken !== '') {
if (!this.verifyToken(req.body.twoFAToken)) { if (!this.verifyToken(req.body.twoFAToken)) {
logger.error({fileName: 'Authenticate', lineNum: 61, msg: 'Invalid Token! Failed IP ' + reqIP}); logger.error({fileName: 'Authenticate', lineNum: 75, msg: 'Invalid Token! Failed IP ' + reqIP});
failed.count = failed.count + 1; failed.count = failed.count + 1;
failed.lastTried = currentTime; failed.lastTried = currentTime;
return res.status(401).json(handleError(failed, currentTime, 'Invalid 2FA Token!')); return res.status(401).json(handleError(failed, currentTime, 'Invalid 2FA Token!'));
@ -86,7 +86,7 @@ exports.authenticateUser = (req, res, next) => {
); );
res.status(200).json({ token: token }); res.status(200).json({ token: token });
} else { } else {
logger.error({fileName: 'Authenticate', lineNum: 85, msg: 'Invalid Password! Failed IP ' + reqIP}); logger.error({fileName: 'Authenticate', lineNum: 89, msg: 'Invalid Password! Failed IP ' + reqIP});
failed.count = common.rtl_pass !== password ? (failed.count + 1) : failed.count; failed.count = common.rtl_pass !== password ? (failed.count + 1) : failed.count;
failed.lastTried = common.rtl_pass !== password ? currentTime : failed.lastTried; failed.lastTried = common.rtl_pass !== password ? currentTime : failed.lastTried;
return res.status(401).json(handleError(failed, currentTime, 'Invalid Password!')); return res.status(401).json(handleError(failed, currentTime, 'Invalid Password!'));
@ -96,7 +96,7 @@ exports.authenticateUser = (req, res, next) => {
exports.resetPassword = (req, res, next) => { exports.resetPassword = (req, res, next) => {
if(+common.rtl_sso) { if(+common.rtl_sso) {
logger.error({fileName: 'Authenticate', lineNum: 47, msg: 'Password Reset Failed!'}); logger.error({fileName: 'Authenticate', lineNum: 99, msg: 'Password Reset Failed!'});
res.status(401).json({ res.status(401).json({
message: "Password Reset Failed!", message: "Password Reset Failed!",
error: "Password cannot be reset for SSO authentication!" error: "Password cannot be reset for SSO authentication!"
@ -112,7 +112,7 @@ exports.resetPassword = (req, res, next) => {
); );
res.status(200).json({ token: token }); res.status(200).json({ token: token });
} else { } else {
logger.error({fileName: 'Authenticate', lineNum: 63, msg: 'Password Reset Failed!'}); logger.error({fileName: 'Authenticate', lineNum: 115, msg: 'Password Reset Failed!'});
res.status(401).json({ res.status(401).json({
message: "Password Reset Failed!", message: "Password Reset Failed!",
error: "Old password is not correct!" error: "Old password is not correct!"

@ -16,7 +16,7 @@ exports.loopOut = (req, res, next) => {
max_prepay_amt: req.body.prepayAmt, max_prepay_amt: req.body.prepayAmt,
max_swap_fee: req.body.swapFee, max_swap_fee: req.body.swapFee,
swap_publication_deadline: req.body.swapPublicationDeadline, swap_publication_deadline: req.body.swapPublicationDeadline,
label: 'RTL' initiator: 'RTL'
}; };
if (req.body.chanId !== '') { options.body['loop_out_channel'] = req.body.chanId; } if (req.body.chanId !== '') { options.body['loop_out_channel'] = req.body.chanId; }
if (req.body.destAddress !== '') { options.body['dest'] = req.body.destAddress; } if (req.body.destAddress !== '') { options.body['dest'] = req.body.destAddress; }
@ -159,7 +159,7 @@ exports.loopIn = (req, res, next) => {
amt: req.body.amount, amt: req.body.amount,
max_swap_fee: req.body.swapFee, max_swap_fee: req.body.swapFee,
max_miner_fee: req.body.minerFee, max_miner_fee: req.body.minerFee,
label: 'RTL' initiator: 'RTL'
}; };
logger.info({fileName: 'Loop', msg: 'Loop In Body: ' + JSON.stringify(options.body)}); logger.info({fileName: 'Loop', msg: 'Loop In Body: ' + JSON.stringify(options.body)});
request.post(options).then(function (body) { request.post(options).then(function (body) {

@ -39,8 +39,8 @@ $ docker-compose logs bitcoind lnd rtl
Once the containers are running you can access the RTL UI at http://localhost:3000 Once the containers are running you can access the RTL UI at http://localhost:3000
- Default password is `changeme`. - Default password is `password`.
- Default host, port and password can be changed in `.env`. - Default host, port and password can be changed in `.env`.
When you are done you can destroy containers with: When you are done you can destroy containers with:
``` ```

1438
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{ {
"name": "rtl", "name": "rtl",
"version": "0.10.1-beta", "version": "0.10.2-beta",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
@ -58,7 +58,7 @@
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~0.1100.4", "@angular-devkit/build-angular": "~0.1100.4",
"@angular/cli": "~11.0.4", "@angular/cli": "^11.2.9",
"@ngrx/store-devtools": "^10.1.0", "@ngrx/store-devtools": "^10.1.0",
"@types/jasmine": "~3.6.0", "@types/jasmine": "~3.6.0",
"@types/node": "^12.19.9", "@types/node": "^12.19.9",

@ -24,7 +24,7 @@
<rtl-side-navigation (ChildNavClicked)="onNavigationClicked($event)" fxFlex="100"></rtl-side-navigation> <rtl-side-navigation (ChildNavClicked)="onNavigationClicked($event)" fxFlex="100"></rtl-side-navigation>
</mat-sidenav> </mat-sidenav>
<mat-sidenav-content [perfectScrollbar] #sideNavContent> <mat-sidenav-content [perfectScrollbar] #sideNavContent>
<div [@routeAnimation]="outlet && outlet.activatedRouteData" class="inner-sidenav-content" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch"> <div class="inner-sidenav-content" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch">
<router-outlet #outlet="outlet"></router-outlet> <router-outlet #outlet="outlet"></router-outlet>
</div> </div>
</mat-sidenav-content>> </mat-sidenav-content>>

@ -51,7 +51,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
document.getElementsByTagName('mat-sidenav-content')[0].scrollTo(0, 0); document.getElementsByTagName('mat-sidenav-content')[0].scrollTo(0, 0);
}); });
this.breakpointObserver.observe([Breakpoints.XSmall, Breakpoints.TabletPortrait, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge]) this.breakpointObserver.observe([Breakpoints.XSmall, Breakpoints.TabletPortrait, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge])
.pipe(takeUntil(this.unSubs[5])) .pipe(takeUntil(this.unSubs[0]))
.subscribe((matches) => { .subscribe((matches) => {
if(matches.breakpoints[Breakpoints.XSmall]) { if(matches.breakpoints[Breakpoints.XSmall]) {
this.commonService.setScreenSize(ScreenSizeEnum.XS); this.commonService.setScreenSize(ScreenSizeEnum.XS);
@ -73,7 +73,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
this.store.dispatch(new RTLActions.FetchRTLConfig()); this.store.dispatch(new RTLActions.FetchRTLConfig());
this.accessKey = this.readAccessKey(); this.accessKey = this.readAccessKey();
this.store.select('root') this.store.select('root')
.pipe(takeUntil(this.unSubs[0])) .pipe(takeUntil(this.unSubs[1]))
.subscribe(rtlStore => { .subscribe(rtlStore => {
this.selNode = rtlStore.selNode; this.selNode = rtlStore.selNode;
this.settings = this.selNode.settings; this.settings = this.selNode.settings;
@ -86,15 +86,20 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
this.flgLoading[0] = false; this.flgLoading[0] = false;
} else { } else {
this.flgLoggedIn = true; this.flgLoggedIn = true;
this.userIdle.startWatching();
} }
}); });
this.actions$.pipe(takeUntil(this.unSubs[1]), this.actions$.pipe(takeUntil(this.unSubs[2]),
filter((action) => action.type === RTLActions.SET_RTL_CONFIG || action.type === RTLActions.LOGOUT)) filter((action) => action.type === RTLActions.SET_RTL_CONFIG || action.type === RTLActions.LOGOUT))
.subscribe((action: (RTLActions.SetRTLConfig | RTLActions.Logout)) => { .subscribe((action: (RTLActions.SetRTLConfig | RTLActions.Logout)) => {
if (action.type === RTLActions.SET_RTL_CONFIG) { if (action.type === RTLActions.SET_RTL_CONFIG) {
if (!this.sessionService.getItem('token')) { if (!this.sessionService.getItem('token')) {
if (+action.payload.sso.rtlSSO) { if (+action.payload.sso.rtlSSO) {
this.store.dispatch(new RTLActions.Login({password: sha256(this.accessKey), defaultPassword: false})); if(!this.accessKey || this.accessKey.trim().length < 32) {
this.router.navigate(['./error'], { state: {errorCode: '406', errorMessage: 'Access key too short. It should be at least 32 characters long.'} });
} else {
this.store.dispatch(new RTLActions.Login({password: sha256(this.accessKey), defaultPassword: false}));
}
} else { } else {
this.router.navigate(['./login']); this.router.navigate(['./login']);
} }
@ -102,11 +107,13 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
} }
if (action.type === RTLActions.LOGOUT) { if (action.type === RTLActions.LOGOUT) {
this.flgLoggedIn = false; this.flgLoggedIn = false;
this.userIdle.stopWatching();
this.userIdle.stopTimer();
} }
}); });
this.userIdle.startWatching(); this.userIdle.onTimerStart().pipe(takeUntil(this.unSubs[3])).subscribe(count => {this.logger.info('Counting Down: ' + (11 - count))});
this.userIdle.onTimerStart().pipe(takeUntil(this.unSubs[2])).subscribe(count => {}); this.userIdle.onTimeout().pipe(takeUntil(this.unSubs[4])).subscribe(() => {
this.userIdle.onTimeout().pipe(takeUntil(this.unSubs[3])).subscribe(() => { this.logger.info('Time Out!');
if (this.sessionService.getItem('token')) { if (this.sessionService.getItem('token')) {
this.flgLoggedIn = false; this.flgLoggedIn = false;
this.logger.warn('Time limit exceeded for session inactivity.'); this.logger.warn('Time limit exceeded for session inactivity.');
@ -117,14 +124,13 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
titleMessage: 'Time limit exceeded for session inactivity.' titleMessage: 'Time limit exceeded for session inactivity.'
}})); }}));
this.store.dispatch(new RTLActions.Logout()); this.store.dispatch(new RTLActions.Logout());
this.userIdle.resetTimer();
} }
}); });
} }
private readAccessKey() { private readAccessKey() {
const url = window.location.href; const url = window.location.href;
return url.includes('access-key=') ? url.substring(url.lastIndexOf('access-key=') + 11).trim() : ''; return url.includes('access-key=') ? url.substring(url.lastIndexOf('access-key=') + 11).trim() : null;
} }
ngAfterViewInit() { ngAfterViewInit() {

@ -36,7 +36,7 @@ import { LayoutModule } from '@angular/cdk/layout';
routing, routing,
LayoutModule, LayoutModule,
HammerModule, HammerModule,
UserIdleModule.forRoot({idle: 60 * 60, timeout: 1}), UserIdleModule.forRoot({idle: 3590, timeout: 10, ping: 12000}), // One hour
StoreModule.forRoot(RTLReducer, { StoreModule.forRoot(RTLReducer, {
runtimeChecks: { runtimeChecks: {
strictStateImmutability: false, strictStateImmutability: false,

@ -1,4 +1,4 @@
<div [@routeAnimation]="outlet && outlet.activatedRouteData" class="inner-sidenav-content" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch"> <div class="inner-sidenav-content" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch">
<mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar>
<router-outlet #outlet="outlet"></router-outlet> <router-outlet #outlet="outlet"></router-outlet>
</div> </div>

@ -30,7 +30,7 @@
</div> </div>
</div> </div>
<ng-template #noChannelBlock> <ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1"> <div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1 w-100">
No channels available. No channels available.
<button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button> <button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div> </div>

@ -1,4 +1,4 @@
<div fxLayout="column" class="padding-gap-x-large"> <div fxLayout="column" class="padding-gap-x">
<div fxLayout="row" fxLayoutAlign="space-between end" fxLayoutAlign.gt-sm="start end"> <div fxLayout="row" fxLayoutAlign="space-between end" fxLayoutAlign.gt-sm="start end">
<mat-form-field fxFlex="48" fxFlex.gt-md="25" fxLayoutAlign="start end" class="mr-2"> <mat-form-field fxFlex="48" fxFlex.gt-md="25" fxLayoutAlign="start end" class="mr-2">
<mat-select [(ngModel)]="selectedAddressType" placeholder="Address Type" name="address_type" tabindex="1"> <mat-select [(ngModel)]="selectedAddressType" placeholder="Address Type" name="address_type" tabindex="1">

@ -1,13 +1,13 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">{{sweepAll ? 'Sweep All Funds' : 'Send Funds'}}</span> <span class="page-title">{{sweepAll ? 'Sweep All Funds' : 'Send Funds'}}</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="row wrap" fxLayoutAlign="space-between start" fxFlex="100" *ngIf="!sweepAll; else sweepAllBlock;" class="padding-gap overflow-x-hidden" (submit)="onSendFunds()" (reset)="resetData()" #form="ngForm"> <form fxLayout="row wrap" fxLayoutAlign="space-between start" fxFlex="100" *ngIf="!sweepAll; else sweepAllBlock;" class="overflow-x-hidden" (submit)="onSendFunds()" (reset)="resetData()" #form="ngForm">
<mat-form-field fxFlex="55"> <mat-form-field fxFlex="55">
<input matInput autoFocus [(ngModel)]="transaction.address" placeholder="Bitcoin Address" tabindex="1" name="address" required #address="ngModel"> <input matInput autoFocus [(ngModel)]="transaction.address" placeholder="Bitcoin Address" tabindex="1" name="address" required #address="ngModel">
<mat-error *ngIf="!transaction.address">Bitcoin address is required.</mat-error> <mat-error *ngIf="!transaction.address">Bitcoin address is required.</mat-error>

@ -1,4 +1,4 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap-x-large"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap-x">
<div fxLayout="row"> <div fxLayout="row">
<button mat-flat-button color="primary" type="button" tabindex="1" (click)="openSendFundsModal()">{{sweepAll ? 'Sweep All' : 'Send Funds'}}</button> <button mat-flat-button color="primary" type="button" tabindex="1" (click)="openSendFundsModal()">{{sweepAll ? 'Sweep All' : 'Send Funds'}}</button>
</div> </div>

@ -62,10 +62,9 @@
</ng-container> </ng-container>
<tr mat-footer-row *matFooterRowDef="['no_utxo']" [ngClass]="{'display-none': listUTXOs?.data && listUTXOs?.data?.length>0}"></tr> <tr mat-footer-row *matFooterRowDef="['no_utxo']" [ngClass]="{'display-none': listUTXOs?.data && listUTXOs?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<!-- <tr mat-row *matRowDef="let row; columns: displayedColumns;" [ngClass]="{'alert alert-warn': !isDustUTXO && row.value < 10000}"></tr> -->
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>
</div> </div>

@ -1,4 +1,4 @@
import { Component, ViewChild, Input, OnChanges } from '@angular/core'; import { Component, ViewChild, Input, OnChanges, AfterViewInit } from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects'; import { Actions } from '@ngrx/effects';
@ -21,7 +21,7 @@ import * as fromRTLReducer from '../../../../store/rtl.reducers';
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('UTXOs') } { provide: MatPaginatorIntl, useValue: getPaginatorLabel('UTXOs') }
] ]
}) })
export class CLOnChainUtxosComponent implements OnChanges { export class CLOnChainUtxosComponent implements OnChanges, AfterViewInit {
@ViewChild(MatSort, { static: false }) sort: MatSort|undefined; @ViewChild(MatSort, { static: false }) sort: MatSort|undefined;
@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator|undefined; @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator|undefined;
@Input() numDustUTXOs = 0; @Input() numDustUTXOs = 0;
@ -53,6 +53,12 @@ export class CLOnChainUtxosComponent implements OnChanges {
} }
} }
ngAfterViewInit() {
if (this.utxos && this.utxos.length > 0 && this.sort && this.paginator) {
this.loadUTXOsTable(this.utxos);
}
}
ngOnChanges() { ngOnChanges() {
if (this.utxos && this.utxos.length > 0) { if (this.utxos && this.utxos.length > 0) {
this.loadUTXOsTable(this.utxos); this.loadUTXOsTable(this.utxos);
@ -81,8 +87,8 @@ export class CLOnChainUtxosComponent implements OnChanges {
loadUTXOsTable(utxos: any[]) { loadUTXOsTable(utxos: any[]) {
this.listUTXOs = new MatTableDataSource<UTXO>([...utxos]); this.listUTXOs = new MatTableDataSource<UTXO>([...utxos]);
this.listUTXOs.sort = this.sort;
this.listUTXOs.sortingDataAccessor = (data: any, sortHeaderId: string) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null; this.listUTXOs.sortingDataAccessor = (data: any, sortHeaderId: string) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;
this.listUTXOs.sort = this.sort;
this.listUTXOs.filterPredicate = (utxo: UTXO, fltr: string) => JSON.stringify(utxo).toLowerCase().includes(fltr); this.listUTXOs.filterPredicate = (utxo: UTXO, fltr: string) => JSON.stringify(utxo).toLowerCase().includes(fltr);
this.listUTXOs.paginator = this.paginator; this.listUTXOs.paginator = this.paginator;
this.logger.info(this.listUTXOs); this.logger.info(this.listUTXOs);

@ -1,13 +1,13 @@
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="space-between stretch"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="space-between stretch">
<div fxFlex="100" class="padding-gap-large pl-3"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header mb-1"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Channel Information</span> <span class="page-title">Channel Information</span>
</div> </div>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}"> <mat-card-content class="padding-gap-x-large" [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}">
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="50"> <div fxFlex="50">
@ -71,8 +71,8 @@
<span class="overflow-wrap foreground-secondary-text">{{channel.private ? 'Yes' : 'No'}}</span> <span class="overflow-wrap foreground-secondary-text">{{channel.private ? 'Yes' : 'No'}}</span>
</div> </div>
</div> </div>
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div *ngIf="showAdvanced"> <div *ngIf="showAdvanced">
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100"> <div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">Funding Transaction Id</h4> <h4 fxLayoutAlign="start" class="font-bold-500">Funding Transaction Id</h4>

@ -1,5 +1,5 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
@ -100,5 +100,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -157,9 +157,9 @@ export class CLChannelOpenTableComponent implements OnInit, AfterViewInit, OnDes
this.clEffects.setLookupCL this.clEffects.setLookupCL
.pipe(take(1)) .pipe(take(1))
.subscribe((resLookup: ChannelEdge[]) => { .subscribe((resLookup: ChannelEdge[]) => {
if (resLookup.length > 0 && resLookup[0].destination === this.information.id) { if (resLookup.length > 0 && resLookup[0].source === this.information.id) {
this.myChanPolicy = {fee_base_msat: resLookup[0].base_fee_millisatoshi, fee_rate_milli_msat: resLookup[0].fee_per_millionth}; this.myChanPolicy = {fee_base_msat: resLookup[0].base_fee_millisatoshi, fee_rate_milli_msat: resLookup[0].fee_per_millionth};
} else if (resLookup.length > 1 && resLookup[1].destination === this.information.id) { } else if (resLookup.length > 1 && resLookup[1].source === this.information.id) {
this.myChanPolicy = {fee_base_msat: resLookup[1].base_fee_millisatoshi, fee_rate_milli_msat: resLookup[1].fee_per_millionth}; this.myChanPolicy = {fee_base_msat: resLookup[1].base_fee_millisatoshi, fee_rate_milli_msat: resLookup[1].fee_per_millionth};
} else { } else {
this.myChanPolicy = {fee_base_msat: 0, fee_rate_milli_msat: 0}; this.myChanPolicy = {fee_base_msat: 0, fee_rate_milli_msat: 0};
@ -232,10 +232,10 @@ export class CLChannelOpenTableComponent implements OnInit, AfterViewInit, OnDes
}); });
this.channels = new MatTableDataSource<Channel>([...mychannels]); this.channels = new MatTableDataSource<Channel>([...mychannels]);
this.channels.filterPredicate = (channel: Channel, fltr: string) => { this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id : '') + const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id.toLowerCase() : '') +
(channel.short_channel_id ? channel.short_channel_id : '') + (channel.id ? channel.id : '') + (channel.alias ? channel.alias : '') + (channel.short_channel_id ? channel.short_channel_id.toLowerCase() : '') + (channel.id ? channel.id.toLowerCase() : '') + (channel.alias ? channel.alias.toLowerCase() : '') +
(channel.private ? 'private' : 'public') + (channel.state ? channel.state.toLowerCase() : '') + (channel.private ? 'private' : 'public') + (channel.state ? channel.state.toLowerCase() : '') +
(channel.funding_txid ? channel.funding_txid : '') + (channel.msatoshi_to_us ? channel.msatoshi_to_us : '') + (channel.funding_txid ? channel.funding_txid.toLowerCase() : '') + (channel.msatoshi_to_us ? channel.msatoshi_to_us : '') +
(channel.msatoshi_total ? channel.msatoshi_total : '') + (channel.their_channel_reserve_satoshis ? channel.their_channel_reserve_satoshis : '') + (channel.msatoshi_total ? channel.msatoshi_total : '') + (channel.their_channel_reserve_satoshis ? channel.their_channel_reserve_satoshis : '') +
(channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : ''); (channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : '');
return newChannel.includes(fltr); return newChannel.includes(fltr);

@ -1,5 +1,5 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
@ -73,5 +73,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -79,7 +79,7 @@ export class CLChannelPendingTableComponent implements OnInit, AfterViewInit, On
} }
this.numPeers = (rtlStore.peers && rtlStore.peers.length) ? rtlStore.peers.length : 0; this.numPeers = (rtlStore.peers && rtlStore.peers.length) ? rtlStore.peers.length : 0;
this.totalBalance = rtlStore.balance.totalBalance; this.totalBalance = rtlStore.balance.totalBalance;
this.channelsData = rtlStore.allChannels.filter(channel => !(channel.state === 'CHANNELD_NORMAL' && channel.connected)); this.channelsData = this.commonService.sortByKey(rtlStore.allChannels.filter(channel => !(channel.state === 'CHANNELD_NORMAL' && channel.connected)), 'state', 'string');
if (this.channelsData.length > 0) { if (this.channelsData.length > 0) {
this.loadChannelsTable(this.channelsData); this.loadChannelsTable(this.channelsData);
} }
@ -132,10 +132,10 @@ export class CLChannelPendingTableComponent implements OnInit, AfterViewInit, On
}); });
this.channels = new MatTableDataSource<Channel>([...mychannels]); this.channels = new MatTableDataSource<Channel>([...mychannels]);
this.channels.filterPredicate = (channel: Channel, fltr: string) => { this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id : '') + const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id.toLowerCase() : '') +
(channel.short_channel_id ? channel.short_channel_id : '') + (channel.id ? channel.id : '') + (channel.alias ? channel.alias : '') + (channel.short_channel_id ? channel.short_channel_id.toLowerCase() : '') + (channel.id ? channel.id.toLowerCase() : '') + (channel.alias ? channel.alias.toLowerCase() : '') +
(channel.private ? 'private' : 'public') + (channel.state ? channel.state.toLowerCase() : '') + (channel.private ? 'private' : 'public') + (channel.state ? channel.state.toLowerCase() : '') +
(channel.funding_txid ? channel.funding_txid : '') + (channel.msatoshi_to_us ? channel.msatoshi_to_us : '') + (channel.funding_txid ? channel.funding_txid.toLowerCase() : '') + (channel.msatoshi_to_us ? channel.msatoshi_to_us : '') +
(channel.msatoshi_total ? channel.msatoshi_total : '') + (channel.their_channel_reserve_satoshis ? channel.their_channel_reserve_satoshis : '') + (channel.msatoshi_total ? channel.msatoshi_total : '') + (channel.their_channel_reserve_satoshis ? channel.their_channel_reserve_satoshis : '') +
(channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : ''); (channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : '');
return newChannel.includes(fltr); return newChannel.includes(fltr);

@ -1,8 +1,8 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap-x"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<div fxLayout="row"> <div fxLayout="row">
<button mat-flat-button color="primary" (click)="onOpenChannel()" type="submit" tabindex="1">Open Channel</button> <button mat-flat-button color="primary" (click)="onOpenChannel()" type="submit" tabindex="1">Open Channel</button>
</div> </div>
<div fxLayout="column" fxFlex="100" class="mt-2 bordered-box"> <div fxLayout="column" fxFlex="100" class="my-2 bordered-box">
<mat-tab-group [(selectedIndex)]="activeLink" (selectedTabChange)="onSelectedTabChange($event)"> <mat-tab-group [(selectedIndex)]="activeLink" (selectedTabChange)="onSelectedTabChange($event)">
<mat-tab> <mat-tab>
<ng-template mat-tab-label> <ng-template mat-tab-label>

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">{{alertTitle}}</span> <span class="page-title">{{alertTitle}}</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="column" (submit)="onOpenChannel()" (reset)="resetData()" #form="ngForm"> <form fxLayout="column" (submit)="onOpenChannel()" (reset)="resetData()" #form="ngForm">
<div fxLayout="column"> <div fxLayout="column">
<mat-form-field fxFlex="100" *ngIf="!peer && peers && peers.length > 0"> <mat-form-field fxFlex="100" *ngIf="!peer && peers && peers.length > 0">

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Connect to a new peer</span> <span class="page-title">Connect to a new peer</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<div fxLayout="column"> <div fxLayout="column">
<mat-vertical-stepper [linear]="true" #stepper (selectionChange)="stepSelectionChanged($event)"> <mat-vertical-stepper [linear]="true" #stepper (selectionChange)="stepSelectionChanged($event)">
<mat-step [stepControl]="peerFormGroup" [editable]="flgEditable"> <mat-step [stepControl]="peerFormGroup" [editable]="flgEditable">

@ -1,9 +1,9 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" #peersForm="ngForm"> <form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" #peersForm="ngForm">
<button mat-flat-button color="primary" type="submit" tabindex="1" (click)="onConnectPeer({})">Add Peer</button> <button mat-flat-button color="primary" type="submit" tabindex="1" (click)="onConnectPeer({})">Add Peer</button>
</form> </form>
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"> <div fxFlex="70">
<fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Connected Peers</span> <span class="page-title">Connected Peers</span>
@ -68,6 +68,6 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.pub_key === newlyAddedPeer && flgAnimate) ? 'added' : 'notAdded'"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.pub_key === newlyAddedPeer && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>

@ -1,6 +1,6 @@
<div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'error-border': errorMessage !== '', 'padding-gap-x': true}"> <div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'error-border': errorMessage !== '', 'padding-gap-x': true}">
<div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div> <div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target)" placeholder="Filter"> <input matInput (keyup)="applyFilter($event.target)" placeholder="Filter">
@ -69,5 +69,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -101,7 +101,7 @@ export class CLFailedTransactionsComponent implements OnInit, AfterViewInit, OnD
this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null; this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;
this.forwardingHistoryEvents.paginator = this.paginator; this.forwardingHistoryEvents.paginator = this.paginator;
this.forwardingHistoryEvents.filterPredicate = (event: ForwardingEvent, fltr: string) => { this.forwardingHistoryEvents.filterPredicate = (event: ForwardingEvent, fltr: string) => {
const newEvent = event.status + event.received_time_str + event.resolved_time_str + event.in_channel + event.out_channel + (event.in_msatoshi/1000) + (event.out_msatoshi/1000) + event.fee; const newEvent = (event.status ? event.status.toLowerCase() : '') + (event.received_time_str ? event.received_time_str.toLowerCase() : '') + (event.resolved_time_str ? event.resolved_time_str.toLowerCase() : '') + (event.in_channel ? event.in_channel.toLowerCase() : '') + (event.out_channel ? event.out_channel.toLowerCase() : '') + (event.in_msatoshi ? (event.in_msatoshi/1000) : '') + (event.out_msatoshi ? (event.out_msatoshi/1000) : '') + (event.fee ? event.fee : '');
return newEvent.includes(fltr); return newEvent.includes(fltr);
}; };
this.logger.info(this.forwardingHistoryEvents); this.logger.info(this.forwardingHistoryEvents);

@ -1,6 +1,6 @@
<div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'error-border': errorMessage !== '', 'padding-gap-x': true}"> <div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'error-border': errorMessage !== '', 'padding-gap-x': true}">
<div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div> <div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput [(ngModel)]="filterValue" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter"> <input matInput [(ngModel)]="filterValue" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
@ -69,5 +69,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -116,7 +116,7 @@ export class CLForwardingHistoryComponent implements OnInit, AfterViewInit, OnDe
this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null; this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;
this.forwardingHistoryEvents.paginator = this.paginator; this.forwardingHistoryEvents.paginator = this.paginator;
this.forwardingHistoryEvents.filterPredicate = (event: ForwardingEvent, fltr: string) => { this.forwardingHistoryEvents.filterPredicate = (event: ForwardingEvent, fltr: string) => {
const newEvent = event.received_time_str.toLowerCase() + event.resolved_time_str.toLowerCase() + event.in_channel + event.out_channel + (event.in_msatoshi/1000) + (event.out_msatoshi/1000) + event.fee; const newEvent = (event.received_time_str ? event.received_time_str.toLowerCase() : '') + (event.resolved_time_str ? event.resolved_time_str.toLowerCase() : '') + (event.in_channel ? event.in_channel.toLowerCase() : '') + (event.out_channel ? event.out_channel.toLowerCase() : '') + (event.in_msatoshi ? (event.in_msatoshi/1000) : '') + (event.out_msatoshi ? (event.out_msatoshi/1000) : '') + (event.fee ? event.fee : '');
return newEvent.includes(fltr); return newEvent.includes(fltr);
}; };
this.logger.info(this.forwardingHistoryEvents); this.logger.info(this.forwardingHistoryEvents);

@ -5,10 +5,8 @@ import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { faMapSigns } from '@fortawesome/free-solid-svg-icons'; import { faMapSigns } from '@fortawesome/free-solid-svg-icons';
import * as CLActions from '../store/cl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers'; import * as fromRTLReducer from '../../store/rtl.reducers';
@Component({ @Component({
selector: 'rtl-cl-routing', selector: 'rtl-cl-routing',
templateUrl: './routing.component.html', templateUrl: './routing.component.html',
@ -33,7 +31,6 @@ export class CLRoutingComponent implements OnInit, OnDestroy {
} }
ngOnDestroy() { ngOnDestroy() {
this.store.dispatch(new CLActions.SetForwardingHistory({}));
this.unSubs.forEach(completeSub => { this.unSubs.forEach(completeSub => {
completeSub.next(); completeSub.next();
completeSub.complete(); completeSub.complete();

@ -19,6 +19,7 @@ import * as fromRTLReducer from '../../store/rtl.reducers';
import * as RTLActions from '../../store/rtl.actions'; import * as RTLActions from '../../store/rtl.actions';
import * as CLActions from './cl.actions'; import * as CLActions from './cl.actions';
import * as fromCLReducers from '../store/cl.reducers'; import * as fromCLReducers from '../store/cl.reducers';
import { AlertTypeEnum, CurrencyUnitEnum } from '../../shared/services/consts-enums-functions';
@Injectable() @Injectable()
export class CLEffects implements OnDestroy { export class CLEffects implements OnDestroy {
@ -55,11 +56,25 @@ export class CLEffects implements OnDestroy {
takeUntil(this.actions$.pipe(ofType(RTLActions.SET_SELECTED_NODE))), takeUntil(this.actions$.pipe(ofType(RTLActions.SET_SELECTED_NODE))),
map((info) => { map((info) => {
this.logger.info(info); this.logger.info(info);
this.initializeRemainingData(info, action.payload.loadPage); if (info.chains && info.chains.length && info.chains[0]
return { && (typeof info.chains[0] === 'object' && info.chains[0].hasOwnProperty('chain') && info.chains[0].chain.toLowerCase().indexOf('bitcoin') < 0)
type: CLActions.SET_INFO_CL, ) {
payload: info ? info : {} this.store.dispatch(new RTLActions.CloseAllDialogs());
}; this.store.dispatch(new RTLActions.OpenAlert({ data: {
type: AlertTypeEnum.ERROR,
alertTitle: 'Shitcoin Found',
titleMessage: 'Sorry Not Sorry, RTL is Bitcoin Only!'
}}));
return {
type: RTLActions.LOGOUT
};
} else {
this.initializeRemainingData(info, action.payload.loadPage);
return {
type: CLActions.SET_INFO_CL,
payload: info ? info : {}
};
}
}), }),
catchError((err) => { catchError((err) => {
const code = (err.error && err.error.error && err.error.error.message && err.error.error.message.code) ? err.error.error.message.code : (err.error && err.error.error && err.error.error.code) ? err.error.error.code : err.status ? err.status : ''; const code = (err.error && err.error.error && err.error.error.message && err.error.error.message.code) ? err.error.error.message.code : (err.error && err.error.error && err.error.error.code) ? err.error.error.code : err.status ? err.status : '';
@ -310,9 +325,9 @@ export class CLEffects implements OnDestroy {
this.logger.info(postRes); this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner()); this.store.dispatch(new RTLActions.CloseSpinner());
if(action.payload.channelId === 'all') { if(action.payload.channelId === 'all') {
this.store.dispatch(new RTLActions.OpenSnackBar('All Channels Updated Successfully.')); this.store.dispatch(new RTLActions.OpenSnackBar({message:'All Channels Updated Successfully. Fee policy updates may take some time to reflect on the channel.', duration: 5000}));
} else { } else {
this.store.dispatch(new RTLActions.OpenSnackBar('Channel Updated Successfully!')); this.store.dispatch(new RTLActions.OpenSnackBar({message:'Channel Updated Successfully. Fee policy updates may take some time to reflect on the channel.', duration: 5000}));
} }
return { return {
type: CLActions.FETCH_CHANNELS_CL type: CLActions.FETCH_CHANNELS_CL
@ -724,13 +739,13 @@ export class CLEffects implements OnDestroy {
const node_data = { const node_data = {
identity_pubkey: info.id, identity_pubkey: info.id,
alias: info.alias, alias: info.alias,
testnet: (info.network === 'testnet' || info.network === 'litecoin-testnet') ? true : false, testnet: (info.network.toLowerCase() === 'testnet') ? true : false,
chains: info.chains, chains: info.chains,
uris: info.uris, uris: info.uris,
version: info.version, version: info.version,
api_version: info.api_version, api_version: info.api_version,
currency_unit: 'BTC', currency_unit: CurrencyUnitEnum.BTC,
smaller_currency_unit: 'Sats', smaller_currency_unit: CurrencyUnitEnum.SATS,
numberOfPendingChannels: info.num_pending_channels numberOfPendingChannels: info.num_pending_channels
}; };
this.store.dispatch(new RTLActions.OpenSpinner('Initializing Node Data...')); this.store.dispatch(new RTLActions.OpenSpinner('Initializing Node Data...'));

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Create Invoice</span> <span class="page-title">Create Invoice</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="row wrap" fxLayoutAlign="start space-between" fxFlex="100" #addInvoiceForm="ngForm"> <form fxLayout="row wrap" fxLayoutAlign="start space-between" fxFlex="100" #addInvoiceForm="ngForm">
<mat-form-field fxFlex="100" fxLayoutAlign="start end"> <mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput autoFocus [(ngModel)]="description" placeholder="Description" tabindex="2" name="description"> <input matInput autoFocus [(ngModel)]="description" placeholder="Description" tabindex="2" name="description">
@ -34,7 +34,7 @@
<fa-icon [icon]="faExclamationTriangle" class="mr-1 alert-icon"></fa-icon> <fa-icon [icon]="faExclamationTriangle" class="mr-1 alert-icon"></fa-icon>
<span *ngIf="invoiceError !== ''">{{invoiceError}}</span> <span *ngIf="invoiceError !== ''">{{invoiceError}}</span>
</div> </div>
<div fxLayout="row" fxFlex="100" class="mt-2" fxLayoutAlign="end center"> <div fxLayout="row" fxFlex="100" class="mt-1" fxLayoutAlign="end center">
<button class="mr-1" mat-stroked-button color="primary" tabindex="7" type="reset" (click)="resetData()">Clear Field</button> <button class="mr-1" mat-stroked-button color="primary" tabindex="7" type="reset" (click)="resetData()">Clear Field</button>
<button mat-flat-button color="primary" (click)="onAddInvoice(addInvoiceForm)" tabindex="8">Create Invoice</button> <button mat-flat-button color="primary" (click)="onAddInvoice(addInvoiceForm)" tabindex="8">Create Invoice</button>
</div> </div>

@ -2,15 +2,15 @@
<div fxFlex="35" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap-large" [ngClass]="{'display-none': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}"> <div fxFlex="35" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap-large" [ngClass]="{'display-none': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}">
<qrcode [qrdata]="invoice.bolt11" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode> <qrcode [qrdata]="invoice.bolt11" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode>
</div> </div>
<div fxFlex="65" class="padding-gap-large"> <div fxFlex="65">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header mb-1"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">{{screenSize === screenSizeEnum.XS ? (newlyAdded ? 'Created' : 'Invoice') : (newlyAdded ? 'Invoice Created' : 'Invoice Information')}}</span> <span class="page-title">{{screenSize === screenSizeEnum.XS ? (newlyAdded ? 'Created' : 'Invoice') : (newlyAdded ? 'Invoice Created' : 'Invoice Information')}}</span>
</div> </div>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}"> <mat-card-content class="padding-gap-x-large" [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}">
<div fxLayout="column"> <div fxLayout="column">
<div fxFlex="30" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap" [ngClass]="{'display-none': screenSize !== screenSizeEnum.XS && screenSize !== screenSizeEnum.SM}"> <div fxFlex="30" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap" [ngClass]="{'display-none': screenSize !== screenSizeEnum.XS && screenSize !== screenSizeEnum.SM}">
<qrcode [qrdata]="invoice.bolt11" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode> <qrcode [qrdata]="invoice.bolt11" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode>

@ -81,6 +81,6 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.label == newlyAddedInvoiceMemo && row.value == newlyAddedInvoiceValue && flgAnimate) ? 'added' : 'notAdded'"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.label == newlyAddedInvoiceMemo && row.value == newlyAddedInvoiceValue && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>

@ -135,6 +135,6 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns; when: !is_group;" [@newlyAddedRowAnimation]="(row.payment_hash === newlyAddedPayment && flgAnimate) ? 'added' : 'notAdded'"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns; when: !is_group;" [@newlyAddedRowAnimation]="(row.payment_hash === newlyAddedPayment && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>

@ -17,7 +17,7 @@
<button mat-flat-button color="primary" type="submit" tabindex="4">Query Route</button> <button mat-flat-button color="primary" type="submit" tabindex="4">Query Route</button>
</div> </div>
</form> </form>
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-2 mb-1"> <div fxLayout="row" fxLayoutAlign="start center" class="page-sub-title-container mt-2 mb-1">
<div fxFlex="70"> <div fxFlex="70">
<fa-icon [icon]="faRoute" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faRoute" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Transaction Route</span> <span class="page-title">Transaction Route</span>

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Send Payment</span> <span class="page-title">Send Payment</span>
</div> </div>
<button tabindex="12" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button> <button tabindex="12" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px" fxLayout="column" fxLayoutAlign="start stretch"> <mat-card-content class="padding-gap-x-large" fxLayout="column" fxLayoutAlign="start stretch">
<mat-radio-group *ngIf="isCompatibleVersion" class="my-1" color="primary" name="paymentType" [(ngModel)]="paymentType" (change)="onPaymentTypeChange()" fxFlex="100" fxLayoutAlign="start stretch"> <mat-radio-group *ngIf="isCompatibleVersion" class="my-1" color="primary" name="paymentType" [(ngModel)]="paymentType" (change)="onPaymentTypeChange()" fxFlex="100" fxLayoutAlign="start stretch">
<mat-radio-button fxFlex="25" tabindex="1" value="invoice" class="mr-2">Invoice Payment</mat-radio-button> <mat-radio-button fxFlex="25" tabindex="1" value="invoice" class="mr-2">Invoice Payment</mat-radio-button>
<mat-radio-button fxFlex="25" tabindex="2" value="keysend">Keysend Payment</mat-radio-button> <mat-radio-button fxFlex="25" tabindex="2" value="keysend">Keysend Payment</mat-radio-button>

@ -1,4 +1,4 @@
<div [@routeAnimation]="outlet && outlet.activatedRouteData" class="inner-sidenav-content" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch"> <div class="inner-sidenav-content" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch">
<mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar>
<router-outlet #outlet="outlet"></router-outlet> <router-outlet #outlet="outlet"></router-outlet>
</div> </div>

@ -30,7 +30,7 @@
</div> </div>
</div> </div>
<ng-template #noChannelBlock> <ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1"> <div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1 w-100">
No channels available. No channels available.
<button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button> <button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div> </div>

@ -1,5 +1,5 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap-x-large"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<div fxLayout="row" class="mt-1"> <div fxLayout="row">
<button mat-flat-button color="primary" (click)="onGenerateAddress()" tabindex="1" class="top-minus-15px">Generate Address</button> <button mat-flat-button color="primary" (click)="onGenerateAddress()" tabindex="1">Generate Address</button>
</div> </div>
</div> </div>

@ -1,13 +1,13 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Send Payment</span> <span class="page-title">Send Payment</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="row wrap" fxFlex="100" fxLayoutAlign="space-between start" class="padding-gap overflow-x-hidden" (submit)="onSendFunds()" (reset)="resetData()" #form="ngForm"> <form fxLayout="row wrap" fxFlex="100" fxLayoutAlign="space-between start" class="overflow-x-hidden" (submit)="onSendFunds()" (reset)="resetData()" #form="ngForm">
<mat-form-field fxFlex="55"> <mat-form-field fxFlex="55">
<input matInput autoFocus [(ngModel)]="transaction.address" placeholder="Bitcoin Address" tabindex="1" name="addr" required #addrs="ngModel"> <input matInput autoFocus [(ngModel)]="transaction.address" placeholder="Bitcoin Address" tabindex="1" name="addr" required #addrs="ngModel">
<mat-error *ngIf="!transaction.address">Bitcoin address is required.</mat-error> <mat-error *ngIf="!transaction.address">Bitcoin address is required.</mat-error>

@ -1,4 +1,4 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap-x-large"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<div fxLayout="row"> <div fxLayout="row">
<button mat-flat-button color="primary" type="button" tabindex="1" (click)="openSendFundsModal()">{{sweepAll ? 'Sweep All' : 'Send Funds'}}</button> <button mat-flat-button color="primary" type="button" tabindex="1" (click)="openSendFundsModal()">{{sweepAll ? 'Sweep All' : 'Send Funds'}}</button>
</div> </div>

@ -1,4 +1,4 @@
<div fxLayout="row wrap" fxLayoutAlign="start start" fxLayout.gt-sm="column" fxFlex="100" fxLayoutAlign.gt-sm="start stretch" class="padding-gap-x-large"> <div fxLayout="row wrap" fxLayoutAlign="start start" fxLayout.gt-sm="column" fxFlex="100" fxLayoutAlign.gt-sm="start stretch">
<div fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"> <div fxFlex="70">
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
@ -59,7 +59,7 @@
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>
</div> </div>

@ -1,13 +1,13 @@
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="space-between stretch"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="space-between stretch">
<div fxFlex="100" class="padding-gap-large pl-3"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header mb-1"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Channel Information</span> <span class="page-title">Channel Information</span>
</div> </div>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}"> <mat-card-content class="padding-gap-x-large" [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}">
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="row"> <div fxLayout="row">
<div *ngIf="channelsType === 'open'" fxFlex="50"> <div *ngIf="channelsType === 'open'" fxFlex="50">
@ -59,8 +59,8 @@
<span class="overflow-wrap foreground-secondary-text">{{channel.isFunder ? 'Yes' : 'No'}}</span> <span class="overflow-wrap foreground-secondary-text">{{channel.isFunder ? 'Yes' : 'No'}}</span>
</div> </div>
</div> </div>
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div *ngIf="showAdvanced && channelsType === 'open'"> <div *ngIf="showAdvanced && channelsType === 'open'">
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="50"> <div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Base Fee (mSats)</h4> <h4 fxLayoutAlign="start" class="font-bold-500">Base Fee (mSats)</h4>

@ -1,5 +1,5 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
@ -78,5 +78,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -1,5 +1,5 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
@ -78,5 +78,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -1,5 +1,5 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
@ -49,5 +49,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -1,8 +1,8 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap-x"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<div fxLayout="row"> <div fxLayout="row">
<button mat-flat-button color="primary" (click)="onOpenChannel()" type="submit" tabindex="1">Open Channel</button> <button mat-flat-button color="primary" (click)="onOpenChannel()" type="submit" tabindex="1">Open Channel</button>
</div> </div>
<div fxLayout="column" fxFlex="100" class="mt-2 bordered-box"> <div fxLayout="column" fxFlex="100" class="my-2 bordered-box">
<mat-tab-group [(selectedIndex)]="activeLink" (selectedTabChange)="onSelectedTabChange($event)"> <mat-tab-group [(selectedIndex)]="activeLink" (selectedTabChange)="onSelectedTabChange($event)">
<mat-tab> <mat-tab>
<ng-template mat-tab-label> <ng-template mat-tab-label>

@ -47,6 +47,8 @@ export class ECLChannelsTablesComponent implements OnInit, OnDestroy {
this.information = rtlStore.information; this.information = rtlStore.information;
this.peers = rtlStore.peers; this.peers = rtlStore.peers;
this.totalBalance = rtlStore.onchainBalance.total; this.totalBalance = rtlStore.onchainBalance.total;
console.warn(this.numOfPendingChannels);
console.warn(rtlStore.channelsStatus.pending);
this.logger.info(rtlStore); this.logger.info(rtlStore);
}); });
} }

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">{{alertTitle}}</span> <span class="page-title">{{alertTitle}}</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="column" (submit)="onOpenChannel()" (reset)="resetData()" #form="ngForm"> <form fxLayout="column" (submit)="onOpenChannel()" (reset)="resetData()" #form="ngForm">
<div fxLayout="column"> <div fxLayout="column">
<mat-form-field fxFlex="100" *ngIf="!peer && peers && peers.length > 0"> <mat-form-field fxFlex="100" *ngIf="!peer && peers && peers.length > 0">

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Connect to a new peer</span> <span class="page-title">Connect to a new peer</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<div fxLayout="column"> <div fxLayout="column">
<mat-vertical-stepper [linear]="true" #stepper (selectionChange)="stepSelectionChanged($event)"> <mat-vertical-stepper [linear]="true" #stepper (selectionChange)="stepSelectionChanged($event)">
<mat-step [stepControl]="peerFormGroup" [editable]="flgEditable"> <mat-step [stepControl]="peerFormGroup" [editable]="flgEditable">

@ -1,9 +1,9 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" #peersForm="ngForm"> <form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" #peersForm="ngForm">
<button mat-flat-button color="primary" type="submit" tabindex="1" (click)="onConnectPeer({})">Add Peer</button> <button mat-flat-button color="primary" type="submit" tabindex="1" (click)="onConnectPeer({})">Add Peer</button>
</form> </form>
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"> <div fxFlex="70">
<fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Peers</span> <span class="page-title">Peers</span>
@ -74,6 +74,6 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.pub_key === newlyAddedPeer && flgAnimate) ? 'added' : 'notAdded'"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.pub_key === newlyAddedPeer && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>

@ -1,6 +1,6 @@
<div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'error-border': errorMessage !== '', 'padding-gap-x': true}"> <div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'error-border': errorMessage !== '', 'padding-gap-x': true}">
<div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div> <div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput [(ngModel)]="filterValue" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter"> <input matInput [(ngModel)]="filterValue" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
@ -55,5 +55,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -1,8 +1,8 @@
<div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'error-border': errorMessage !== '', 'padding-gap': true}"> <div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'error-border': errorMessage !== '', 'padding-gap': true}">
<div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div> <div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-md="row" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap-x page-sub-title-container"> <div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-md="row" fxFlex="100" fxLayoutAlign="space-between stretch" class="page-sub-title-container">
<div fxLayout="column" fxFlex="49" fxLayoutAlign="start end" class="mb-6"> <div fxLayout="column" fxFlex="49" fxLayoutAlign="start end" class="mb-6">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}">
<div fxFlex="70">Incoming</div> <div fxFlex="70">Incoming</div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyIncomingFilter($event.target)" placeholder="Filter"> <input matInput (keyup)="applyIncomingFilter($event.target)" placeholder="Filter">
@ -41,10 +41,10 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator #paginatorIn [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator #paginatorIn [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
<div fxLayout="column" fxFlex="49" fxLayoutAlign="start start"> <div fxLayout="column" fxFlex="49" fxLayoutAlign="start start">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}">
<div fxFlex="70">Outgoing</div> <div fxFlex="70">Outgoing</div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyOutgoingFilter($event.target)" placeholder="Filter"> <input matInput (keyup)="applyOutgoingFilter($event.target)" placeholder="Filter">
@ -82,7 +82,7 @@
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
<mat-paginator #paginatorOut [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator #paginatorOut [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>
</div> </div>

@ -125,7 +125,7 @@ export class ECLEffects implements OnDestroy {
this.store.dispatch(new ECLActions.SetPendingChannels((channelsRes && channelsRes.pendingChannels.length > 0) ? channelsRes.pendingChannels : [])); this.store.dispatch(new ECLActions.SetPendingChannels((channelsRes && channelsRes.pendingChannels.length > 0) ? channelsRes.pendingChannels : []));
this.store.dispatch(new ECLActions.SetInactiveChannels((channelsRes && channelsRes.inactiveChannels.length > 0) ? channelsRes.inactiveChannels : [])); this.store.dispatch(new ECLActions.SetInactiveChannels((channelsRes && channelsRes.inactiveChannels.length > 0) ? channelsRes.inactiveChannels : []));
this.store.dispatch(new ECLActions.SetLightningBalance(channelsRes.lightningBalances)); this.store.dispatch(new ECLActions.SetLightningBalance(channelsRes.lightningBalances));
if (action.payload.fetchPayments) { if (action.payload && action.payload.fetchPayments) {
this.store.dispatch(new ECLActions.FetchPayments()); this.store.dispatch(new ECLActions.FetchPayments());
} }
return { return {
@ -243,11 +243,12 @@ export class ECLEffects implements OnDestroy {
.pipe( .pipe(
map((postRes: Peer[]) => { map((postRes: Peer[]) => {
this.logger.info(postRes); this.logger.info(postRes);
postRes = (postRes && postRes.length) ? postRes : [];
this.store.dispatch(new RTLActions.CloseSpinner()); this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new ECLActions.SetPeers((postRes && postRes.length) ? postRes : [])); this.store.dispatch(new ECLActions.SetPeers(postRes));
return { return {
type: ECLActions.NEWLY_ADDED_PEER_ECL, type: ECLActions.NEWLY_ADDED_PEER_ECL,
payload: { peer: postRes[0] } payload: { peer: postRes.find(peer => peer.nodeId === (action.payload.id.includes('@') ? action.payload.id.substring(0, action.payload.id.indexOf('@')) : action.payload.id)) }
}; };
}), }),
catchError((err: any) => { catchError((err: any) => {
@ -298,7 +299,8 @@ export class ECLEffects implements OnDestroy {
this.store.dispatch(new RTLActions.CloseSpinner()); this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenSnackBar('Channel Added Successfully!')); this.store.dispatch(new RTLActions.OpenSnackBar('Channel Added Successfully!'));
return { return {
type: ECLActions.FETCH_CHANNELS_ECL type: ECLActions.FETCH_CHANNELS_ECL,
payload: { fetchPayments: false }
}; };
}), }),
catchError((err: any) => { catchError((err: any) => {
@ -330,7 +332,8 @@ export class ECLEffects implements OnDestroy {
this.store.dispatch(new RTLActions.OpenSnackBar('Channel Updated Successfully!')); this.store.dispatch(new RTLActions.OpenSnackBar('Channel Updated Successfully!'));
} }
return { return {
type: ECLActions.FETCH_CHANNELS_ECL type: ECLActions.FETCH_CHANNELS_ECL,
payload: { fetchPayments: false }
}; };
}), }),
catchError((err: any) => { catchError((err: any) => {

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Create Invoice</span> <span class="page-title">Create Invoice</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="row wrap" fxLayoutAlign="start space-between" fxFlex="100" #addInvoiceForm="ngForm"> <form fxLayout="row wrap" fxLayoutAlign="start space-between" fxFlex="100" #addInvoiceForm="ngForm">
<mat-form-field fxFlex="100" fxLayoutAlign="start end"> <mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput autoFocus [(ngModel)]="description" placeholder="Description" tabindex="2" name="description" required> <input matInput autoFocus [(ngModel)]="description" placeholder="Description" tabindex="2" name="description" required>

@ -2,15 +2,15 @@
<div fxFlex="35" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap-large" [ngClass]="{'display-none': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}"> <div fxFlex="35" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap-large" [ngClass]="{'display-none': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}">
<qrcode [qrdata]="invoice.serialized" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode> <qrcode [qrdata]="invoice.serialized" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode>
</div> </div>
<div fxFlex="65" class="padding-gap-large"> <div fxFlex="65">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header mb-1"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">{{screenSize === screenSizeEnum.XS ? (newlyAdded ? 'Created' : 'Invoice') : (newlyAdded ? 'Invoice Created' : 'Invoice Information')}}</span> <span class="page-title">{{screenSize === screenSizeEnum.XS ? (newlyAdded ? 'Created' : 'Invoice') : (newlyAdded ? 'Invoice Created' : 'Invoice Information')}}</span>
</div> </div>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}"> <mat-card-content class="padding-gap-x-large" [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}">
<div fxLayout="column"> <div fxLayout="column">
<div fxFlex="30" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap" [ngClass]="{'display-none': screenSize !== screenSizeEnum.XS && screenSize !== screenSizeEnum.SM}"> <div fxFlex="30" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap" [ngClass]="{'display-none': screenSize !== screenSizeEnum.XS && screenSize !== screenSizeEnum.SM}">
<qrcode [qrdata]="invoice.serialized" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode> <qrcode [qrdata]="invoice.serialized" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode>

@ -1,4 +1,4 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" class="padding-gap"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch">
<form *ngIf="calledFrom === 'home'" fxLayout="row wrap" fxLayoutAlign="stretch start" fxFlex="100" #addInvoiceForm="ngForm"> <form *ngIf="calledFrom === 'home'" fxLayout="row wrap" fxLayoutAlign="stretch start" fxFlex="100" #addInvoiceForm="ngForm">
<mat-form-field fxFlex="100" fxLayoutAlign="space-between stretch"> <mat-form-field fxFlex="100" fxLayoutAlign="space-between stretch">
<input matInput [(ngModel)]="description" placeholder="Description" tabindex="2" name="description" required="true"> <input matInput [(ngModel)]="description" placeholder="Description" tabindex="2" name="description" required="true">
@ -86,6 +86,6 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.label == newlyAddedInvoiceMemo && row.value == newlyAddedInvoiceValue && flgAnimate) ? 'added' : 'notAdded'"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.label == newlyAddedInvoiceMemo && row.value == newlyAddedInvoiceValue && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>

@ -1,12 +1,12 @@
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="space-between stretch"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="space-between stretch">
<div fxFlex="100" class="padding-gap-large pl-3"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Payment Information</span> <span class="page-title">Payment Information</span>
</div> </div>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content [perfectScrollbar] class="mt-5px mb-0 pr-2 h-40" #scrollContainer> <mat-card-content [perfectScrollbar] class="h-40 padding-gap-x-large" #scrollContainer>
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="30"> <div fxFlex="30">
@ -96,12 +96,12 @@
</div> </div>
</div> </div>
</mat-card-content> </mat-card-content>
<div fxLayout="row" fxLayoutAlign="start end" class="btn-sticky-container"> <div fxLayout="row" fxLayoutAlign="start end" class="btn-sticky-container padding-gap-x-large">
<button mat-mini-fab aria-label="Scroll Down" fxLayoutAlign="center center" (click)="onScrollDown()"> <button mat-mini-fab aria-label="Scroll Down" fxLayoutAlign="center center" (click)="onScrollDown()">
<mat-icon fxLayoutAlign="center center">arrow_downward</mat-icon> <mat-icon fxLayoutAlign="center center">arrow_downward</mat-icon>
</button> </button>
</div> </div>
<div fxLayout="row" fxLayoutAlign="end center" class="mt-1"> <div fxLayout="row" fxLayoutAlign="end center" class="padding-gap-x-large padding-gap-bottom-large">
<button class="mr-1" fxLayoutAlign="center center" tabindex="1" mat-stroked-button color="primary" type="button" [mat-dialog-close]="false" default>OK</button> <button class="mr-1" fxLayoutAlign="center center" tabindex="1" mat-stroked-button color="primary" type="button" [mat-dialog-close]="false" default>OK</button>
</div> </div>
</div> </div>

@ -1,4 +1,4 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="padding-gap"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<form *ngIf="calledFrom === 'home'" fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" #sendPaymentForm="ngForm"> <form *ngIf="calledFrom === 'home'" fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" #sendPaymentForm="ngForm">
<mat-form-field fxFlex="100"> <mat-form-field fxFlex="100">
<textarea [perfectScrollbar] matInput placeholder="Payment Request" name="paymentRequest" tabindex="1" [ngModel]="paymentRequest" (ngModelChange)="onPaymentRequestEntry($event)" required (matTextareaAutosize)="true" #paymentReq="ngModel"></textarea> <textarea [perfectScrollbar] matInput placeholder="Payment Request" name="paymentRequest" tabindex="1" [ngModel]="paymentRequest" (ngModelChange)="onPaymentRequestEntry($event)" required (matTextareaAutosize)="true" #paymentReq="ngModel"></textarea>
@ -140,6 +140,6 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.payment_hash === newlyAddedPayment && flgAnimate) ? 'added' : 'notAdded'"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.payment_hash === newlyAddedPayment && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>

@ -1,4 +1,4 @@
<div fxLayout="column" fxFlex="100" class="padding-gap"> <div fxLayout="column" fxFlex="100">
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" (ngSubmit)="queryRoutesForm.form.valid && onQueryRoutes()" #queryRoutesForm="ngForm"> <form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" (ngSubmit)="queryRoutesForm.form.valid && onQueryRoutes()" #queryRoutesForm="ngForm">
<div fxFlex="100" class="alert alert-warn"> <div fxFlex="100" class="alert alert-warn">
<fa-icon [icon]="faExclamationTriangle" class="mr-1 alert-icon"></fa-icon> <fa-icon [icon]="faExclamationTriangle" class="mr-1 alert-icon"></fa-icon>
@ -17,7 +17,7 @@
<button mat-flat-button color="primary" type="submit" tabindex="4">Query Route</button> <button mat-flat-button color="primary" type="submit" tabindex="4">Query Route</button>
</div> </div>
</form> </form>
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-2 mb-1"> <div fxLayout="row" fxLayoutAlign="start center" class="page-sub-title-container mt-2 mb-1">
<div fxFlex="70"> <div fxFlex="70">
<fa-icon [icon]="faRoute" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faRoute" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Transaction Route</span> <span class="page-title">Transaction Route</span>

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Send Payment</span> <span class="page-title">Send Payment</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayoutAlign="space-between stretch" fxLayout="column" #sendPaymentForm="ngForm"> <form fxLayoutAlign="space-between stretch" fxLayout="column" #sendPaymentForm="ngForm">
<mat-form-field fxFlex="100"> <mat-form-field fxFlex="100">
<textarea autoFocus matInput placeholder="Payment Request" name="paymentRequest" tabindex="1" [ngModel]="paymentRequest" (ngModelChange)="onPaymentRequestEntry($event)" (matTextareaAutosize)="true" required #paymentReq="ngModel"></textarea> <textarea autoFocus matInput placeholder="Payment Request" name="paymentRequest" tabindex="1" [ngModel]="paymentRequest" (ngModelChange)="onPaymentRequestEntry($event)" (matTextareaAutosize)="true" required #paymentReq="ngModel"></textarea>

@ -14,7 +14,7 @@
<button mat-flat-button color="primary" tabindex="3" (click)="onDownloadBackup({})">Download Backup</button> <button mat-flat-button color="primary" tabindex="3" (click)="onDownloadBackup({})">Download Backup</button>
</div> </div>
</div> </div>
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container mt-2"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container mt-2">
<div fxFlex="70"> <div fxFlex="70">
<fa-icon [icon]="faArchive" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faArchive" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Backups</span> <span class="page-title">Backups</span>
@ -54,5 +54,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -76,7 +76,7 @@ export class ChannelBackupTableComponent implements OnInit, AfterViewInit, OnDes
this.selectedChannel = undefined; this.selectedChannel = undefined;
} }
if(action.type === RTLActions.SHOW_FILE) { if(action.type === RTLActions.SHOW_FILE) {
this.commonService.downloadFile(action.payload, 'Backup-Channel-' + (this.selectedChannel.channel_point ? this.selectedChannel.channel_point : 'All'), '.bak', '.bak'); this.commonService.downloadFile(action.payload, 'channel-' + (this.selectedChannel.channel_point ? this.selectedChannel.channel_point : 'all'), '.bak', '.bak');
this.selectedChannel = undefined; this.selectedChannel = undefined;
this.store.dispatch(new RTLActions.CloseSpinner()); this.store.dispatch(new RTLActions.CloseSpinner());
} }
@ -123,8 +123,8 @@ export class ChannelBackupTableComponent implements OnInit, AfterViewInit, OnDes
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null; this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.channels.filterPredicate = (channel: Channel, fltr: string) => { this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.active) ? 'active' : 'inactive') + (channel.channel_point ? channel.channel_point : '') + (channel.chan_id ? channel.chan_id : '') + const newChannel = ((channel.active) ? 'active' : 'inactive') + (channel.channel_point ? channel.channel_point.toLowerCase() : '') + (channel.chan_id ? channel.chan_id.toLowerCase() : '') +
(channel.remote_pubkey ? channel.remote_pubkey : '') + (channel.remote_alias ? channel.remote_alias : '') + (channel.remote_pubkey ? channel.remote_pubkey.toLowerCase() : '') + (channel.remote_alias ? channel.remote_alias.toLowerCase() : '') +
(channel.capacity ? channel.capacity : '') + (channel.local_balance ? channel.local_balance : '') + (channel.capacity ? channel.capacity : '') + (channel.local_balance ? channel.local_balance : '') +
(channel.remote_balance ? channel.remote_balance : '') + (channel.total_satoshis_sent ? channel.total_satoshis_sent : '') + (channel.remote_balance ? channel.remote_balance : '') + (channel.total_satoshis_sent ? channel.total_satoshis_sent : '') +
(channel.total_satoshis_received ? channel.total_satoshis_received : '') + (channel.commit_fee ? channel.commit_fee : '') + (channel.total_satoshis_received ? channel.total_satoshis_received : '') + (channel.commit_fee ? channel.commit_fee : '') +

@ -12,7 +12,7 @@
<div fxLayout="column" fxLayoutAlign="space-between start" fxLayout.gt-md="row wrap" *ngIf="!allRestoreExists && channels && channels?.data?.length && channels?.data?.length>0"> <div fxLayout="column" fxLayoutAlign="space-between start" fxLayout.gt-md="row wrap" *ngIf="!allRestoreExists && channels && channels?.data?.length && channels?.data?.length>0">
<h4 fxFlex="100">Restore folder location: {{selNode.channelBackupPath}}/restore</h4> <h4 fxFlex="100">Restore folder location: {{selNode.channelBackupPath}}/restore</h4>
</div> </div>
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container mt-2"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container mt-2">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target)" placeholder="Filter"> <input matInput (keyup)="applyFilter($event.target)" placeholder="Filter">
@ -43,5 +43,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -30,7 +30,7 @@
</div> </div>
</div> </div>
<ng-template #noChannelBlock> <ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1"> <div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1 w-100">
No channels available. No channels available.
<button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button> <button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div> </div>

@ -1,4 +1,4 @@
<div [@routeAnimation]="outlet && outlet.activatedRouteData" class="inner-sidenav-content" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch"> <div class="inner-sidenav-content" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch">
<mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar>
<router-outlet #outlet="outlet"></router-outlet> <router-outlet #outlet="outlet"></router-outlet>
</div> </div>

@ -1,13 +1,13 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Label UTXO</span> <span class="page-title">Label UTXO</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="row wrap" fxLayoutAlign="space-between start" fxFlex="100" class="padding-gap overflow-x-hidden" (submit)="onLabelUTXO()" (reset)="resetData()" #form="ngForm"> <form fxLayout="row wrap" fxLayoutAlign="space-between start" fxFlex="100" class="overflow-x-hidden" (submit)="onLabelUTXO()" (reset)="resetData()" #form="ngForm">
<mat-form-field fxFlex.gt-sm="100"> <mat-form-field fxFlex.gt-sm="100">
<input autoFocus matInput [(ngModel)]="label" placeholder="UTXO Label" name="label" tabindex="1" required> <input autoFocus matInput [(ngModel)]="label" placeholder="UTXO Label" name="label" tabindex="1" required>
<mat-error *ngIf="!label">UTXO Label is required.</mat-error> <mat-error *ngIf="!label">UTXO Label is required.</mat-error>

@ -1,13 +1,13 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">{{sweepAll ? 'Sweep All Funds' : 'Send Funds'}}</span> <span class="page-title">{{sweepAll ? 'Sweep All Funds' : 'Send Funds'}}</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" [mat-dialog-close]="false" default mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="row wrap" fxLayoutAlign="space-between start" fxFlex="100" *ngIf="!sweepAll; else sweepAllBlock;" class="padding-gap overflow-x-hidden" (submit)="onSendFunds()" (reset)="resetData()" #form="ngForm"> <form fxLayout="row wrap" fxLayoutAlign="space-between start" fxFlex="100" *ngIf="!sweepAll; else sweepAllBlock;" class="overflow-x-hidden" (submit)="onSendFunds()" (reset)="resetData()" #form="ngForm">
<mat-form-field fxFlex.gt-sm="55"> <mat-form-field fxFlex.gt-sm="55">
<input autoFocus matInput [(ngModel)]="transactionAddress" placeholder="Bitcoin Address" tabindex="1" name="address" required #address="ngModel"> <input autoFocus matInput [(ngModel)]="transactionAddress" placeholder="Bitcoin Address" tabindex="1" name="address" required #address="ngModel">
<mat-error *ngIf="!transactionAddress">Bitcoin address is required.</mat-error> <mat-error *ngIf="!transactionAddress">Bitcoin address is required.</mat-error>

@ -59,7 +59,7 @@
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>
</div> </div>

@ -72,7 +72,7 @@
<!-- <tr mat-row *matRowDef="let row; columns: displayedColumns;" [ngClass]="{'alert alert-warn': !isDustUTXO && row.amount_sat < 1000}"></tr> --> <!-- <tr mat-row *matRowDef="let row; columns: displayedColumns;" [ngClass]="{'alert alert-warn': !isDustUTXO && row.amount_sat < 1000}"></tr> -->
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>
</div> </div>
</div> </div>

@ -93,9 +93,9 @@ export class OnChainUTXOsComponent implements OnChanges, OnDestroy {
loadUTXOsTable(UTXOs: UTXO[]) { loadUTXOsTable(UTXOs: UTXO[]) {
this.listUTXOs = new MatTableDataSource<UTXO>([...UTXOs]); this.listUTXOs = new MatTableDataSource<UTXO>([...UTXOs]);
this.listUTXOs.filterPredicate = (utxo: UTXO, fltr: string) => { this.listUTXOs.filterPredicate = (utxo: UTXO, fltr: string) => {
const newUTXO = ((utxo.label ? utxo.label : '') + (utxo.outpoint.txid_str ? utxo.outpoint.txid_str : '') + (utxo.outpoint.output_index ? utxo.outpoint.output_index : '') const newUTXO = ((utxo.label ? utxo.label.toLowerCase() : '') + (utxo.outpoint.txid_str ? utxo.outpoint.txid_str.toLowerCase() : '') + (utxo.outpoint.output_index ? utxo.outpoint.output_index : '')
+ (utxo.outpoint.txid_bytes ? utxo.outpoint.txid_bytes : '') + (utxo.address ? utxo.address : '') + (utxo.address_type ? utxo.address_type : '') + (utxo.outpoint.txid_bytes ? utxo.outpoint.txid_bytes.toLowerCase() : '') + (utxo.address ? utxo.address.toLowerCase() : '') + (utxo.address_type ? utxo.address_type.toLowerCase() : '')
+ (utxo.amount_sat ? utxo.amount_sat : '') + (utxo.confirmations ? utxo.confirmations : '') + (utxo.pk_script ? utxo.pk_script : '')); + (utxo.amount_sat ? utxo.amount_sat : '') + (utxo.confirmations ? utxo.confirmations : '') + (utxo.pk_script ? utxo.pk_script.toLowerCase() : ''));
return newUTXO.includes(fltr); return newUTXO.includes(fltr);
}; };
this.listUTXOs.sortingDataAccessor = (data: any, sortHeaderId: string) => { this.listUTXOs.sortingDataAccessor = (data: any, sortHeaderId: string) => {

@ -1,15 +1,17 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Bump Fee</span> <span class="page-title">Bump Fee</span>
</div> </div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<form fxLayout="column"> <form fxLayout="column">
<div fxLayout="column" class="bordered-box my-2 p-2"> <div fxLayout="column" class="bordered-box mb-1 p-2">
<p fxLayoutAlign="start center" class="pb-1 word-break">Bump fee for channel point: {{bumpFeeChannel?.channel?.channel_point}}</p> <p fxLayoutAlign="start center" class="pb-1 word-break">Bump fee for channel point: {{bumpFeeChannel?.channel?.channel_point}}
<fa-icon class="ml-1" [icon]="faCopy" matSuffix rtlClipboard [payload]="bumpFeeChannel?.channel?.txid_str" (copied)="onCopyID($event)" matTooltip="Copy transaction ID"></fa-icon>
</p>
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<div fxFlex="100" class="alert alert-info"> <div fxFlex="100" class="alert alert-info">
<fa-icon [icon]="faInfoCircle" class="mr-1 alert-icon"></fa-icon> <fa-icon [icon]="faInfoCircle" class="mr-1 alert-icon"></fa-icon>

@ -1,10 +1,11 @@
import { Component, OnInit, OnDestroy, ViewChild, Inject } from '@angular/core'; import { Component, OnInit, OnDestroy, ViewChild, Inject } from '@angular/core';
import { NgModel } from '@angular/forms'; import { NgModel } from '@angular/forms';
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 { 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';
import { faInfoCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import { faCopy, faInfoCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { PendingOpenChannel } from '../../../../shared/models/lndModels'; import { PendingOpenChannel } from '../../../../shared/models/lndModels';
import { PendingOpenChannelInformation } from '../../../../shared/models/alertData'; import { PendingOpenChannelInformation } from '../../../../shared/models/alertData';
@ -23,16 +24,17 @@ export class BumpFeeComponent implements OnInit, OnDestroy {
@ViewChild('outputIdx') set payReq(outIdx: NgModel) {if(outIdx) { this.outputIdx = outIdx; }} @ViewChild('outputIdx') set payReq(outIdx: NgModel) {if(outIdx) { this.outputIdx = outIdx; }}
public bumpFeeChannel: PendingOpenChannel; public bumpFeeChannel: PendingOpenChannel;
public transTypes = [...TRANS_TYPES]; public transTypes = [...TRANS_TYPES];
public selTransType = '1'; public selTransType = '2';
public blocks = null; public blocks = null;
public fees = null; public fees = null;
public outputIndex = null; public outputIndex = null;
public faCopy = faCopy;
public faInfoCircle = faInfoCircle; public faInfoCircle = faInfoCircle;
public faExclamationTriangle = faExclamationTriangle; public faExclamationTriangle = faExclamationTriangle;
public bumpFeeError = ''; public bumpFeeError = '';
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(public dialogRef: MatDialogRef<BumpFeeComponent>, @Inject(MAT_DIALOG_DATA) public data: PendingOpenChannelInformation, private store: Store<fromRTLReducer.RTLState>, private dataService: DataService) {} constructor(public dialogRef: MatDialogRef<BumpFeeComponent>, @Inject(MAT_DIALOG_DATA) public data: PendingOpenChannelInformation, private store: Store<fromRTLReducer.RTLState>, private dataService: DataService, private snackBar: MatSnackBar) {}
ngOnInit() { ngOnInit() {
this.transTypes = this.transTypes.splice(1); this.transTypes = this.transTypes.splice(1);
@ -57,9 +59,13 @@ export class BumpFeeComponent implements OnInit, OnDestroy {
}); });
} }
onCopyID(payload: string) {
this.snackBar.open('Transaction ID copied.');
}
resetData() { resetData() {
this.bumpFeeError = ''; this.bumpFeeError = '';
this.selTransType = '1'; this.selTransType = '2';
this.blocks = null; this.blocks = null;
this.fees = null; this.fees = null;
this.outputIdx.control.setErrors(null); this.outputIdx.control.setErrors(null);

@ -1,13 +1,13 @@
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="space-between stretch"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="space-between stretch">
<div fxFlex="100" class="padding-gap-large pl-3"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header mb-1"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start"> <div fxFlex="95" fxLayoutAlign="start start">
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Channel Information</span> <span class="page-title">Channel Information</span>
</div> </div>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}"> <mat-card-content class="padding-gap-x-large" [ngClass]="{'xs-scroll-y': screenSize === screenSizeEnum.XS}">
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="50"> <div fxFlex="50">
@ -71,8 +71,8 @@
<span class="overflow-wrap foreground-secondary-text">{{channel.num_updates | number}}</span> <span class="overflow-wrap foreground-secondary-text">{{channel.num_updates | number}}</span>
</div> </div>
</div> </div>
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div *ngIf="showAdvanced"> <div *ngIf="showAdvanced">
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="25"> <div fxFlex="25">
<h4 fxLayoutAlign="start" class="font-bold-500">Commit Fee</h4> <h4 fxLayoutAlign="start" class="font-bold-500">Commit Fee</h4>
@ -131,7 +131,7 @@
</div> </div>
<mat-divider [inset]="true" class="my-1"></mat-divider> <mat-divider [inset]="true" class="my-1"></mat-divider>
</div> </div>
<div [ngClass]="{'mt-2': !showAdvanced, 'mt-1': showAdvanced}" fxLayout="row" fxLayoutAlign="end center" fxFlex="100"> <div class="mt-1" fxLayout="row" fxLayoutAlign="end center" fxFlex="100">
<button mat-stroked-button color="primary" type="reset" (click)="onShowAdvanced()" tabindex="1" class="mr-1"> <button mat-stroked-button color="primary" type="reset" (click)="onShowAdvanced()" tabindex="1" class="mr-1">
<p *ngIf="!showAdvanced; else hideAdvancedText">Show Advanced</p> <p *ngIf="!showAdvanced; else hideAdvancedText">Show Advanced</p>
<ng-template #hideAdvancedText><p>Hide Advanced</p></ng-template> <ng-template #hideAdvancedText><p>Hide Advanced</p></ng-template>

@ -1,12 +1,12 @@
<div fxLayout="row"> <div fxLayout="row">
<div fxFlex="100" class="padding-gap-large"> <div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header"> <mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start" class="padding-gap-x-large"><span class="page-title">Channel Rebalance</span></div> <div fxFlex="95" fxLayoutAlign="start start"><span class="page-title">Channel Rebalance</span></div>
<button tabindex="15" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button> <button tabindex="15" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header> </mat-card-header>
<mat-card-content class="mt-5px"> <mat-card-content class="padding-gap-x-large">
<div fxLayout="column"> <div fxLayout="column">
<div class="padding-gap-x-large" fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign="space-between stretch"> <div fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign="space-between stretch">
<div fxFlex="100" class="alert alert-info"> <div fxFlex="100" class="alert alert-info">
<fa-icon [icon]="faInfoCircle" class="mr-1 alert-icon"></fa-icon> <fa-icon [icon]="faInfoCircle" class="mr-1 alert-icon"></fa-icon>
<span>Circular Rebalance is a payment you make to *yourselves* to affect a relative change in the balances of two channels. <span>Circular Rebalance is a payment you make to *yourselves* to affect a relative change in the balances of two channels.

@ -179,7 +179,7 @@ export class ChannelRebalanceComponent implements OnInit, OnDestroy {
sendPayment(payReq: string) { sendPayment(payReq: string) {
this.flgInvoiceGenerated = true; this.flgInvoiceGenerated = true;
this.paymentRequest = payReq; this.paymentRequest = payReq;
this.store.dispatch(new LNDActions.SendPayment({paymentReq: payReq, paymentDecoded: {}, zeroAmtInvoice: false, outgoingChannel: this.selChannel, feeLimitType: this.feeFormGroup.controls.selFeeLimitType.value, feeLimit: this.feeFormGroup.controls.feeLimit.value, allowSelfPayment: true, lastHopPubkey: this.inputFormGroup.controls.selRebalancePeer.value.remote_pubkey, fromDialog: true})); this.store.dispatch(new LNDActions.SendPayment({paymentReq: payReq, outgoingChannel: this.selChannel, feeLimitType: this.feeFormGroup.controls.selFeeLimitType.value, feeLimit: this.feeFormGroup.controls.feeLimit.value, allowSelfPayment: true, lastHopPubkey: this.inputFormGroup.controls.selRebalancePeer.value.remote_pubkey, fromDialog: true}));
} }
filterActiveChannels() { filterActiveChannels() {

@ -1,5 +1,5 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target)" placeholder="Filter"> <input matInput (keyup)="applyFilter($event.target)" placeholder="Filter">
@ -91,5 +91,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -131,7 +131,8 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
}; };
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.channels.filterPredicate = (channel: Channel, fltr: string) => { this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = channel.remote_alias + channel.pending_htlcs.map(htlc => JSON.stringify(htlc) + (htlc.incoming ? 'yes' : 'no')); const newChannel = (channel.remote_alias ? channel.remote_alias.toLowerCase() : '') +
channel.pending_htlcs.map(htlc => JSON.stringify(htlc) + (htlc.incoming ? 'yes' : 'no'));
return newChannel.includes(fltr); return newChannel.includes(fltr);
}; };
} }

@ -1,5 +1,5 @@
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target)" placeholder="Filter"> <input matInput (keyup)="applyFilter($event.target)" placeholder="Filter">
@ -56,5 +56,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

@ -1,5 +1,5 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap-x">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
@ -84,5 +84,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
</div> </div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator> <mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div> </div>

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

Loading…
Cancel
Save