msatoshi migration without backward compatibility

msatoshi migration without backward compatibility
pull/1247/head
Shahana Farooqui 11 months ago
parent 40173091e9
commit 1fcad6306f

@ -11,15 +11,15 @@ parameters have `default` values for initial setup and can be updated after RTL
"defaultNodeIndex": <Default index to load when rtl server starts, default 1, Optional>,
"dbDirectoryPath": "<Complete path of the folder where rtl database file should be saved, defults to RTL root, Optional>",
"SSO": {
"rtlSSO": <parameter to turn SSO off/on. Allowed values - 1 (single sign on via an external cookie), 0 (stand alone RTL authentication), default 0, Required>,
"rtlSSO": <parameter to turn SSO off/on. Allowed values - 1 (single sign on via an external cookie), 0 (stand alone RTL authentication), Required>,
"rtlCookiePath": "<Full path of the cookie file including the file name. The application url needs to pass the value from this cookie file as query param 'access-key' for the SSO authentication to work, Required if SSO=1 else empty (Optional)>",
"logoutRedirectLink": "<URL to re-direct to after logout/timeout from RTL, Required if SSO=1 else empty (Optional)>"
},
"nodes": [
{
"index": <Incremental node indices starting from 1, Required>,
"lnNode": "<Node name to uniquely identify the node in the UI, Default 'Node 1', Required>",
"lnImplementation": "<LNP implementation, Allowed values LND/CLN/ECL. Default 'LND', Required>",
"lnNode": "<Node name to uniquely identify the node in the UI, Required>",
"lnImplementation": "<LNP implementation, Allowed values LND/CLN/ECL, Required>",
"Authentication": {
"macaroonPath": "<Path for the folder containing 'admin.macaroon' (LND)/'access.macaroon' (CLN) file, Required for LND & CLN>",
"swapMacaroonPath": "<Path for the folder containing 'loop.macaroon' (LND), Required for LND Loop>",
@ -28,16 +28,16 @@ parameters have `default` values for initial setup and can be updated after RTL
"lnApiPassword": "<Password to be used for ECL API authentication. Mandatory only for ECL if the configPath is missing>"
},
"Settings": {
"userPersona": "<User persona to tailor the data on UI. Allowed values MERCHANT, OPERATOR. Default MERCHANT, Required>",
"themeMode": "<Theme modes, Allowed values DAY, NIGHT. Default DAY, Required>",
"themeColor": "<Theme colors, Allowed values PURPLE, TEAL, INDIGO, PINK, YELLOW. Default PURPLE, Required>",
"userPersona": "<User persona to tailor the data on UI. Allowed values MERCHANT/OPERATOR. Default MERCHANT, Optional>",
"themeMode": "<Theme modes, Allowed values DAY, NIGHT. Default DAY, Optional>",
"themeColor": "<Theme colors, Allowed values PURPLE, TEAL, INDIGO, PINK, YELLOW. Default PURPLE, Optional>",
"channelBackupPath": "<Path to save channel backup file. Only for LND implementation, Default <RTL root>\backup\node-1, Optional>",
"bitcoindConfigPath": "<Path of bitcoind.conf path if available locally>",
"logLevel": <logging levels, will log in accordance with the logLevel value provided, Allowed values ERROR, WARN, INFO, DEBUG>,
"fiatConversion": <parameter to turn fiat conversion off/on. Allowed values - true, false, default false, Required>,
"currencyUnit": "<Optional: Fiat current Unit for currency conversion, default 'USD' If fiatConversion is true, Required if fiatConversion is true>",
"fiatConversion": <parameter to turn fiat conversion off/on. Allowed values - true, false, default false, Optional>,
"currencyUnit": "<Optional: Fiat current Unit for currency conversion, default 'USD', Optional>",
"unannouncedChannels": <parameter to turn off/on setting for opening announced Channels, default false, Optional>
"lnServerUrl": "<Service url for LND/Core Lightning REST APIs for the node, e.g. https://192.168.0.1:8080 OR https://192.168.0.1:3001 OR http://192.168.0.1:8080. Default 'https://127.0.0.1:8080', Required",
"lnServerUrl": "<Service url for LND/Core Lightning REST APIs for the node, e.g. https://192.168.0.1:8080 OR https://192.168.0.1:3001 OR http://192.168.0.1:8080. Default 'https://127.0.0.1:8080', Optional>
"swapServerUrl": "<Service url for swap server REST APIs for the node, e.g. https://127.0.0.1:8081, Optional>",
"boltzServerUrl": "<Service url for boltz server REST APIs for the node, e.g. https://127.0.0.1:9003, Optional>"
}
@ -50,12 +50,12 @@ parameters have `default` values for initial setup and can be updated after RTL
The environment variable can also be used for all of the above configurations except the UI settings.<br />
If the environment variables are set, it will take precedence over the parameters in the RTL-Config.json file.<br />
<br />
PORT (port number for the rtl node server, default 3000, Required)<br />
PORT (port number for the rtl node server, default 3000, Optional)<br />
HOST (host for the rtl node server, default localhost, Optional)<br />
DB_DIRECTORY_PATH (Path for the folder where rtl database file should be saved, default RTL root directory, Optional)
APP_PASSWORD (Plaintext password to be provided by the parent container, NOT suggested for standalone RTL applications, to be used by Umbrel) (Optional)<br />
LN_IMPLEMENTATION (LND/CLN/ECL. Default 'LND', Required)<br />
LN_SERVER_URL (LN server URL for LNP REST APIs, default https://127.0.0.1:8080) (Required)<br />
LN_IMPLEMENTATION (LND/CLN/ECL. Default 'LND', Optional)<br />
LN_SERVER_URL (LN server URL for LNP REST APIs, default https://127.0.0.1:8080) (Optional)<br />
SWAP_SERVER_URL (Swap server URL for REST APIs, default http://127.0.0.1:8081) (Optional)<br />
BOLTZ_SERVER_URL (Boltz server URL for REST APIs, default http://127.0.0.1:9003) (Optional)<br />
CONFIG_PATH (Full path of the LNP .conf file including the file name) (Optional for LND & CLN, Mandatory for ECL if LN_API_PASSWORD is undefined)<br />

@ -1,23 +0,0 @@
name: Pull Request Stats
on:
push:
branches: [ master, 'Release-*' ]
tags: [ 'v*' ]
release:
types: [released]
# Triggers the workflow only when merging pull request to the branches.
pull_request:
types: [opened, closed]
branches: [ master, 'Release-*', '*' ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
stats:
runs-on: ubuntu-latest
steps:
- name: Run pull request stats
uses: flowwer-dev/pull-request-stats@master
with:
period: 365

@ -17,8 +17,9 @@ export const listPeerChannels = (req, res, next) => {
channel.alias = channel.peer_id.substring(0, 20);
}
const local = channel.to_us_msat || 0;
const remote = (channel.total_msat - channel.to_us_msat) || 0;
const remote = (channel.total_msat - local) || 0;
const total = channel.total_msat || 0;
channel.to_them_msat = remote;
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3);
return channel;
});
@ -35,20 +36,16 @@ export const listChannels = (req, res, next) => {
if (options.error) {
return res.status(options.statusCode).json({ message: options.message, error: options.error });
}
if (common.isVersionCompatible(req.session.selectedNode.api_version, '0.10.2')) {
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listPeerChannels';
}
else {
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listChannels';
}
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listPeerChannels';
request(options).then((body) => {
body?.map((channel) => {
if (!channel.alias || channel.alias === '') {
channel.alias = channel.id.substring(0, 20);
}
const local = (channel.msatoshi_to_us) ? channel.msatoshi_to_us : (channel.to_us_msat || 0);
const remote = (channel.msatoshi_to_them) ? channel.msatoshi_to_them : ((channel.total_msat - channel.to_us_msat) || 0);
const total = channel.msatoshi_total ? channel.msatoshi_total : (channel.total_msat || 0);
const local = channel.to_us_msat || 0;
const remote = (channel.total_msat - local) || 0;
const total = channel.total_msat || 0;
channel.to_them_msat = remote;
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3);
return channel;
});

@ -22,8 +22,8 @@ function paymentReducer(accumulator, currentPayment) {
}
function summaryReducer(accumulator, mpp) {
if (mpp.status === 'complete') {
accumulator.msatoshi = accumulator.msatoshi + mpp.msatoshi;
accumulator.msatoshi_sent = accumulator.msatoshi_sent + mpp.msatoshi_sent;
accumulator.amount_msat = accumulator.amount_msat + mpp.amount_msat;
accumulator.amount_sent_msat = accumulator.amount_sent_msat + mpp.amount_sent_msat;
accumulator.status = mpp.status;
}
if (mpp.bolt11) {
@ -47,10 +47,10 @@ function groupBy(payments) {
delete temp.partid;
}
else {
const paySummary = curr?.reduce(summaryReducer, { msatoshi: 0, msatoshi_sent: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
const paySummary = curr?.reduce(summaryReducer, { amount_msat: 0, amount_sent_msat: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
temp = {
is_group: true, is_expanded: false, total_parts: (curr.length ? curr.length : 0), status: paySummary.status, payment_hash: curr[0].payment_hash,
destination: curr[0].destination, msatoshi: paySummary.msatoshi, msatoshi_sent: paySummary.msatoshi_sent, created_at: curr[0].created_at,
destination: curr[0].destination, amount_msat: paySummary.amount_msat, amount_sent_msat: paySummary.amount_sent_msat, created_at: curr[0].created_at,
mpps: curr
};
if (paySummary.bolt11) {

@ -72,17 +72,12 @@ export class CLWebSocketClient {
this.wsServer.sendEventsToAllLNClients(msgStr, clWsClt.selectedNode);
};
clWsClt.webSocketClient.onerror = (err) => {
if (clWsClt.selectedNode.api_version === '' || !clWsClt.selectedNode.api_version || this.common.isVersionCompatible(clWsClt.selectedNode.api_version, '0.6.0')) {
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'ERROR', fileName: 'CLWebSocket', msg: 'Web socket error', error: err });
const errStr = ((typeof err === 'object' && err.message) ? JSON.stringify({ error: err.message }) : (typeof err === 'object') ? JSON.stringify({ error: err }) : ('{ "error": ' + err + ' }'));
this.wsServer.sendErrorToAllLNClients(errStr, clWsClt.selectedNode);
clWsClt.webSocketClient.close();
if (clWsClt.reConnect) {
this.reconnet(clWsClt);
}
}
else {
clWsClt.reConnect = false;
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'ERROR', fileName: 'CLWebSocket', msg: 'Web socket error', error: err });
const errStr = ((typeof err === 'object' && err.message) ? JSON.stringify({ error: err.message }) : (typeof err === 'object') ? JSON.stringify({ error: err }) : ('{ "error": ' + err + ' }'));
this.wsServer.sendErrorToAllLNClients(errStr, clWsClt.selectedNode);
clWsClt.webSocketClient.close();
if (clWsClt.reConnect) {
this.reconnet(clWsClt);
}
};
};

@ -194,19 +194,19 @@ export const circularRebalance = (req, res, next) => {
return res.status(201).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: payToRouteCallRes, paymentStatus: payStatus });
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Channel Rebalance From Sent Info Error', req.session.selectedNode);
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: payToRouteCallRes, paymentStatus: { message: err.message, error: err.error } });
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: payToRouteCallRes, paymentStatus: err.error });
});
}, 3000);
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Channel Rebalance From Send Payment To Route Error', req.session.selectedNode);
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: {}, paymentStatus: { message: err.message, error: err.error } });
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: {}, paymentStatus: err.error });
});
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Channel Rebalance From Find Routes Error', req.session.selectedNode);
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: (foundExistingInvoice.serialized || ''), paymentHash: '', paymentDetails: {}, paymentStatus: { message: err.message, error: err.error } });
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: (foundExistingInvoice.serialized || ''), paymentHash: '', paymentDetails: {}, paymentStatus: err.error });
});
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Channel Rebalance From List Pending Invoices Error', req.session.selectedNode);
return res.status(err.statusCode).json({ flgReusingInvoice: false, invoice: '', paymentHash: '', paymentDetails: {}, paymentStatus: { message: err.message, error: err.error } });
return res.status(err.statusCode).json({ flgReusingInvoice: false, invoice: '', paymentHash: '', paymentDetails: {}, paymentStatus: err.error });
});
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -10,9 +10,9 @@
<link i18n-rel="" rel="mask-icon" href="assets/images/favicon-light/safari-pinned-tab.svg" color="#5bbad5">
<meta i18n-content="" name="msapplication-TileColor" content="#da532c">
<meta i18n-content="" name="theme-color" content="#ffffff">
<style>html{width:100%;height:99%;line-height:1.5;overflow-x:hidden;font-family:Roboto,sans-serif!important;font-size:95%}@media only screen and (max-width: 56.25em){html{font-size:90%}}@media only screen and (max-width: 37.5em){html{font-size:80%}}body{box-sizing:border-box;height:100%;margin:0;overflow:hidden}*{margin:0;padding:0}@font-face{font-family:Roboto;src:url(Roboto-Thin.f7a95c9c5999532c.woff2) format("woff2"),url(Roboto-Thin.c13c157cb81e8ebb.woff) format("woff");font-weight:100;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-ThinItalic.b0e084abf689f393.woff2) format("woff2"),url(Roboto-ThinItalic.1111028df6cea564.woff) format("woff");font-weight:100;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Light.0e01b6cd13b3857f.woff2) format("woff2"),url(Roboto-Light.603ca9a537b88428.woff) format("woff");font-weight:300;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-LightItalic.232ef4b20215f720.woff2) format("woff2"),url(Roboto-LightItalic.1b5e142f787151c8.woff) format("woff");font-weight:300;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Regular.475ba9e4e2d63456.woff2) format("woff2"),url(Roboto-Regular.bcefbfee882bc1cb.woff) format("woff");font-weight:400;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-RegularItalic.e3a9ebdaac06bbc4.woff2) format("woff2"),url(Roboto-RegularItalic.0668fae6af0cf8c2.woff) format("woff");font-weight:400;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Medium.457532032ceb0168.woff2) format("woff2"),url(Roboto-Medium.6e1ae5f0b324a0aa.woff) format("woff");font-weight:500;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-MediumItalic.872f7060602d55d2.woff2) format("woff2"),url(Roboto-MediumItalic.e06fb533801cbb08.woff) format("woff");font-weight:500;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Bold.447291a88c067396.woff2) format("woff2"),url(Roboto-Bold.fc482e6133cf5e26.woff) format("woff");font-weight:700;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BoldItalic.1b15168ef6fa4e16.woff2) format("woff2"),url(Roboto-BoldItalic.e26ba339b06f09f7.woff) format("woff");font-weight:700;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Black.2eaa390d458c877d.woff2) format("woff2"),url(Roboto-Black.b25f67ad8583da68.woff) format("woff");font-weight:900;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BlackItalic.7dc03ee444552bc5.woff2) format("woff2"),url(Roboto-BlackItalic.c8dc642467cb3099.woff) format("woff");font-weight:900;font-style:italic}</style><link rel="stylesheet" href="styles.cf1ae92c15ddd814.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.cf1ae92c15ddd814.css"></noscript></head>
<style>html{width:100%;height:99%;line-height:1.5;overflow-x:hidden;font-family:Roboto,sans-serif!important;font-size:95%}@media only screen and (max-width: 56.25em){html{font-size:90%}}@media only screen and (max-width: 37.5em){html{font-size:80%}}body{box-sizing:border-box;height:100%;margin:0;overflow:hidden}*{margin:0;padding:0}@font-face{font-family:Roboto;src:url(Roboto-Thin.f7a95c9c5999532c.woff2) format("woff2"),url(Roboto-Thin.c13c157cb81e8ebb.woff) format("woff");font-weight:100;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-ThinItalic.b0e084abf689f393.woff2) format("woff2"),url(Roboto-ThinItalic.1111028df6cea564.woff) format("woff");font-weight:100;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Light.0e01b6cd13b3857f.woff2) format("woff2"),url(Roboto-Light.603ca9a537b88428.woff) format("woff");font-weight:300;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-LightItalic.232ef4b20215f720.woff2) format("woff2"),url(Roboto-LightItalic.1b5e142f787151c8.woff) format("woff");font-weight:300;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Regular.475ba9e4e2d63456.woff2) format("woff2"),url(Roboto-Regular.bcefbfee882bc1cb.woff) format("woff");font-weight:400;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-RegularItalic.e3a9ebdaac06bbc4.woff2) format("woff2"),url(Roboto-RegularItalic.0668fae6af0cf8c2.woff) format("woff");font-weight:400;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Medium.457532032ceb0168.woff2) format("woff2"),url(Roboto-Medium.6e1ae5f0b324a0aa.woff) format("woff");font-weight:500;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-MediumItalic.872f7060602d55d2.woff2) format("woff2"),url(Roboto-MediumItalic.e06fb533801cbb08.woff) format("woff");font-weight:500;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Bold.447291a88c067396.woff2) format("woff2"),url(Roboto-Bold.fc482e6133cf5e26.woff) format("woff");font-weight:700;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BoldItalic.1b15168ef6fa4e16.woff2) format("woff2"),url(Roboto-BoldItalic.e26ba339b06f09f7.woff) format("woff");font-weight:700;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Black.2eaa390d458c877d.woff2) format("woff2"),url(Roboto-Black.b25f67ad8583da68.woff) format("woff");font-weight:900;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BlackItalic.7dc03ee444552bc5.woff2) format("woff2"),url(Roboto-BlackItalic.c8dc642467cb3099.woff) format("woff");font-weight:900;font-style:italic}</style><link rel="stylesheet" href="styles.b8517c06fec8ff5b.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.b8517c06fec8ff5b.css"></noscript></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.82293937345ce6e2.js" type="module"></script><script src="polyfills.9720483e1820202a.js" type="module"></script><script src="main.305260af7e1a40e5.js" type="module"></script>
<script src="runtime.4e09381a0ca9f8c5.js" type="module"></script><script src="polyfills.aa01d8f6b94657cb.js" type="module"></script><script src="main.a8d0423aed5824d7.js" type="module"></script>
</body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
(()=>{"use strict";var e,v={},m={};function r(e){var f=m[e];if(void 0!==f)return f.exports;var t=m[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(f,t,i,o)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,o]=e[n],c=!0,d=0;d<t.length;d++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[d]))?t.splice(d--,1):(c=!1,o<a&&(a=o));if(c){e.splice(n--,1);var u=i();void 0!==u&&(f=u)}}return f}o=o||0;for(var n=e.length;n>0&&e[n-1][2]>o;n--)e[n]=e[n-1];e[n]=[t,i,o]},r.d=(e,f)=>{for(var t in f)r.o(f,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:f[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((f,t)=>(r.f[t](e,f),f),[])),r.u=e=>e+"."+{167:"836d81485f16d9bc",267:"8f996ec2b4b156e0",315:"2aa7cf820fb9df7e",636:"c6beed2b2207416a"}[e]+".js",r.miniCssF=e=>{},r.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),(()=>{var e={},f="RTLApp:";r.l=(t,i,o,n)=>{if(e[t])e[t].push(i);else{var a,c;if(void 0!==o)for(var d=document.getElementsByTagName("script"),u=0;u<d.length;u++){var l=d[u];if(l.getAttribute("src")==t||l.getAttribute("data-webpack")==f+o){a=l;break}}a||(c=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",f+o),a.src=r.tu(t)),e[t]=[i];var s=(g,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(y=>y(b)),g)return g(b)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:f=>f},typeof trustedTypes<"u"&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(i,o)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)o.push(n[2]);else if(666!=i){var a=new Promise((l,s)=>n=e[i]=[l,s]);o.push(n[2]=a);var c=r.p+r.u(i),d=new Error;r.l(c,l=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var s=l&&("load"===l.type?"missing":l.type),p=l&&l.target&&l.target.src;d.message="Loading chunk "+i+" failed.\n("+s+": "+p+")",d.name="ChunkLoadError",d.type=s,d.request=p,n[1](d)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var f=(i,o)=>{var d,u,[n,a,c]=o,l=0;if(n.some(p=>0!==e[p])){for(d in a)r.o(a,d)&&(r.m[d]=a[d]);if(c)var s=c(r)}for(i&&i(o);l<n.length;l++)r.o(e,u=n[l])&&e[u]&&e[u][0](),e[u]=0;return r.O(s)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(f.bind(null,0)),t.push=f.bind(null,t.push.bind(t))})()})();
(()=>{"use strict";var e,v={},m={};function r(e){var f=m[e];if(void 0!==f)return f.exports;var t=m[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(f,t,i,o)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,o]=e[n],c=!0,l=0;l<t.length;l++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[l]))?t.splice(l--,1):(c=!1,o<a&&(a=o));if(c){e.splice(n--,1);var d=i();void 0!==d&&(f=d)}}return f}o=o||0;for(var n=e.length;n>0&&e[n-1][2]>o;n--)e[n]=e[n-1];e[n]=[t,i,o]},r.d=(e,f)=>{for(var t in f)r.o(f,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:f[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((f,t)=>(r.f[t](e,f),f),[])),r.u=e=>e+"."+{167:"0a9eb98ff4d99d80",267:"3689ab295fbf3315",315:"9579a11e45886597",636:"0b59d6feb16561e4"}[e]+".js",r.miniCssF=e=>{},r.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),(()=>{var e={},f="RTLApp:";r.l=(t,i,o,n)=>{if(e[t])e[t].push(i);else{var a,c;if(void 0!==o)for(var l=document.getElementsByTagName("script"),d=0;d<l.length;d++){var u=l[d];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==f+o){a=u;break}}a||(c=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",f+o),a.src=r.tu(t)),e[t]=[i];var s=(g,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(y=>y(b)),g)return g(b)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:f=>f},typeof trustedTypes<"u"&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(i,o)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)o.push(n[2]);else if(666!=i){var a=new Promise((u,s)=>n=e[i]=[u,s]);o.push(n[2]=a);var c=r.p+r.u(i),l=new Error;r.l(c,u=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var s=u&&("load"===u.type?"missing":u.type),p=u&&u.target&&u.target.src;l.message="Loading chunk "+i+" failed.\n("+s+": "+p+")",l.name="ChunkLoadError",l.type=s,l.request=p,n[1](l)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var f=(i,o)=>{var l,d,[n,a,c]=o,u=0;if(n.some(p=>0!==e[p])){for(l in a)r.o(a,l)&&(r.m[l]=a[l]);if(c)var s=c(r)}for(i&&i(o);u<n.length;u++)r.o(e,d=n[u])&&e[d]&&e[d][0](),e[d]=0;return r.O(s)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(f.bind(null,0)),t.push=f.bind(null,t.push.bind(t))})()})();

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

2363
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{
"name": "rtl",
"version": "0.13.7-beta",
"version": "0.14.0-beta",
"license": "MIT",
"type": "module",
"scripts": {

@ -14,8 +14,9 @@ export const listPeerChannels = (req, res, next) => {
body?.map((channel) => {
if (!channel.alias || channel.alias === '') { channel.alias = channel.peer_id.substring(0, 20); }
const local = channel.to_us_msat || 0;
const remote = (channel.total_msat - channel.to_us_msat) || 0;
const remote = (channel.total_msat - local) || 0;
const total = channel.total_msat || 0;
channel.to_them_msat = remote;
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3);
return channel;
});
@ -31,17 +32,14 @@ export const listChannels = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Channels..' });
options = common.getOptions(req);
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
if (common.isVersionCompatible(req.session.selectedNode.api_version, '0.10.2')) {
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listPeerChannels';
} else {
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listChannels';
}
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listPeerChannels';
request(options).then((body) => {
body?.map((channel) => {
if (!channel.alias || channel.alias === '') { channel.alias = channel.id.substring(0, 20); }
const local = (channel.msatoshi_to_us) ? channel.msatoshi_to_us : (channel.to_us_msat || 0);
const remote = (channel.msatoshi_to_them) ? channel.msatoshi_to_them : ((channel.total_msat - channel.to_us_msat) || 0);
const total = channel.msatoshi_total ? channel.msatoshi_total : (channel.total_msat || 0);
const local = channel.to_us_msat || 0;
const remote = (channel.total_msat - local) || 0;
const total = channel.total_msat || 0;
channel.to_them_msat = remote;
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3);
return channel;
});

@ -22,8 +22,8 @@ function paymentReducer(accumulator, currentPayment) {
function summaryReducer(accumulator, mpp) {
if (mpp.status === 'complete') {
accumulator.msatoshi = accumulator.msatoshi + mpp.msatoshi;
accumulator.msatoshi_sent = accumulator.msatoshi_sent + mpp.msatoshi_sent;
accumulator.amount_msat = accumulator.amount_msat + mpp.amount_msat;
accumulator.amount_sent_msat = accumulator.amount_sent_msat + mpp.amount_sent_msat;
accumulator.status = mpp.status;
}
if (mpp.bolt11) { accumulator.bolt11 = mpp.bolt11; }
@ -43,10 +43,10 @@ function groupBy(payments) {
temp.total_parts = 1;
delete temp.partid;
} else {
const paySummary = curr?.reduce(summaryReducer, { msatoshi: 0, msatoshi_sent: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
const paySummary = curr?.reduce(summaryReducer, { amount_msat: 0, amount_sent_msat: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
temp = {
is_group: true, is_expanded: false, total_parts: (curr.length ? curr.length : 0), status: paySummary.status, payment_hash: curr[0].payment_hash,
destination: curr[0].destination, msatoshi: paySummary.msatoshi, msatoshi_sent: paySummary.msatoshi_sent, created_at: curr[0].created_at,
destination: curr[0].destination, amount_msat: paySummary.amount_msat, amount_sent_msat: paySummary.amount_sent_msat, created_at: curr[0].created_at,
mpps: curr
};
if (paySummary.bolt11) { temp.bolt11 = paySummary.bolt11; }

@ -85,15 +85,11 @@ export class CLWebSocketClient {
};
clWsClt.webSocketClient.onerror = (err) => {
if (clWsClt.selectedNode.api_version === '' || !clWsClt.selectedNode.api_version || this.common.isVersionCompatible(clWsClt.selectedNode.api_version, '0.6.0')) {
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'ERROR', fileName: 'CLWebSocket', msg: 'Web socket error', error: err });
const errStr = ((typeof err === 'object' && err.message) ? JSON.stringify({ error: err.message }) : (typeof err === 'object') ? JSON.stringify({ error: err }) : ('{ "error": ' + err + ' }'));
this.wsServer.sendErrorToAllLNClients(errStr, clWsClt.selectedNode);
clWsClt.webSocketClient.close();
if (clWsClt.reConnect) { this.reconnet(clWsClt); }
} else {
clWsClt.reConnect = false;
}
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'ERROR', fileName: 'CLWebSocket', msg: 'Web socket error', error: err });
const errStr = ((typeof err === 'object' && err.message) ? JSON.stringify({ error: err.message }) : (typeof err === 'object') ? JSON.stringify({ error: err }) : ('{ "error": ' + err + ' }'));
this.wsServer.sendErrorToAllLNClients(errStr, clWsClt.selectedNode);
clWsClt.webSocketClient.close();
if (clWsClt.reConnect) { this.reconnet(clWsClt); }
};
};

@ -189,20 +189,20 @@ export const circularRebalance = (req, res, next) => {
return res.status(201).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: payToRouteCallRes, paymentStatus: payStatus });
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Channel Rebalance From Sent Info Error', req.session.selectedNode);
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: payToRouteCallRes, paymentStatus: { message: err.message, error: err.error } });
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: payToRouteCallRes, paymentStatus: err.error });
});
}, 3000);
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Channel Rebalance From Send Payment To Route Error', req.session.selectedNode);
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: {}, paymentStatus: { message: err.message, error: err.error } });
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: invoice, paymentHash: paymentHash, paymentDetails: {}, paymentStatus: err.error });
});
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Channel Rebalance From Find Routes Error', req.session.selectedNode);
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: (foundExistingInvoice.serialized || ''), paymentHash: '', paymentDetails: {}, paymentStatus: { message: err.message, error: err.error } });
return res.status(err.statusCode).json({ flgReusingInvoice: !!foundExistingInvoice, invoice: (foundExistingInvoice.serialized || ''), paymentHash: '', paymentDetails: {}, paymentStatus: err.error });
});
}).catch((errRes) => {
const err = common.handleError(errRes, 'Channels', 'Channel Rebalance From List Pending Invoices Error', req.session.selectedNode);
return res.status(err.statusCode).json({ flgReusingInvoice: false, invoice: '', paymentHash: '', paymentDetails: {}, paymentStatus: { message: err.message, error: err.error } });
return res.status(err.statusCode).json({ flgReusingInvoice: false, invoice: '', paymentHash: '', paymentDetails: {}, paymentStatus: err.error });
});
};

@ -58,7 +58,7 @@
</ng-container>
<ng-container matColumnDef="msatoshi">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Amount (Sats)</th>
<td *matCellDef="let hop" mat-cell><span fxLayoutAlign="end center">{{((hop?.msatoshi/1000) || hop?.amount_msat/1000) | number}}</span></td>
<td *matCellDef="let hop" mat-cell><span fxLayoutAlign="end center">{{hop?.amount_msat/1000 | number}}</span></td>
</ng-container>
<ng-container matColumnDef="actions">
<th *matHeaderCellDef mat-header-cell>

@ -90,7 +90,7 @@ export class CLNQueryRoutesComponent implements OnInit, OnDestroy {
[{ key: 'id', value: selHop.id, title: 'ID', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'channel', value: selHop.channel, title: 'Channel', width: 50, type: DataTypeEnum.STRING },
{ key: 'alias', value: selHop.alias, title: 'Peer Alias', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'amount_msat', value: (selHop.msatoshi || selHop.amount_msat), title: 'Amount (mSat)', width: 34, type: selHop.msatoshi ? DataTypeEnum.STRING : DataTypeEnum.NUMBER },
[{ key: 'amount_msat', value: selHop.amount_msat, title: 'Amount (mSat)', width: 34, type: DataTypeEnum.NUMBER },
{ key: 'direction', value: selHop.direction, title: 'Direction', width: 33, type: DataTypeEnum.STRING },
{ key: 'delay', value: selHop.delay, title: 'Delay', width: 33, type: DataTypeEnum.NUMBER }]
];

@ -15,7 +15,7 @@
<div class="channels-capacity-scroll" [perfectScrollbar]>
<div *ngIf="activeChannels && activeChannels.length > 0; else noChannelBlock" fxLayout="column"fxFlex="100">
<div *ngFor="let channel of activeChannels" class="mt-2">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filter: channel.peer_id}" matTooltip="{{channel.alias || channel.peer_id}}" matTooltipDisabled="{{(channel.alias || channel.peer_id).length < 26}}">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filterColumn: channel.alias ? 'alias' : 'peer_id', filterValue: channel.alias || channel.peer_id}" matTooltip="{{channel.alias || channel.peer_id}}" matTooltipDisabled="{{(channel.alias || channel.peer_id).length < 26}}">
{{(channel.alias || channel.peer_id) | slice:0:24}}{{(channel.alias || channel.peer_id).length > 25 ? '...' : ''}}
</a>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">

@ -8,7 +8,7 @@
<div fxLayout="column" fxFlex.gt-sm="88" fxFlex="84" fxLayoutAlign="start start" [perfectScrollbar]>
<div *ngIf="activeChannels && activeChannels.length > 0; else noChannelBlock" fxLayout="column" fxFlex="100"class="w-100">
<div *ngFor="let channel of activeChannels" class="mt-2">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filter: channel.peer_id}" matTooltip="{{channel.alias || channel.peer_id}}" matTooltipDisabled="{{(channel.alias || channel.peer_id).length < 26}}">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filterColumn: channel.alias ? 'alias' : 'peer_id', filterValue: channel.alias || channel.peer_id}" matTooltip="{{channel.alias || channel.peer_id}}" matTooltipDisabled="{{(channel.alias || channel.peer_id).length < 26}}">
{{(channel.alias || channel.peer_id) | slice:0:24}}{{(channel.alias || channel.peer_id).length > 25 ? '...' : ''}}
</a>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">

@ -141,7 +141,7 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : this.commonService.titleCase(column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform((returnColumn.column || ''), '_') : this.commonService.titleCase(column);
}
setFilterPredicate() {

@ -51,7 +51,6 @@
</mat-form-field>
</div>
</div>
<div *ngIf="isCompatibleVersion" fxLayout="column" fxLayoutAlign="space-between stretch" fxLayoutAlign.gt-sm="space-between center" fxLayout.gt-sm="row wrap">
<mat-expansion-panel fxLayout="column" fxFlex="100" class="flat-expansion-panel mt-2" expanded="false" (closed)="onAdvancedPanelToggle(true)" (opened)="onAdvancedPanelToggle(false)">
<mat-expansion-panel-header>
<mat-panel-title>
@ -76,7 +75,6 @@
</div>
</div>
</mat-expansion-panel>
</div>
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch"></div>
<div *ngIf="sendFundError !== ''" fxFlex="100" class="alert alert-danger mt-1">
<fa-icon class="mr-1 alert-icon" [icon]="faExclamationTriangle"></fa-icon>

@ -48,7 +48,6 @@ export class CLNOnChainSendModalComponent implements OnInit, OnDestroy {
public selectedAddress = ADDRESS_TYPES[1];
public blockchainBalance: Balance = {};
public information: GetInfo = {};
public isCompatibleVersion = false;
public newAddress = '';
public transaction: OnChain | any = {};
public feeRateTypes = FEE_RATE_TYPES;
@ -140,9 +139,6 @@ export class CLNOnChainSendModalComponent implements OnInit, OnDestroy {
this.store.select(clnNodeInformation).pipe(takeUntil(this.unSubs[2])).
subscribe((nodeInfo: GetInfo) => {
this.information = nodeInfo;
this.isCompatibleVersion =
this.commonService.isVersionCompatible(this.information.version, '0.9.0') &&
this.commonService.isVersionCompatible(this.information.api_version, '0.4.0');
});
this.store.select(utxos).pipe(takeUntil(this.unSubs[3])).
subscribe((utxosSeletor: { utxos: UTXO[], apiCallStatus: ApiCallStatusPayload }) => {

@ -144,7 +144,7 @@ export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestro
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : column === 'is_dust' ? 'Dust' : this.commonService.titleCase(column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform((returnColumn.column || ''), '_') : column === 'is_dust' ? 'Dust' : this.commonService.titleCase(column);
}
setFilterPredicate() {
@ -164,7 +164,7 @@ export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestro
break;
case 'value':
rowToFilter = (rowData?.value || ((rowData?.amount_msat || 0) / 1000)).toString();
rowToFilter = ((rowData?.amount_msat || 0) / 1000).toString();
break;
default:
@ -180,8 +180,8 @@ export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestro
this.listUTXOs.sort = this.sort;
this.listUTXOs.sortingDataAccessor = (data: UTXO, sortHeaderId: string) => {
switch (sortHeaderId) {
case 'is_dust': return (+(data.amount_msat || 0) / 1000) < this.dustAmount;
case 'value': return data.value || (+(data.amount_msat || 0) / 1000);
case 'is_dust': return ((data.amount_msat || 0) / 1000) < this.dustAmount;
case 'value': return ((data.amount_msat || 0) / 1000);
default: return (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;
}
};

@ -6,7 +6,6 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { CLNChannelInformationComponent } from '../../channel-information-modal/channel-information.component';
import { Channel, ChannelHTLC } from '../../../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
@ -103,7 +102,7 @@ export class CLNChannelActiveHTLCsTableComponent implements OnInit, AfterViewIni
[{ key: 'amount_msat', value: ((selHtlc.amount_msat || 0) / 1000), title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'direction', value: this.commonService.titleCase(selHtlc.direction || ''), title: 'Direction', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'expiry', value: selHtlc.expiry, title: 'Expiry', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'state', value: this.camelCaseWithReplace.transform(selHtlc.state || '', '_'), title: 'State', width: 50, type: DataTypeEnum.STRING }],
{ key: 'state', value: this.camelCaseWithReplace.transform((selHtlc.state || '') || '', '_'), title: 'State', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'id', value: selHtlc.id, title: 'HTLC ID', width: 50, type: DataTypeEnum.STRING },
{ key: 'local_trimmed', value: selHtlc.local_trimmed, title: 'Local Trimmed', width: 50, type: DataTypeEnum.BOOLEAN }],
[{ key: 'payment_hash', value: selHtlc.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }]
@ -125,7 +124,7 @@ export class CLNChannelActiveHTLCsTableComponent implements OnInit, AfterViewIni
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : this.commonService.titleCase(column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform((returnColumn.column || ''), '_') : this.commonService.titleCase(column);
}
setFilterPredicate() {
@ -150,7 +149,7 @@ export class CLNChannelActiveHTLCsTableComponent implements OnInit, AfterViewIni
break;
case 'state':
rowToFilter = rowData.htlcs?.map((htlc) => this.camelCaseWithReplace.transform(htlc.state || '', '_').toLowerCase() + ' ').toString() || '';
rowToFilter = rowData.htlcs?.map((htlc) => this.camelCaseWithReplace.transform((htlc.state || '') || '', '_').toLowerCase() + ' ').toString() || '';
break;
case 'payment_hash':

@ -71,12 +71,12 @@
<ng-container matColumnDef="our_channel_reserve_satoshis">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Local Reserve (Sats)</th>
<td *matCellDef="let channel" mat-cell><span fxLayoutAlign="end center">
{{channel?.our_reserve_msat | number:'1.0-0'}} </span></td>
{{channel?.our_reserve_msat / 1000 | number:'1.0-0'}} </span></td>
</ng-container>
<ng-container matColumnDef="their_channel_reserve_satoshis">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Remote Reserve (Sats)</th>
<td *matCellDef="let channel" mat-cell><span fxLayoutAlign="end center">
{{channel?.their_reserve_msat | number:'1.0-0'}} </span></td>
{{channel?.their_reserve_msat / 1000 | number:'1.0-0'}} </span></td>
</ng-container>
<ng-container matColumnDef="msatoshi_total">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Total (Sats)</th>

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild, AfterViewInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -64,7 +63,7 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private clnEffects: CLNEffects, private commonService: CommonService, private router: Router, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private clnEffects: CLNEffects, private commonService: CommonService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize();
}
@ -276,7 +275,7 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : this.commonService.titleCase(column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform((returnColumn.column || ''), '_') : this.commonService.titleCase(column);
}
setFilterPredicate() {
@ -287,10 +286,10 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
rowToFilter = ((rowData.peer_connected) ? 'connected' : 'disconnected') + (rowData.channel_id ? rowData.channel_id.toLowerCase() : '') +
(rowData.short_channel_id ? rowData.short_channel_id.toLowerCase() : '') + (rowData.id ? rowData.id.toLowerCase() : '') + (rowData.alias ? rowData.alias.toLowerCase() : '') +
(rowData.private ? 'private' : 'public') + (rowData.state ? rowData.state.toLowerCase() : '') +
(rowData.funding_txid ? rowData.funding_txid.toLowerCase() : '') + (rowData.to_them_msat ? rowData.to_them_msat : '') +
(rowData.to_us_msat ? rowData.to_us_msat : '') + (rowData.total_msat ? rowData.total_msat : '') +
(rowData.their_reserve_msat ? rowData.their_reserve_msat : '') + (rowData.our_reserve_msat ? rowData.our_reserve_msat : '') +
(rowData.spendable_msat ? rowData.spendable_msat : '');
(rowData.funding_txid ? rowData.funding_txid.toLowerCase() : '') + (rowData.to_them_msat ? rowData.to_them_msat / 1000 : '') +
(rowData.to_us_msat ? rowData.to_us_msat / 1000 : '') + (rowData.total_msat ? rowData.total_msat / 1000 : '') +
(rowData.their_reserve_msat ? rowData.their_reserve_msat / 1000 : '') + (rowData.our_reserve_msat ? rowData.our_reserve_msat / 1000 : '') +
(rowData.spendable_msat ? rowData.spendable_msat / 1000 : '');
break;
case 'private':
@ -302,19 +301,27 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
break;
case 'msatoshi_total':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['total_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((rowData['total_msat'] || 0) / 1000)?.toString() || '';
break;
case 'spendable_msatoshi':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['spendable_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((rowData['spendable_msat'] || 0) / 1000)?.toString() || '';
break;
case 'msatoshi_to_us':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['to_us_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((rowData['to_us_msat'] || 0) / 1000)?.toString() || '';
break;
case 'msatoshi_to_them':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['to_them_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((rowData['to_them_msat'] || 0) / 1000)?.toString() || '';
break;
case 'our_channel_reserve_satoshis':
rowToFilter = ((rowData['our_reserve_msat'] || 0) / 1000)?.toString() || '';
break;
case 'their_channel_reserve_satoshis':
rowToFilter = ((rowData['their_reserve_msat'] || 0) / 1000)?.toString() || '';
break;
default:
@ -331,16 +338,22 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => {
switch (sortHeaderId) {
case 'msatoshi_total':
return data['msatoshi_total'] || data['total_msat'];
return data['total_msat'];
case 'spendable_msatoshi':
return data['spendable_msatoshi'] || data['spendable_msat'];
return data['spendable_msat'];
case 'msatoshi_to_us':
return data['msatoshi_to_us'] || data['to_us_msat'];
return data['to_us_msat'];
case 'msatoshi_to_them':
return data['msatoshi_to_them'] || data['to_them_msat'];
return data['to_them_msat'];
case 'our_channel_reserve_satoshis':
return data['our_reserve_msat'];
case 'their_channel_reserve_satoshis':
return data['their_reserve_msat'];
default:
return (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;

@ -67,12 +67,12 @@
<ng-container matColumnDef="our_channel_reserve_satoshis">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Local Reserve (Sats)</th>
<td *matCellDef="let channel" mat-cell><span fxLayoutAlign="end center">
{{channel?.our_reserve_msat | number:'1.0-0'}} </span></td>
{{channel?.our_reserve_msat/1000 | number:'1.0-0'}} </span></td>
</ng-container>
<ng-container matColumnDef="their_channel_reserve_satoshis">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Remote Reserve (Sats)</th>
<td *matCellDef="let channel" mat-cell><span fxLayoutAlign="end center">
{{channel?.their_reserve_msat | number:'1.0-0'}} </span></td>
{{channel?.their_reserve_msat/1000 | number:'1.0-0'}} </span></td>
</ng-container>
<ng-container matColumnDef="msatoshi_total">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Total (Sats)</th>
@ -108,7 +108,7 @@
<mat-select placeholder="Actions" tabindex="4" class="mr-0">
<mat-select-trigger></mat-select-trigger>
<mat-option (click)="onChannelClick(channel, $event)">View Info</mat-option>
<mat-option *ngIf="isCompatibleVersion && (channel.state === 'CHANNELD_SHUTTING_DOWN' || channel.state === 'CLOSINGD_SIGEXCHANGE' || (!channel.connected && channel.state === 'CHANNELD_NORMAL'))" (click)="onChannelClose(channel)">Close Channel</mat-option>
<mat-option *ngIf="(channel.state === 'CHANNELD_SHUTTING_DOWN' || channel.state === 'CLOSINGD_SIGEXCHANGE' || (!channel.connected && channel.state === 'CHANNELD_NORMAL'))" (click)="onChannelClose(channel)">Close Channel</mat-option>
<mat-option *ngIf="channel.state === 'CHANNELD_AWAITING_LOCKIN'" (click)="onBumpFee(channel)">Bump Fee</mat-option>
</mat-select>
</div>

@ -44,7 +44,6 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
public colWidth = '20rem';
public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'pending_inactive_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
public isCompatibleVersion = false;
public totalBalance = 0;
public displayedColumns: any[] = [];
public channelsData: Channel[] = [];
@ -72,9 +71,6 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
this.store.select(nodeInfoAndBalanceAndNumPeers).pipe(takeUntil(this.unSubs[0])).
subscribe((infoBalNumpeersSelector: { information: GetInfo, balance: Balance, numPeers: number }) => {
this.information = infoBalNumpeersSelector.information;
if (this.information.api_version) {
this.isCompatibleVersion = this.commonService.isVersionCompatible(this.information.api_version, '0.4.2');
}
this.numPeers = infoBalNumpeersSelector.numPeers;
this.totalBalance = infoBalNumpeersSelector.balance.totalBalance || 0;
this.logger.info(infoBalNumpeersSelector);
@ -172,7 +168,7 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : this.commonService.titleCase(column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform((returnColumn.column || ''), '_') : this.commonService.titleCase(column);
}
setFilterPredicate() {
@ -183,9 +179,9 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
rowToFilter = ((rowData.peer_connected) ? 'connected' : 'disconnected') + (rowData.channel_id ? rowData.channel_id.toLowerCase() : '') +
(rowData.short_channel_id ? rowData.short_channel_id.toLowerCase() : '') + (rowData.id ? rowData.id.toLowerCase() : '') + (rowData.alias ? rowData.alias.toLowerCase() : '') +
(rowData.private ? 'private' : 'public') + ((rowData.state && this.CLNChannelPendingState[rowData.state]) ? this.CLNChannelPendingState[rowData.state].toLowerCase() : '') +
(rowData.funding_txid ? rowData.funding_txid.toLowerCase() : '') + (rowData.to_us_msat ? rowData.to_us_msat : '') + (rowData.to_them_msat ? rowData.to_them_msat : '') +
(rowData.total_msat ? rowData.total_msat : '') + (rowData.their_reserve_msat ? rowData.their_reserve_msat : '') +
(rowData.our_reserve_msat ? rowData.our_reserve_msat : '') + (rowData.spendable_msat ? rowData.spendable_msat : '');
(rowData.funding_txid ? rowData.funding_txid.toLowerCase() : '') + (rowData.to_us_msat ? rowData.to_us_msat : '') + (rowData.to_them_msat ? rowData.to_them_msat / 1000 : '') +
(rowData.total_msat ? rowData.total_msat / 1000 : '') + (rowData.their_reserve_msat ? rowData.their_reserve_msat / 1000 : '') +
(rowData.our_reserve_msat ? rowData.our_reserve_msat / 1000 : '') + (rowData.spendable_msat ? rowData.spendable_msat / 1000 : '');
break;
case 'private':
@ -197,19 +193,27 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
break;
case 'msatoshi_total':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['total_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((rowData['total_msat'] || 0) / 1000)?.toString() || '';
break;
case 'spendable_msatoshi':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['spendable_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((rowData['spendable_msat'] || 0) / 1000)?.toString() || '';
break;
case 'msatoshi_to_us':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['to_us_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((rowData['to_us_msat'] || 0) / 1000)?.toString() || '';
break;
case 'msatoshi_to_them':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['to_them_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((rowData['to_them_msat'] || 0) / 1000)?.toString() || '';
break;
case 'our_channel_reserve_satoshis':
rowToFilter = ((rowData['our_reserve_msat'] || 0) / 1000)?.toString() || '';
break;
case 'their_channel_reserve_satoshis':
rowToFilter = ((rowData['their_reserve_msat'] || 0) / 1000)?.toString() || '';
break;
case 'state':
@ -230,16 +234,22 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => {
switch (sortHeaderId) {
case 'msatoshi_total':
return data['msatoshi_total'] || data['total_msat'];
return data['total_msat'];
case 'spendable_msatoshi':
return data['spendable_msatoshi'] || data['spendable_msat'];
return data['spendable_msat'];
case 'msatoshi_to_us':
return data['msatoshi_to_us'] || data['to_us_msat'];
return data['to_us_msat'];
case 'msatoshi_to_them':
return data['msatoshi_to_them'] || data['to_them_msat'];
return data['to_them_msat'];
case 'our_channel_reserve_satoshis':
return data['our_reserve_msat'];
case 'their_channel_reserve_satoshis':
return data['their_reserve_msat'];
case 'state':
return this.CLNChannelPendingState[data.state];

@ -74,9 +74,7 @@ export class CLNChannelsTablesComponent implements OnInit, OnDestroy {
peers: this.peers,
information: this.information,
balance: this.totalBalance,
utxos: this.utxos,
isCompatibleVersion: this.commonService.isVersionCompatible(this.information.version, '0.9.0') &&
this.commonService.isVersionCompatible(this.information.api_version, '0.4.0')
utxos: this.utxos
};
this.store.dispatch(openAlert({
payload: {

@ -66,20 +66,18 @@
</mat-form-field>
</div>
</div>
<div *ngIf="isCompatibleVersion" fxLayout="column" fxLayoutAlign="space-between stretch" fxLayoutAlign.gt-sm="space-between center" fxLayout.gt-sm="row wrap">
<mat-form-field fxLayout="column" fxFlex="54" fxLayoutAlign="start end">
<mat-label>Coin Selection</mat-label>
<mat-select tabindex="6" multiple [(value)]="selUTXOs" (selectionChange)="onUTXOSelectionChange($event)">
<mat-select-trigger>{{totalSelectedUTXOAmount | number}} Sats ({{selUTXOs.length > 1 ? selUTXOs.length + ' UTXOs' : '1 UTXO'}})</mat-select-trigger>
<mat-option *ngFor="let utxo of utxos" [value]="utxo">{{utxo.amount_msat / 1000 | number:'1.0-0'}} Sats</mat-option>
</mat-select>
</mat-form-field>
<div fxFlex="41" fxLayout="row" fxLayoutAlign="start center">
<mat-slide-toggle tabindex="7" color="primary" name="flgUseAllBalance" [disabled]="selUTXOs.length < 1" [(ngModel)]="flgUseAllBalance" (change)="onUTXOAllBalanceChange()">
Use selected UTXOs balance
</mat-slide-toggle>
<mat-icon matTooltip="Use selected UTXOs balance as the amount to be sent. Final amount sent will be less the mining fee." matTooltipPosition="before" class="info-icon">info_outline</mat-icon>
</div>
<mat-form-field fxLayout="column" fxFlex="54" fxLayoutAlign="start end">
<mat-label>Coin Selection</mat-label>
<mat-select tabindex="6" multiple [(value)]="selUTXOs" (selectionChange)="onUTXOSelectionChange($event)">
<mat-select-trigger>{{totalSelectedUTXOAmount | number}} Sats ({{selUTXOs.length > 1 ? selUTXOs.length + ' UTXOs' : '1 UTXO'}})</mat-select-trigger>
<mat-option *ngFor="let utxo of utxos" [value]="utxo">{{(utxo.amount_msat) / 1000 | number:'1.0-0'}} Sats</mat-option>
</mat-select>
</mat-form-field>
<div fxFlex="41" fxLayout="row" fxLayoutAlign="start center">
<mat-slide-toggle tabindex="7" color="primary" name="flgUseAllBalance" [disabled]="selUTXOs.length < 1" [(ngModel)]="flgUseAllBalance" (change)="onUTXOAllBalanceChange()">
Use selected UTXOs balance
</mat-slide-toggle>
<mat-icon matTooltip="Use selected UTXOs balance as the amount to be sent. Final amount sent will be less the mining fee." matTooltipPosition="before" class="info-icon">info_outline</mat-icon>
</div>
</div>
</mat-expansion-panel>

@ -29,7 +29,6 @@ export class CLNOpenChannelComponent implements OnInit, OnDestroy {
public selectedPeer = new UntypedFormControl();
public faExclamationTriangle = faExclamationTriangle;
public alertTitle: string;
public isCompatibleVersion = false;
public selNode: SelNodeChild | null = {};
public peer: Peer | null;
public peers: Peer[];
@ -61,14 +60,12 @@ export class CLNOpenChannelComponent implements OnInit, OnDestroy {
ngOnInit() {
if (this.data.message) {
this.isCompatibleVersion = this.data.message.isCompatibleVersion;
this.information = this.data.message.information;
this.totalBalance = this.data.message.balance;
this.utxos = this.data.message.utxos;
this.peer = this.data.message.peer || null;
this.peers = this.data.message.peers || [];
} else {
this.isCompatibleVersion = false;
this.information = {};
this.totalBalance = 0;
this.utxos = [];
@ -168,7 +165,7 @@ export class CLNOpenChannelComponent implements OnInit, OnDestroy {
onUTXOSelectionChange(event: any) {
if (this.selUTXOs.length && this.selUTXOs.length > 0) {
this.totalSelectedUTXOAmount = this.selUTXOs?.reduce((acc, curr: UTXO) => acc + (curr.value || 0), 0);
this.totalSelectedUTXOAmount = this.selUTXOs?.reduce((acc, curr: UTXO) => acc + ((curr.amount_msat || 0) / 1000), 0);
if (this.flgUseAllBalance) {
this.onUTXOAllBalanceChange();
}

@ -133,8 +133,8 @@ export class CLNRoutingReportComponent implements OnInit, OnDestroy {
this.filteredEventsBySelectedPeriod?.map((event) => {
const monthNumber = event.received_time ? new Date((+event.received_time) * 1000).getMonth() : 12;
feeReport[monthNumber].extra.totalEvents = feeReport[monthNumber].extra.totalEvents + 1;
feeReport[monthNumber].value = feeReport[monthNumber].value + (+(event.fee || event.fee_msat || 0) / 1000);
this.totalFeeMsat = (this.totalFeeMsat || 0) + +(event.fee || event.fee_msat || 0);
feeReport[monthNumber].value = feeReport[monthNumber].value + (+(event.fee_msat || 0) / 1000);
this.totalFeeMsat = (this.totalFeeMsat || 0) + +(event.fee_msat || 0);
return this.filteredEventsBySelectedPeriod;
});
} else {
@ -144,8 +144,8 @@ export class CLNRoutingReportComponent implements OnInit, OnDestroy {
this.filteredEventsBySelectedPeriod?.map((event) => {
const dateNumber = event.received_time ? Math.floor((+event.received_time - startDateInSeconds) / this.secondsInADay) : 0;
feeReport[dateNumber].extra.totalEvents = feeReport[dateNumber].extra.totalEvents + 1;
feeReport[dateNumber].value = feeReport[dateNumber].value + (+(event.fee || event.fee_msat || 0) / 1000);
this.totalFeeMsat = (this.totalFeeMsat || 0) + +(event.fee || event.fee_msat || 0);
feeReport[dateNumber].value = feeReport[dateNumber].value + (+(event.fee_msat || 0) / 1000);
this.totalFeeMsat = (this.totalFeeMsat || 0) + +(event.fee_msat || 0);
return this.filteredEventsBySelectedPeriod;
});
}
@ -163,8 +163,8 @@ export class CLNRoutingReportComponent implements OnInit, OnDestroy {
this.filteredEventsBySelectedPeriod?.map((event) => {
const monthNumber = event.received_time ? new Date((+event.received_time) * 1000).getMonth() : 12;
eventsReport[monthNumber].value = eventsReport[monthNumber].value + 1;
eventsReport[monthNumber].extra.totalFees = eventsReport[monthNumber].extra.totalFees + (+(event.fee || event.fee_msat || 0) / 1000);
this.totalFeeMsat = (this.totalFeeMsat || 0) + +(event.fee || event.fee_msat || 0);
eventsReport[monthNumber].extra.totalFees = eventsReport[monthNumber].extra.totalFees + (+(event.fee_msat || 0) / 1000);
this.totalFeeMsat = (this.totalFeeMsat || 0) + +(event.fee_msat || 0);
return this.filteredEventsBySelectedPeriod;
});
} else {
@ -174,8 +174,8 @@ export class CLNRoutingReportComponent implements OnInit, OnDestroy {
this.filteredEventsBySelectedPeriod?.map((event) => {
const dateNumber = event.received_time ? Math.floor((+event.received_time - startDateInSeconds) / this.secondsInADay) : 0;
eventsReport[dateNumber].value = eventsReport[dateNumber].value + 1;
eventsReport[dateNumber].extra.totalFees = eventsReport[dateNumber].extra.totalFees + (+(event.fee || event.fee_msat || 0) / 1000);
this.totalFeeMsat = (this.totalFeeMsat || 0) + +(event.fee || event.fee_msat || 0);
eventsReport[dateNumber].extra.totalFees = eventsReport[dateNumber].extra.totalFees + (+(event.fee_msat || 0) / 1000);
this.totalFeeMsat = (this.totalFeeMsat || 0) + +(event.fee_msat || 0);
return this.filteredEventsBySelectedPeriod;
});
}

@ -122,15 +122,15 @@ export class CLNTransactionsReportComponent implements OnInit, OnDestroy {
}
filteredPayments?.map((payment) => {
const monthNumber = new Date((payment.created_at || 0) * 1000).getMonth();
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + (payment.msatoshi_sent || payment.amount_sent_msat || 0);
transactionsReport[monthNumber].series[0].value = transactionsReport[monthNumber].series[0].value + ((payment.msatoshi_sent || payment.amount_sent_msat || 0) / 1000);
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + (payment.amount_sent_msat || 0);
transactionsReport[monthNumber].series[0].value = transactionsReport[monthNumber].series[0].value + ((payment.amount_sent_msat || 0) / 1000);
transactionsReport[monthNumber].series[0].extra.total = transactionsReport[monthNumber].series[0].extra.total + 1;
return this.transactionsReportSummary;
});
filteredInvoices?.map((invoice) => {
const monthNumber = new Date(+(invoice.paid_at || 0) * 1000).getMonth();
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + (invoice.msatoshi_received || invoice.amount_received_msat || 0);
transactionsReport[monthNumber].series[1].value = transactionsReport[monthNumber].series[1].value + ((invoice.msatoshi_received || invoice.amount_received_msat || 0) / 1000);
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + (invoice.amount_received_msat || 0);
transactionsReport[monthNumber].series[1].value = transactionsReport[monthNumber].series[1].value + ((invoice.amount_received_msat || 0) / 1000);
transactionsReport[monthNumber].series[1].extra.total = transactionsReport[monthNumber].series[1].extra.total + 1;
return this.transactionsReportSummary;
});
@ -140,15 +140,15 @@ export class CLNTransactionsReportComponent implements OnInit, OnDestroy {
}
filteredPayments?.map((payment) => {
const dateNumber = Math.floor((+(payment.created_at || 0) - startDateInSeconds) / this.secondsInADay);
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + (payment.msatoshi_sent || payment.amount_sent_msat || 0);
transactionsReport[dateNumber].series[0].value = transactionsReport[dateNumber].series[0].value + ((payment.msatoshi_sent || payment.amount_sent_msat || 0) / 1000);
this.transactionsReportSummary.amountPaidSelectedPeriod = this.transactionsReportSummary.amountPaidSelectedPeriod + (payment.amount_sent_msat || 0);
transactionsReport[dateNumber].series[0].value = transactionsReport[dateNumber].series[0].value + ((payment.amount_sent_msat || 0) / 1000);
transactionsReport[dateNumber].series[0].extra.total = transactionsReport[dateNumber].series[0].extra.total + 1;
return this.transactionsReportSummary;
});
filteredInvoices?.map((invoice) => {
const dateNumber = Math.floor((+(invoice.paid_at || 0) - startDateInSeconds) / this.secondsInADay);
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + (invoice.msatoshi_received || invoice.amount_received_msat || 0);
transactionsReport[dateNumber].series[1].value = transactionsReport[dateNumber].series[1].value + ((invoice.msatoshi_received || invoice.amount_received_msat || 0) / 1000);
this.transactionsReportSummary.amountReceivedSelectedPeriod = this.transactionsReportSummary.amountReceivedSelectedPeriod + (invoice.amount_received_msat || 0);
transactionsReport[dateNumber].series[1].value = transactionsReport[dateNumber].series[1].value + ((invoice.amount_received_msat || 0) / 1000);
transactionsReport[dateNumber].series[1].extra.total = transactionsReport[dateNumber].series[1].extra.total + 1;
return this.transactionsReportSummary;
});

@ -59,10 +59,7 @@
<ng-container matColumnDef="in_msatoshi">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Amount In (Sats)</th>
<td *matCellDef="let fhEvent" mat-cell>
<span *ngIf="fhEvent?.in_msatoshi" fxLayoutAlign="end center">
{{fhEvent?.in_msatoshi/1000 | number:fhEvent?.in_msatoshi < 1000 ? '1.0-4' : '1.0-0'}}
</span>
<span *ngIf="!fhEvent?.in_msatoshi && fhEvent?.in_msat" fxLayoutAlign="end center">
<span fxLayoutAlign="end center">
{{fhEvent?.in_msat/1000 | number:fhEvent?.in_msat < 1000 ? '1.0-4' : '1.0-0'}}
</span>
</td>
@ -70,10 +67,7 @@
<ng-container matColumnDef="out_msatoshi">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Amount Out (Sats)</th>
<td *matCellDef="let fhEvent" mat-cell>
<span *ngIf="fhEvent?.out_msatoshi" fxLayoutAlign="end center">
{{fhEvent?.out_msatoshi/1000 | number:fhEvent?.out_msatoshi < 1000 ? '1.0-4' : '1.0-0'}}
</span>
<span *ngIf="!fhEvent?.out_msatoshi && fhEvent?.out_msat" fxLayoutAlign="end center">
<span fxLayoutAlign="end center">
{{fhEvent?.out_msat/1000 | number:fhEvent?.out_msat < 1000 ? '1.0-4' : '1.0-0'}}
</span>
</td>

@ -107,9 +107,9 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
{ key: 'resolved_time', value: selFEvent.resolved_time, title: 'Resolved Time', width: 50, type: DataTypeEnum.DATE_TIME }],
[{ key: 'in_channel_alias', value: selFEvent.in_channel_alias, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING },
{ key: 'out_channel_alias', value: selFEvent.out_channel_alias, title: 'Outbound Channel', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'in_msatoshi', value: (selFEvent.in_msatoshi || selFEvent.in_msat), title: 'Amount In (mSats)', width: 33, type: DataTypeEnum.NUMBER },
{ key: 'out_msatoshi', value: (selFEvent.out_msatoshi || selFEvent.out_msat), title: 'Amount Out (mSats)', width: 33, type: DataTypeEnum.NUMBER },
{ key: 'fee', value: (selFEvent.fee || selFEvent.fee_msat), title: 'Fee (mSats)', width: 34, type: DataTypeEnum.NUMBER }]
[{ key: 'in_msatoshi', value: selFEvent.in_msat, title: 'Amount In (mSats)', width: 33, type: DataTypeEnum.NUMBER },
{ key: 'out_msatoshi', value: selFEvent.out_msat, title: 'Amount Out (mSats)', width: 33, type: DataTypeEnum.NUMBER },
{ key: 'fee', value: selFEvent.fee_msat, title: 'Fee (mSats)', width: 34, type: DataTypeEnum.NUMBER }]
];
if (selFEvent.payment_hash) {
reorderedFHEvent?.unshift([{ key: 'payment_hash', value: selFEvent.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }]);
@ -143,8 +143,7 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
(rowData.resolved_time ? this.datePipe.transform(new Date(rowData.resolved_time * 1000), 'dd/MMM/y HH:mm')?.toLowerCase() + ' ' : '') +
(rowData.in_channel ? rowData.in_channel.toLowerCase() + ' ' : '') + (rowData.out_channel ? rowData.out_channel.toLowerCase() + ' ' : '') +
(rowData.in_channel_alias ? rowData.in_channel_alias.toLowerCase() + ' ' : '') + (rowData.out_channel_alias ? rowData.out_channel_alias.toLowerCase() + ' ' : '') +
(rowData.in_msatoshi ? (rowData.in_msatoshi / 1000) + ' ' : '') + (rowData.out_msatoshi ? (rowData.out_msatoshi / 1000) + ' ' : '') + (rowData.fee ? rowData.fee + ' ' : '') +
(rowData.in_msat ? (+rowData.in_msat / 1000) + ' ' : '') + (rowData.out_msat ? (+rowData.out_msat / 1000) + ' ' : '') + (rowData.fee_msat ? rowData.fee_msat + ' ' : '');
(rowData.fee_msat ? rowData.fee_msat + ' ' : '') + (rowData.in_msat ? (+rowData.in_msat / 1000) + ' ' : '') + (rowData.out_msat ? (+rowData.out_msat / 1000) + ' ' : '') + (rowData.fee_msat ? rowData.fee_msat + ' ' : '');
break;
case 'received_time':
@ -153,15 +152,15 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
break;
case 'fee':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['fee_msat'] || 0)))?.toString() || '';
rowToFilter = ((rowData['fee_msat'] || 0))?.toString() || '';
break;
case 'in_msatoshi':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['in_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = (+(rowData['in_msat'] || 0) / 1000)?.toString() || '';
break;
case 'out_msatoshi':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['out_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = (+(rowData['out_msat'] || 0) / 1000)?.toString() || '';
break;
default:
@ -178,13 +177,13 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
this.failedForwardingEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => {
switch (sortHeaderId) {
case 'in_msatoshi':
return data['in_msatoshi'] || data['in_msat'];
return data['in_msat'];
case 'out_msatoshi':
return data['out_msatoshi'] || data['out_msat'];
return data['out_msat'];
case 'fee':
return data['fee'] || data['fee_msat'];
return data['fee_msat'];
default:
return (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;

@ -61,10 +61,7 @@
<ng-container matColumnDef="in_msatoshi">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Amount In (Sats)</th>
<td *matCellDef="let fhEvent" mat-cell>
<span *ngIf="fhEvent?.in_msatoshi" fxLayoutAlign="end center">
{{fhEvent?.in_msatoshi/1000 | number:fhEvent?.in_msatoshi < 1000 ? '1.0-4' : '1.0-0'}}
</span>
<span *ngIf="!fhEvent?.in_msatoshi && fhEvent?.in_msat" fxLayoutAlign="end center">
<span fxLayoutAlign="end center">
{{fhEvent?.in_msat/1000 | number:fhEvent?.in_msat < 1000 ? '1.0-4' : '1.0-0'}}
</span>
</td>
@ -72,10 +69,7 @@
<ng-container matColumnDef="out_msatoshi">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Amount Out (Sats)</th>
<td *matCellDef="let fhEvent" mat-cell>
<span *ngIf="fhEvent?.out_msatoshi" fxLayoutAlign="end center">
{{fhEvent?.out_msatoshi/1000 | number:fhEvent?.out_msatoshi < 1000 ? '1.0-4' : '1.0-0'}}
</span>
<span *ngIf="!fhEvent?.out_msatoshi && fhEvent?.out_msat" fxLayoutAlign="end center">
<span fxLayoutAlign="end center">
{{fhEvent?.out_msat/1000 | number:fhEvent?.out_msat < 1000 ? '1.0-4' : '1.0-0'}}
</span>
</td>

@ -130,13 +130,13 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
onForwardingEventClick(selFEvent: ForwardingEvent, event: any) {
const reorderedFHEvent = [
[{ key: 'status', value: 'Settled', title: 'Status', width: 50, type: DataTypeEnum.STRING },
{ key: 'fee', value: (selFEvent.fee || selFEvent.fee_msat), title: 'Fee (mSats)', width: 50, type: DataTypeEnum.NUMBER }],
{ key: 'fee', value: selFEvent.fee_msat, title: 'Fee (mSats)', width: 50, type: DataTypeEnum.NUMBER }],
[{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME },
{ key: 'resolved_time', value: selFEvent.resolved_time, title: 'Resolved Time', width: 50, type: DataTypeEnum.DATE_TIME }],
[{ key: 'in_channel', value: selFEvent.in_channel_alias, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING },
{ key: 'out_channel', value: selFEvent.out_channel_alias, title: 'Outbound Channel', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'in_msatoshi', value: (selFEvent.in_msatoshi || selFEvent.in_msat), title: 'In (mSats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'out_msatoshi', value: (selFEvent.out_msatoshi || selFEvent.out_msat), title: 'Out (mSats)', width: 50, type: DataTypeEnum.NUMBER }]
[{ key: 'in_msatoshi', value: selFEvent.in_msat, title: 'In (mSats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'out_msatoshi', value: selFEvent.out_msat, title: 'Out (mSats)', width: 50, type: DataTypeEnum.NUMBER }]
];
if (selFEvent.payment_hash) {
reorderedFHEvent.unshift([{ key: 'payment_hash', value: selFEvent.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }]);
@ -172,7 +172,6 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
(rowData.resolved_time ? this.datePipe.transform(new Date(rowData.resolved_time * 1000), 'dd/MMM/y HH:mm')?.toLowerCase() + ' ' : '') +
(rowData.in_channel ? rowData.in_channel.toLowerCase() + ' ' : '') + (rowData.out_channel ? rowData.out_channel.toLowerCase() + ' ' : '') +
(rowData.in_channel_alias ? rowData.in_channel_alias.toLowerCase() + ' ' : '') + (rowData.out_channel_alias ? rowData.out_channel_alias.toLowerCase() + ' ' : '') +
(rowData.in_msatoshi ? (rowData.in_msatoshi / 1000) + ' ' : '') + (rowData.out_msatoshi ? (rowData.out_msatoshi / 1000) + ' ' : '') + (rowData.fee ? rowData.fee + ' ' : '') +
(rowData.in_msat ? (+rowData.in_msat / 1000) + ' ' : '') + (rowData.out_msat ? (+rowData.out_msat / 1000) + ' ' : '') + (rowData.fee_msat ? rowData.fee_msat + ' ' : '');
break;
@ -182,15 +181,15 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
break;
case 'fee':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['fee_msat'] || 0)))?.toString() || '';
rowToFilter = ((+(rowData['fee_msat'] || 0)))?.toString() || '';
break;
case 'in_msatoshi':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['in_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((+(rowData['in_msat'] || 0)) / 1000)?.toString() || '';
break;
case 'out_msatoshi':
rowToFilter = ((+(rowData[this.selFilterBy] || rowData['out_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((+(rowData['out_msat'] || 0)) / 1000)?.toString() || '';
break;
default:
@ -207,13 +206,13 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => {
switch (sortHeaderId) {
case 'in_msatoshi':
return data['in_msatoshi'] || data['in_msat'];
return data['in_msat'];
case 'out_msatoshi':
return data['out_msatoshi'] || data['out_msat'];
return data['out_msat'];
case 'fee':
return data['fee'] || data['fee_msat'];
return data['fee_msat'];
default:
return (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;

@ -55,10 +55,7 @@
<ng-container matColumnDef="in_msatoshi">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Amount In (Sats)</th>
<td *matCellDef="let fhEvent" mat-cell>
<span *ngIf="fhEvent?.in_msatoshi" fxLayoutAlign="end center">
{{fhEvent?.in_msatoshi/1000 | number:fhEvent?.in_msatoshi < 1000 ? '1.0-4' : '1.0-0'}}
</span>
<span *ngIf="!fhEvent?.in_msatoshi && fhEvent?.in_msat" fxLayoutAlign="end center">
<span fxLayoutAlign="end center">
{{fhEvent?.in_msat/1000 | number:fhEvent?.in_msat < 1000 ? '1.0-4' : '1.0-0'}}
</span>
</td>

@ -106,7 +106,7 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
const reorderedFHEvent = [
[{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME },
{ key: 'in_channel_alias', value: selFEvent.in_channel_alias, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING }],
[{ key: 'in_msatoshi', value: (selFEvent.in_msatoshi || selFEvent.in_msat), title: 'Amount In (mSats)', width: 100, type: DataTypeEnum.NUMBER }],
[{ key: 'in_msatoshi', value: selFEvent.in_msat, title: 'Amount In (mSats)', width: 100, type: DataTypeEnum.NUMBER }],
[{ key: 'failreason', value: selFEvent.failreason ? this.CLNFailReason[selFEvent.failreason] : '', title: 'Reason for Failure', width: 100, type: DataTypeEnum.STRING }]
];
this.store.dispatch(openAlert({
@ -137,7 +137,7 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
rowToFilter = (rowData.received_time ? this.datePipe.transform(new Date(rowData.received_time * 1000), 'dd/MMM/y HH:mm')?.toLowerCase() : '') +
(rowData.in_channel_alias ? rowData.in_channel_alias.toLowerCase() : '') +
((rowData.failreason && this.CLNFailReason[rowData.failreason]) ? this.CLNFailReason[rowData.failreason].toLowerCase() : '') +
(rowData.in_msatoshi ? (rowData.in_msatoshi / 1000) : '') + (rowData.in_msat ? rowData.in_msat : '');
(rowData.in_msat ? rowData.in_msat : '');
break;
case 'received_time':
@ -145,7 +145,7 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
break;
case 'in_msatoshi':
rowToFilter = ((rowData['in_msatoshi'] || +(rowData['in_msat'] || 0)) / 1000)?.toString() || '';
rowToFilter = ((+(rowData['in_msat'] || 0)) / 1000)?.toString() || '';
break;
case 'failreason':
@ -166,7 +166,7 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
this.failedLocalForwardingEvents.sortingDataAccessor = (data: LocalFailedEvent, sortHeaderId: string) => {
switch (sortHeaderId) {
case 'in_msatoshi':
return data['in_msatoshi'] || data['in_msat'];
return data['in_msat'];
case 'failreason':
return data.failreason ? this.CLNFailReason[data.failreason] : '';

@ -164,18 +164,18 @@ export class CLNRoutingPeersComponent implements OnInit, OnChanges, AfterViewIni
const incoming: any = incomingResults?.find((result) => result.channel_id === event.in_channel);
const outgoing: any = outgoingResults?.find((result) => result.channel_id === event.out_channel);
if (!incoming) {
incomingResults.push({ channel_id: event.in_channel, alias: event.in_channel_alias, events: 1, total_amount: (event.in_msatoshi || +(event.in_msat || 0)), total_fee: ((event.in_msatoshi || +(event.in_msat || 0)) - (event.out_msatoshi || +(event.out_msat || 0))) });
incomingResults.push({ channel_id: event.in_channel, alias: event.in_channel_alias, events: 1, total_amount: (+(event.in_msat || 0)), total_fee: ((+(event.in_msat || 0)) - (+(event.out_msat || 0))) });
} else {
incoming.events++;
incoming.total_amount = +incoming.total_amount + +(event.in_msatoshi || event.in_msat || 0);
incoming.total_fee = +incoming.total_fee + ((event.in_msatoshi || +(event.in_msat || 0)) - (event.out_msatoshi || +(event.out_msat || 0)));
incoming.total_amount = +incoming.total_amount + +(event.in_msat || 0);
incoming.total_fee = +incoming.total_fee + ((+(event.in_msat || 0)) - (+(event.out_msat || 0)));
}
if (!outgoing) {
outgoingResults.push({ channel_id: event.out_channel, alias: event.out_channel_alias, events: 1, total_amount: (event.out_msatoshi || +(event.out_msat || 0)), total_fee: ((event.in_msatoshi || +(event.in_msat || 0)) - (event.out_msatoshi || +(event.out_msat || 0))) });
outgoingResults.push({ channel_id: event.out_channel, alias: event.out_channel_alias, events: 1, total_amount: (+(event.out_msat || 0)), total_fee: ((+(event.in_msat || 0)) - (+(event.out_msat || 0))) });
} else {
outgoing.events++;
outgoing.total_amount = +outgoing.total_amount + +(event.out_msatoshi || event.out_msat || 0);
outgoing.total_fee = +outgoing.total_fee + ((event.in_msatoshi || +(event.in_msat || 0)) - (event.out_msatoshi || +(event.out_msat || 0)));
outgoing.total_amount = +outgoing.total_amount + +(event.out_msat || 0);
outgoing.total_fee = +outgoing.total_fee + ((+(event.in_msat || 0)) - (+(event.out_msat || 0)));
}
});
return [this.commonService.sortDescByKey(incomingResults, 'total_fee'), this.commonService.sortDescByKey(outgoingResults, 'total_fee')];

@ -113,7 +113,7 @@ export const fetchUTXOs = createAction(CLNActions.FETCH_UTXOS_CLN);
export const setUTXOs = createAction(CLNActions.SET_UTXOS_CLN, props<{ payload: UTXO[] }>());
export const fetchOfferInvoice = createAction(CLNActions.FETCH_OFFER_INVOICE_CLN, props<{ payload: { offer: string, msatoshi?: number } }>());
export const fetchOfferInvoice = createAction(CLNActions.FETCH_OFFER_INVOICE_CLN, props<{ payload: { offer: string, amount_msat?: number } }>());
export const setOfferInvoice = createAction(CLNActions.SET_OFFER_INVOICE_CLN, props<{ payload: OfferInvoice }>());

@ -21,7 +21,7 @@ import { RTLState } from '../../store/rtl.state';
import { addUpdateOfferBookmark, fetchBalance, fetchChannels, fetchFeeRates, fetchFees, fetchInvoices, fetchLocalRemoteBalance,
fetchPayments, fetchPeers, fetchUTXOs, setLookup, setPeers, setQueryRoutes, updateCLAPICallStatus, updateInvoice, setOfferInvoice,
sendPaymentStatus, setForwardingHistory, fetchPageSettings } from './cln.actions';
import { allAPIsCallStatus } from './cln.selector';
import { allAPIsCallStatus, clnNodeInformation, nodeInfoAndBalance } from './cln.selector';
import { ApiCallsListCL } from '../../shared/models/apiCallsPayload';
import { CLNOfferInformationComponent } from '../transactions/offers/offer-information-modal/offer-information.component';
@ -29,6 +29,8 @@ import { CLNOfferInformationComponent } from '../transactions/offers/offer-infor
export class CLNEffects implements OnDestroy {
CHILD_API_URL = API_URL + '/cln';
API_VERION = '';
NODE_VERISON = '';
private flgInitialized = false;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
@ -94,6 +96,8 @@ export class CLNEffects implements OnDestroy {
takeUntil(this.actions.pipe(ofType(RTLActions.SET_SELECTED_NODE))),
map((info) => {
this.logger.info(info);
this.API_VERION = info.api_version || '';
this.NODE_VERISON = info.version || '';
if (info.chains && info.chains.length && info.chains[0] &&
(typeof info.chains[0] === 'object' && info.chains[0].hasOwnProperty('chain') && info?.chains[0].chain &&
(info?.chains[0].chain.toLowerCase().indexOf('bitcoin') < 0 && info?.chains[0].chain.toLowerCase().indexOf('liquid') < 0)
@ -326,7 +330,11 @@ export class CLNEffects implements OnDestroy {
ofType(CLNActions.FETCH_CHANNELS_CLN),
mergeMap(() => {
this.store.dispatch(updateCLAPICallStatus({ payload: { action: 'FetchChannels', status: APICallStatusEnum.INITIATED } }));
return this.httpClient.get<Channel[]>(this.CHILD_API_URL + API_END_POINTS.CHANNELS_API + '/listPeerChannels');
const listChannelsEndpoint =
this.commonService.isVersionCompatible(this.NODE_VERISON, '23.02') &&
this.commonService.isVersionCompatible(this.API_VERION, '0.10.3') ?
'/listPeerChannels' : '/listChannels';
return this.httpClient.get<Channel[]>(this.CHILD_API_URL + API_END_POINTS.CHANNELS_API + listChannelsEndpoint);
}),
map((channels: Channel[]) => {
this.logger.info(channels);
@ -335,12 +343,6 @@ export class CLNEffects implements OnDestroy {
channels.forEach((channel) => {
if (channel.id) { channel.peer_id = channel.id; }
if (channel.connected) { channel.peer_connected = channel.connected; }
if (channel.msatoshi_to_us) { channel.to_us_msat = channel.msatoshi_to_us; }
if (channel.msatoshi_to_them) { channel.to_them_msat = channel.msatoshi_to_them; }
if (channel.msatoshi_total) { channel.total_msat = channel.msatoshi_total; }
if (channel.their_channel_reserve_satoshis) { channel.their_reserve_msat = +channel.their_channel_reserve_satoshis; }
if (channel.our_channel_reserve_satoshis) { channel.our_reserve_msat = +channel.our_channel_reserve_satoshis; }
if (channel.spendable_msatoshi) { channel.spendable_msat = +channel.spendable_msatoshi; }
if (channel.state === 'CHANNELD_NORMAL') {
if (channel.peer_connected) {
sortedChannels.activeChannels.push(channel);
@ -468,7 +470,7 @@ export class CLNEffects implements OnDestroy {
fetchOfferInvoiceCL = createEffect(
() => this.actions.pipe(
ofType(CLNActions.FETCH_OFFER_INVOICE_CLN),
mergeMap((action: { type: string, payload: { offer: string, msatoshi?: string } }) => {
mergeMap((action: { type: string, payload: { offer: string, amount_msat?: string } }) => {
this.store.dispatch(openSpinner({ payload: UI_MESSAGES.FETCH_INVOICE }));
this.store.dispatch(updateCLAPICallStatus({ payload: { action: 'FetchOfferInvoice', status: APICallStatusEnum.INITIATED } }));
return this.httpClient.post(this.CHILD_API_URL + API_END_POINTS.OFFERS_API + '/fetchOfferInvoice', action.payload).
@ -728,7 +730,6 @@ export class CLNEffects implements OnDestroy {
this.logger.info(postRes);
this.store.dispatch(updateCLAPICallStatus({ payload: { action: 'SaveNewInvoice', status: APICallStatusEnum.COMPLETED } }));
this.store.dispatch(closeSpinner({ payload: UI_MESSAGES.ADD_INVOICE }));
postRes.msatoshi = action.payload.amount;
postRes.amount_msat = action.payload.amount;
postRes.label = action.payload.label;
postRes.expires_at = Math.round((new Date().getTime() / 1000) + action.payload.expiry);

@ -32,7 +32,6 @@ export class CLNInvoiceInformationComponent implements OnInit, OnDestroy {
public screenSize = '';
public screenSizeEnum = ScreenSizeEnum;
public flgInvoicePaid = false;
public flgVersionCompatible = true;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(public dialogRef: MatDialogRef<CLNInvoiceInformationComponent>, @Inject(MAT_DIALOG_DATA) public data: CLNInvoiceInformation, private logger: LoggerService, private commonService: CommonService, private snackBar: MatSnackBar, private store: Store<RTLState>) { }
@ -44,10 +43,6 @@ export class CLNInvoiceInformationComponent implements OnInit, OnDestroy {
if (this.screenSize === ScreenSizeEnum.XS) {
this.qrWidth = 220;
}
this.store.select(clnNodeInformation).pipe(takeUntil(this.unSubs[0])).
subscribe((nodeInfo: GetInfo) => {
this.flgVersionCompatible = this.commonService.isVersionCompatible(nodeInfo.api_version, '0.6.0');
});
this.store.select(listInvoices).pipe(takeUntil(this.unSubs[1])).
subscribe((invoicesSelector: { listInvoices: ListInvoices, apiCallStatus: ApiCallStatusPayload }) => {
const invoiceStatus = this.invoice.status;

@ -237,11 +237,11 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
break;
case 'msatoshi':
rowToFilter = ((rowData['msatoshi'] || rowData['amount_msat'] || 0) / 1000)?.toString() || '';
rowToFilter = ((rowData['amount_msat'] || 0) / 1000)?.toString() || '';
break;
case 'msatoshi_received':
rowToFilter = ((rowData['msatoshi_received'] || rowData['amount_received_msat'] || 0) / 1000)?.toString() || '';
rowToFilter = ((rowData['amount_received_msat'] || 0) / 1000)?.toString() || '';
break;
default:
@ -281,10 +281,10 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
this.invoices.sortingDataAccessor = (data: any, sortHeaderId: string) => {
switch (sortHeaderId) {
case 'msatoshi':
return data['msatoshi'] || data['amount_msat'];
return data['amount_msat'];
case 'msatoshi_received':
return data['msatoshi_received'] || data['amount_received_msat'];
return data['amount_received_msat'];
default:
return (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;

@ -22,7 +22,7 @@
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Amount Requested (Sats)</h4>
<span class="foreground-secondary-text">
{{ !offerDecoded?.offer_amount_msat || offerDecoded?.offer_amount_msat === 0 ? 'Open Offer' : (((offerDecoded?.offer_amount || offerDecoded?.offer_amount_msat) / 1000) | number) }}
{{ !offerDecoded?.offer_amount_msat || offerDecoded?.offer_amount_msat === 0 ? 'Open Offer' : ((offerDecoded?.offer_amount_msat / 1000) | number) }}
</span>
</div>
<div fxFlex="50">

@ -13,7 +13,6 @@ import { CLNOfferInformation } from '../../../../shared/models/alertData';
import { ScreenSizeEnum } from '../../../../shared/services/consts-enums-functions';
import { Offer, OfferRequest } from '../../../../shared/models/clnModels';
import { RTLState } from '../../../../store/rtl.state';
@Component({
selector: 'rtl-cln-offer-information',
@ -34,7 +33,7 @@ export class CLNOfferInformationComponent implements OnInit, OnDestroy {
public flgOfferPaid = false;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(public dialogRef: MatDialogRef<CLNOfferInformationComponent>, @Inject(MAT_DIALOG_DATA) public data: CLNOfferInformation, private logger: LoggerService, private commonService: CommonService, private snackBar: MatSnackBar, private store: Store<RTLState>, private dataService: DataService) { }
constructor(public dialogRef: MatDialogRef<CLNOfferInformationComponent>, @Inject(MAT_DIALOG_DATA) public data: CLNOfferInformation, private logger: LoggerService, private commonService: CommonService, private snackBar: MatSnackBar, private dataService: DataService) { }
ngOnInit() {
this.offer = this.data.offer;
@ -48,9 +47,6 @@ export class CLNOfferInformationComponent implements OnInit, OnDestroy {
this.offerDecoded = decodedOffer;
if (this.offerDecoded.offer_id && !this.offerDecoded.offer_amount_msat) {
this.offerDecoded.offer_amount_msat = 0;
this.offerDecoded.offer_amount = 0;
} else {
this.offerDecoded.offer_amount = this.offerDecoded.offer_amount || this.offerDecoded.offer_amount_msat || null;
}
});
}

@ -181,9 +181,6 @@ export class CLNOffersTableComponent implements OnInit, AfterViewInit, OnDestroy
pipe(take(1)).subscribe((offerDecoded: OfferRequest) => {
if (offerDecoded.offer_id && !offerDecoded.offer_amount_msat) {
offerDecoded.offer_amount_msat = 0;
offerDecoded.offer_amount = 0;
} else {
offerDecoded.offer_amount = offerDecoded.offer_amount || offerDecoded.offer_amount_msat || null;
}
const documentDefinition = {
pageSize: 'A5',
@ -211,7 +208,7 @@ export class CLNOffersTableComponent implements OnInit, AfterViewInit, OnDestroy
},
{ text: offerDecoded.offer_description ? offerDecoded.offer_description.substring(0, 160) : '', alignment: 'center', fontSize: 16, color: '#5C5C5C' },
{ qr: selOffer.bolt12, eccLevel: 'M', fit: '227', alignment: 'center', absolutePosition: { x: 7, y: 205 } },
{ text: (!offerDecoded?.offer_amount_msat || offerDecoded?.offer_amount === 0 ? 'Open amount' : (this.decimalPipe.transform((offerDecoded.offer_amount || 0) / 1000) + ' SATS')), fontSize: 20, bold: false, color: 'white', alignment: 'center', absolutePosition: { x: 0, y: 430 } },
{ text: (!offerDecoded?.offer_amount_msat || offerDecoded?.offer_amount_msat === 0 ? 'Open amount' : (this.decimalPipe.transform((offerDecoded.offer_amount_msat || 0) / 1000) + ' SATS')), fontSize: 20, bold: false, color: 'white', alignment: 'center', absolutePosition: { x: 0, y: 430 } },
{ text: 'SCAN TO PAY', fontSize: 22, bold: true, color: 'white', alignment: 'center', absolutePosition: { x: 0, y: 455 } }
],
footer: {

@ -96,11 +96,11 @@
</ng-container>
<ng-container matColumnDef="msatoshi_sent">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Sats Sent</th>
<td *matCellDef="let payment" mat-cell><span fxLayoutAlign="end center">{{payment?.amount_sent_msat/1000 | number:payment?.amount_sent_msat < 1000 ? '1.0-4' : '1.0-0'}}</span></td>
<td *matCellDef="let payment" mat-cell><span fxLayoutAlign="end center">{{payment?.amount_sent_msat/1000 | number:'1.0-4'}}</span></td>
</ng-container>
<ng-container matColumnDef="msatoshi">
<th *matHeaderCellDef mat-header-cell mat-sort-header arrowPosition="before">Sats Received</th>
<td *matCellDef="let payment" mat-cell><span fxLayoutAlign="end center">{{payment?.amount_msat/1000 | number:payment?.amount_msat < 1000 ? '1.0-4' : '1.0-0'}}</span></td>
<td *matCellDef="let payment" mat-cell><span fxLayoutAlign="end center">{{payment?.amount_msat/1000 | number:'1.0-4'}}</span></td>
</ng-container>
<ng-container matColumnDef="actions">
<th *matHeaderCellDef mat-header-cell>

@ -236,12 +236,12 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
this.paymentDecoded = decodedPayment;
if (this.paymentDecoded.amount_msat) {
if (this.selNode?.fiatConversion) {
this.commonService.convertCurrency(this.paymentDecoded.amount_msat ? this.paymentDecoded.amount_msat / 1000 : 0, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, (this.selNode.currencyUnits && this.selNode.currencyUnits.length > 2 ? this.selNode.currencyUnits[2] : ''), this.selNode.fiatConversion).
this.commonService.convertCurrency(this.paymentDecoded.amount_msat / 1000 || 0, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, (this.selNode.currencyUnits && this.selNode.currencyUnits.length > 2 ? this.selNode.currencyUnits[2] : ''), this.selNode.fiatConversion).
pipe(takeUntil(this.unSubs[6])).
subscribe({
next: (data) => {
this.paymentDecodedHint = 'Sending: ' + this.decimalPipe.transform(this.paymentDecoded.amount_msat ?
this.paymentDecoded.amount_msat / 1000 : 0) + ' Sats (' + this.decimalPipe.transform((data.OTHER ? data.OTHER : 0),
(this.paymentDecoded.amount_msat / 1000) : 0) + ' Sats (' + this.decimalPipe.transform((data.OTHER ? data.OTHER : 0),
CURRENCY_UNIT_FORMATS.OTHER) + ' ' + data.unit + ') | Memo: ' + this.paymentDecoded.description;
}, error: (error) => {
this.paymentDecodedHint = 'Sending: ' + this.decimalPipe.transform(this.paymentDecoded.amount_msat ? this.paymentDecoded.amount_msat / 1000 : 0) +
@ -337,11 +337,11 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
break;
case 'msatoshi_sent':
rowToFilter = ((rowData['msatoshi_sent'] || rowData['amount_sent_msat'] || 0) / 1000)?.toString() || '';
rowToFilter = ((rowData['amount_sent_msat'] || 0) / 1000)?.toString() || '';
break;
case 'msatoshi':
rowToFilter = ((rowData['msatoshi'] || rowData['amount_msat'] || 0) / 1000)?.toString() || '';
rowToFilter = ((rowData['amount_msat'] || 0) / 1000)?.toString() || '';
break;
case 'type':
@ -362,10 +362,10 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
this.payments.sortingDataAccessor = (data: any, sortHeaderId: string) => {
switch (sortHeaderId) {
case 'msatoshi_sent':
return data['msatoshi_sent'] || data['amount_sent_msat'];
return data['amount_sent_msat'];
case 'msatoshi':
return data['msatoshi'] || data['amount_msat'];
return data['amount_msat'];
default:
return (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null;

@ -7,7 +7,7 @@
<button tabindex="12" fxLayoutAlign="center center" class="btn-close-x p-0" default mat-button [mat-dialog-close]="false">X</button>
</mat-card-header>
<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" fxFlex="100" fxLayoutAlign="start start" [(ngModel)]="paymentType" (change)="onPaymentTypeChange()">
<mat-radio-group class="my-1" color="primary" name="paymentType" fxFlex="100" fxLayoutAlign="start start" [(ngModel)]="paymentType" (change)="onPaymentTypeChange()">
<mat-radio-button fxFlex="20" tabindex="1" value="{{paymentTypes.INVOICE}}">Invoice</mat-radio-button>
<mat-radio-button fxFlex="20" tabindex="2" value="{{paymentTypes.KEYSEND}}">Keysend</mat-radio-button>
<mat-radio-button *ngIf="selNode.enableOffers" fxFlex="20" tabindex="3" value="{{paymentTypes.OFFER}}">Offer</mat-radio-button>

@ -74,7 +74,6 @@ export class CLNLightningSendPaymentsComponent implements OnInit, OnDestroy {
public selFeeLimitType = FEE_LIMIT_TYPES[0];
public feeLimitTypes = FEE_LIMIT_TYPES;
public paymentError = '';
public isCompatibleVersion = false;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(
@ -109,11 +108,6 @@ export class CLNLightningSendPaymentsComponent implements OnInit, OnDestroy {
this.store.select(clnNodeSettings).pipe(takeUntil(this.unSubs[0])).subscribe((nodeSettings: SelNodeChild | null) => {
this.selNode = nodeSettings;
});
this.store.select(clnNodeInformation).pipe(takeUntil(this.unSubs[1])).subscribe((nodeInfo: GetInfo) => {
this.isCompatibleVersion =
this.commonService.isVersionCompatible(nodeInfo.version, '0.9.0') &&
this.commonService.isVersionCompatible(nodeInfo.api_version, '0.4.0');
});
this.store.select(channels).pipe(takeUntil(this.unSubs[2])).
subscribe((channelsSeletor: { activeChannels: Channel[], pendingChannels: Channel[], inactiveChannels: Channel[], apiCallStatus: ApiCallStatusPayload }) => {
this.activeChannels = channelsSeletor.activeChannels;
@ -227,7 +221,7 @@ export class CLNLightningSendPaymentsComponent implements OnInit, OnDestroy {
} else if (this.paymentType === PaymentTypes.OFFER) {
if (!this.offerInvoice) {
if (this.zeroAmtOffer && this.offerAmount) {
this.store.dispatch(fetchOfferInvoice({ payload: { offer: this.offerRequest, msatoshi: this.offerAmount * 1000 } }));
this.store.dispatch(fetchOfferInvoice({ payload: { offer: this.offerRequest, amount_msat: this.offerAmount * 1000 } }));
} else {
this.store.dispatch(fetchOfferInvoice({ payload: { offer: this.offerRequest } }));
}
@ -296,9 +290,7 @@ export class CLNLightningSendPaymentsComponent implements OnInit, OnDestroy {
this.paymentDecoded.amount_msat = +event.target.value;
}
if (this.paymentType === PaymentTypes.OFFER) {
delete this.offerDecoded.offer_amount;
delete this.offerDecoded.offer_amount_msat;
this.offerDecoded.offer_amount = +event.target.value * 1000;
this.offerDecoded.offer_amount_msat = event.target.value;
}
}
@ -313,15 +305,13 @@ export class CLNLightningSendPaymentsComponent implements OnInit, OnDestroy {
setOfferDecodedDetails() {
if (this.offerDecoded.offer_id && !this.offerDecoded.offer_amount_msat) {
this.offerDecoded.offer_amount_msat = 0;
this.offerDecoded.offer_amount = 0;
this.zeroAmtOffer = true;
this.offerDescription = this.offerDecoded.offer_description || '';
this.offerIssuer = this.offerDecoded.offer_issuer ? this.offerDecoded.offer_issuer : '';
this.offerDecodedHint = 'Zero Amount Offer | Description: ' + this.offerDecoded.offer_description;
} else {
this.zeroAmtOffer = false;
this.offerDecoded.offer_amount = this.offerDecoded.offer_amount || this.offerDecoded.offer_amount_msat || null;
this.offerAmount = this.offerDecoded.offer_amount ? this.offerDecoded.offer_amount / 1000 : 0;
this.offerAmount = this.offerDecoded.offer_amount_msat ? this.offerDecoded.offer_amount_msat / 1000 : 0;
this.offerDescription = this.offerDecoded.offer_description || '';
this.offerIssuer = this.offerDecoded.offer_issuer ? this.offerDecoded.offer_issuer : '';
if (this.selNode && this.selNode.fiatConversion) {

@ -15,7 +15,7 @@
<div class="channels-capacity-scroll" [perfectScrollbar]>
<div *ngIf="allChannels && allChannels?.length > 0; else noChannelBlock" fxLayout="column"fxFlex="100">
<div *ngFor="let channel of allChannels" class="mt-2">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filter: channel.channelId}" matTooltip="{{channel.alias || channel.shortChannelId}}" matTooltipDisabled="{{(channel.alias || channel.shortChannelId).length < 26}}">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filterColumn: channel.alias ? 'alias' : 'shortChannelId', filterValue: channel.alias || channel.shortChannelId}" matTooltip="{{channel.alias || channel.shortChannelId}}" matTooltipDisabled="{{(channel.alias || channel.shortChannelId).length < 26}}">
{{(channel?.alias || channel?.shortChannelId) | slice:0:24}}{{(channel?.alias || channel?.shortChannelId).length > 25 ? '...' : ''}}
</a>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">

@ -8,7 +8,7 @@
<div fxLayout="column" fxFlex.gt-sm="88" fxFlex="84" fxLayoutAlign="start start" [perfectScrollbar]>
<div *ngIf="allChannels && allChannels.length > 0; else noChannelBlock" fxLayout="column" fxFlex="100"class="w-100">
<div *ngFor="let channel of allChannels" class="mt-2">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filter: channel.channelId}" matTooltip="{{channel.alias || channel.shortChannelId}}" matTooltipDisabled="{{(channel.alias || channel.shortChannelId).length < 26}}">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filterColumn: channel.alias ? 'alias' : 'shortChannelId', filterValue: channel.alias || channel.shortChannelId}" matTooltip="{{channel.alias || channel.shortChannelId}}" matTooltipDisabled="{{(channel.alias || channel.shortChannelId).length < 26}}">
{{(channel.alias || channel.shortChannelId) | slice:0:24}}{{(channel.alias || channel.shortChannelId).length > 25 ? '...' : ''}}
</a>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">

@ -64,11 +64,11 @@
</mat-expansion-panel-header>
<div fxLayout="column"><span class="foreground-secondary-text">{{rebalanceStatus.invoice}}</span></div>
</mat-expansion-panel>
<mat-progress-bar *ngIf="!rebalanceStatus.paymentStatus?.route && rebalanceStatus.paymentStatus?.type !== 'pending'" fxFlex="100" color="primary" mode="indeterminate"></mat-progress-bar>
<mat-progress-bar *ngIf="!rebalanceStatus.paymentStatus?.error && !rebalanceStatus.paymentStatus?.route && rebalanceStatus.paymentStatus?.type !== 'pending'" fxFlex="100" color="primary" mode="indeterminate"></mat-progress-bar>
<mat-expansion-panel class="flat-expansion-panel mb-2" fxFlex="100">
<mat-expansion-panel-header>
<mat-panel-title>
<span fxLayoutAlign="start center" fxFlex="100">{{!rebalanceStatus.paymentStatus?.route ? 'Searching route...' : rebalanceStatus.paymentStatus?.type === 'pending' ? 'Route info pending...' : 'Route used'}}<mat-icon *ngIf="rebalanceStatus.paymentStatus?.route" class="ml-1 icon-small">{{rebalanceStatus.paymentStatus?.route ? 'check' : 'close'}}</mat-icon></span>
<span fxLayoutAlign="start center" fxFlex="100">{{rebalanceStatus.paymentStatus?.error ? 'Route search failed' : !rebalanceStatus.paymentStatus?.route ? 'Searching route...' : rebalanceStatus.paymentStatus?.type === 'pending' ? 'Route info pending...' : 'Route used'}}<mat-icon *ngIf="rebalanceStatus.paymentStatus" class="ml-1 icon-small">{{rebalanceStatus.paymentStatus?.route ? 'check' : 'close'}}</mat-icon></span>
</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="column">

@ -54,7 +54,7 @@
<mat-select placeholder="Actions" tabindex="1" class="mr-0">
<mat-select-trigger></mat-select-trigger>
<mat-option (click)="onConnectNode(address)">Connect</mat-option>
<mat-option rtlClipboard [payload]="lookupResult.node.pub_key + '@' + address.addr" (copied)="onCopyNodeURI($event)">Copy URI</mat-option>
<mat-option rtlClipboard [payload]="lookupResult.node.pub_key + '@' + address.addr" (copied)="onCopyNodeURI(address)">Copy URI</mat-option>
</mat-select>
</div>
</td>

@ -46,7 +46,7 @@ export class NodeLookupComponent implements OnInit, OnDestroy {
this.store.dispatch(openAlert({
payload: {
data: {
message: { peer: { pub_key: this.lookupResult.node?.pub_key, address: address }, information: this.information, balance: this.availableBalance },
message: { peer: { pub_key: this.lookupResult.node?.pub_key, address: address.addr }, information: this.information, balance: this.availableBalance },
component: ConnectPeerComponent
}
}

@ -15,7 +15,7 @@
<div class="channels-capacity-scroll" [perfectScrollbar]>
<div *ngIf="allChannels && allChannels.length > 0; else noChannelBlock" fxLayout="column"fxFlex="100">
<div *ngFor="let channel of allChannels" class="mt-2">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filter: channel.chan_id}" matTooltip="{{channel.remote_alias || channel.remote_pubkey}}" matTooltipDisabled="{{(channel.remote_alias || channel.remote_pubkey).length < 26}}">
<a class="dashboard-capacity-header" [routerLink]="['../connections/channels/open']" [state]="{filterColumn: channel.remote_alias ? 'remote_alias' : 'remote_pubkey', filterValue: channel.remote_alias || channel.remote_pubkey}" matTooltip="{{channel.remote_alias || channel.remote_pubkey}}" matTooltipDisabled="{{(channel.remote_alias || channel.remote_pubkey).length < 26}}">
{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}
</a>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">

@ -7,7 +7,7 @@
<div fxLayout="column" fxFlex="3" fxLayoutAlign="end stretch"><mat-divider class="dashboard-divider"></mat-divider></div>
<div *ngIf="allChannels && allChannels.length > 0; else noChannelBlock"[perfectScrollbar]>
<div *ngFor="let channel of allChannels" fxLayout="column">
<a class="dashboard-capacity-header mt-2" [routerLink]="['../connections/channels/open']" [state]="{filter: channel.chan_id}" matTooltip="{{channel.remote_alias || channel.remote_pubkey}}" matTooltipDisabled="{{(channel.remote_alias || channel.remote_pubkey).length < 26}}">
<a class="dashboard-capacity-header mt-2" [routerLink]="['../connections/channels/open']" [state]="{filterColumn: channel.remote_alias ? 'remote_alias' : 'remote_pubkey', filterValue: channel.remote_alias || channel.remote_pubkey}" matTooltip="{{channel.remote_alias || channel.remote_pubkey}}" matTooltipDisabled="{{(channel.remote_alias || channel.remote_pubkey).length < 26}}">
{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}
</a>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start">

@ -7,7 +7,7 @@
<mat-icon *ngIf="value.tooltip" matTooltipPosition="below" class="info-icon" [matTooltip]="value.tooltip">info_outline</mat-icon>
</div>
<span *ngIf="currencyUnit === currencyUnitEnum.SATS" class="cc-data-value">
{{value.dataValue | number}}
{{value.dataValue | number:'1.0-0'}}
</span>
<span *ngIf="currencyUnit === currencyUnitEnum.BTC" class="cc-data-value">
{{value[currencyUnitEnum.BTC] | number:currencyUnitFormats.BTC}}

@ -8,7 +8,6 @@
<nav mat-tab-nav-bar mat-stretch-tabs="false" mat-align-tabs="start" [tabPanel]="tabPanel">
<div role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[0].link" routerLink="{{links[0].link}}" (click)="activeLink = links[0].link">{{links[0].name}}</div>
<div role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[1].link" routerLink="{{links[1].link}}" (click)="activeLink = links[1].link">{{links[1].name}}</div>
<!-- <div role="tab" mat-tab-link *ngIf="selNode?.lnImplementation?.toUpperCase() === 'LND' || selNode?.lnImplementation?.toUpperCase() === 'CLN'" class="mat-tab-label" [active]="activeLink === links[2].link" (click)="activeLink = links[2].link" routerLink="{{links[2].link}}" [state]="{ initial: false }">{{links[2].name}}</div> -->
<div *ngIf="selNode?.lnImplementation?.toUpperCase() === 'LND'" role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[2].link" routerLink="{{links[2].link}}" [state]="{ initial: false }" (click)="activeLink = links[2].link">{{links[2].name}}</div>
<div *ngIf="selNode?.lnImplementation?.toUpperCase() === 'CLN'" role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[3].link" routerLink="{{links[3].link}}" (click)="activeLink = links[3].link">{{links[3].name}}</div>
<div *ngIf="showLnConfig" role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[4].link" (click)="showLnConfigClicked()">{{links[4].name}}</div>

@ -72,7 +72,7 @@ export interface OpenChannelAlert {
export interface CLNOpenChannelAlert {
alertTitle?: string;
titleMessage?: string;
message?: { information: GetInfoCLN, balance: number, utxos: UTXOCLN[], peer?: PeerCLN, peers?: PeerCLN[], isCompatibleVersion: boolean };
message?: { information: GetInfoCLN, balance: number, utxos: UTXOCLN[], peer?: PeerCLN, peers?: PeerCLN[] };
newlyAdded?: boolean;
component?: any;
}

@ -42,8 +42,7 @@ export interface GetInfo {
blockheight?: number;
network?: string;
chains?: GetInfoChain[];
msatoshi_fees_collected?: number;
fees_collected_msat?: string;
fees_collected_msat?: number;
lnImplementation?: string;
}
@ -77,11 +76,9 @@ export interface Invoice {
bolt11?: string;
bolt12?: string;
payment_hash?: string;
msatoshi?: number; // For backward compatibility
amount_msat?: number;
status?: string;
pay_index?: number;
msatoshi_received?: number; // For backward compatibility
amount_received_msat?: number;
paid_at?: number;
payment_preimage?: string;
@ -142,9 +139,7 @@ export interface MPP {
created_at?: number;
destination?: string;
id?: number;
msatoshi?: number; // For Backward compatibility
amount_msat?: number;
msatoshi_sent?: number; // For Backward compatibility
amount_sent_msat?: number;
payment_hash?: string;
payment_preimage?: string;
@ -158,9 +153,7 @@ export interface Payment {
created_at?: number;
destination?: string;
id?: number;
msatoshi?: number; // For Backward compatibility
amount_msat?: number;
msatoshi_sent?: number; // For Backward compatibility
amount_sent_msat?: number;
payment_hash?: string;
payment_preimage?: string;
@ -179,7 +172,6 @@ export interface PayRequest {
created_at?: number;
expiry?: number;
payee?: string;
msatoshi?: number;
amount_msat?: number;
description?: string;
min_final_cltv_expiry?: number;
@ -212,7 +204,6 @@ interface Recurrence {
export interface OfferRequest {
offer_id?: string;
offer_amount?: number | null; // For Backward compatibility
offer_amount_msat?: number;
type?: string;
valid?: boolean;
@ -252,12 +243,9 @@ export interface ForwardingEvent {
out_channel?: string;
in_channel_alias?: string;
out_channel_alias?: string;
in_msatoshi?: number;
in_msat?: string | number;
out_msatoshi?: number;
out_msat?: string | number;
fee?: number;
fee_msat?: string | number;
in_msat?: number;
out_msat?: number;
fee_msat?: number;
status?: string;
received_time?: number;
resolved_time?: number;
@ -266,8 +254,7 @@ export interface ForwardingEvent {
export interface LocalFailedEvent {
in_channel?: string;
in_channel_alias?: string;
in_msatoshi?: number;
in_msat?: string;
in_msat?: number;
out_channel?: string;
out_channel_alias?: string;
status?: string;
@ -287,7 +274,6 @@ export interface Routes {
id?: string;
channel?: string;
direction?: number;
msatoshi?: number;
amount_msat?: number;
delay?: number;
alias?: string;
@ -318,17 +304,11 @@ export interface Channel {
channel_id?: string;
funding_txid?: string;
private?: boolean;
msatoshi_to_us?: number; // For Backward compatibility
to_us_msat?: number;
msatoshi_to_them?: number; // For Backward compatibility
to_them_msat?: number;
msatoshi_total?: number; // For Backward compatibility
total_msat?: number;
their_channel_reserve_satoshis?: string; // For Backward compatibility
their_reserve_msat?: number;
our_channel_reserve_satoshis?: string; // For Backward compatibility
our_reserve_msat?: number;
spendable_msatoshi?: string; // For Backward compatibility
spendable_msat?: number;
direction?: number;
htlcs?: ChannelHTLC[];
@ -414,7 +394,6 @@ export interface FeeRates {
export interface UTXO {
txid?: string;
output?: number;
value?: number; // For Backward compatibility
amount_msat?: number;
status?: string;
blockheight?: string;

@ -137,8 +137,8 @@ export class CLNPageDefinitions {
graph_lookup: {
query_routes: TableDefinition;
};
peerswap: {
swaps: TableDefinition;
};
// peerswap: {
// swaps: TableDefinition;
// };
};

@ -39,7 +39,7 @@ export class CamelCaseWithSpacesPipe implements PipeTransform {
export class CamelCaseWithReplacePipe implements PipeTransform {
transform(value: string, arg1?: string, arg2?: string): string {
value = value?.toLowerCase().replace(/\s+/g, '')?.replace(/-/g, ' ');
value = value ? value.toLowerCase().replace(/\s+/g, '')?.replace(/-/g, ' ') : '';
if (arg1) {
value = value.replace(new RegExp(arg1, 'g'), ' ');
}

@ -12,7 +12,7 @@ export const HOUR_SECONDS = 3600;
export const DEFAULT_INVOICE_EXPIRY = HOUR_SECONDS * 24 * 7;
export const VERSION = '0.13.7-beta';
export const VERSION = '0.14.0-beta';
export const API_URL = isDevMode() ? 'http://localhost:3000/rtl/api' : './api';
@ -789,11 +789,11 @@ export const CLN_DEFAULT_PAGE_SETTINGS: PageSettings[] = [
{ tableId: 'query_routes', recordsPerPage: PAGE_SIZE, sortBy: 'msatoshi', sortOrder: SortOrderEnum.DESCENDING,
columnSelectionSM: ['alias', 'direction', 'msatoshi'],
columnSelection: ['alias', 'channel', 'direction', 'delay', 'msatoshi'] }
] },
{ pageId: 'peerswap', tables: [
{ tableId: 'swaps', recordsPerPage: PAGE_SIZE, sortBy: 'created_at', sortOrder: SortOrderEnum.DESCENDING,
columnSelectionSM: ['id', 'state', 'amount'],
columnSelection: ['id', 'alias', 'short_channel_id', 'created_at', 'state', 'amount'] }
// ] },
// { pageId: 'peerswap', tables: [
// { tableId: 'swaps', recordsPerPage: PAGE_SIZE, sortBy: 'created_at', sortOrder: SortOrderEnum.DESCENDING,
// columnSelectionSM: ['id', 'state', 'amount'],
// columnSelection: ['id', 'alias', 'short_channel_id', 'created_at', 'state', 'amount'] }
] }
];
@ -900,12 +900,12 @@ export const CLN_PAGE_DEFS: CLNPageDefinitions = {
maxColumns: 6,
allowedColumns: [{ column:'id' }, { column:'alias' }, { column:'channel' }, { column:'direction' }, { column:'delay' }, { column:'msatoshi', label: 'Amount' }]
}
},
peerswap: {
swaps: {
maxColumns: 6,
allowedColumns: [{ column:'id' }, { column:'alias' }, { column:'short_channel_id' }, { column:'created_at' }, { column:'state' }, { column:'amount' }]
}
// },
// peerswap: {
// swaps: {
// maxColumns: 6,
// allowedColumns: [{ column:'id' }, { column:'alias' }, { column:'short_channel_id' }, { column:'created_at' }, { column:'state' }, { column:'amount' }]
// }
}
};

@ -340,7 +340,7 @@ export class DataService implements OnDestroy {
map((res: any) => res),
catchError((err) => {
this.handleErrorWithoutAlert('Rebalance Channel', UI_MESSAGES.REBALANCE_CHANNEL, err);
return throwError(() => new Error(this.extractErrorMessage(err)));
return throwError(() => err.error);
})
);
}

@ -43,7 +43,7 @@
color: $foreground-text;
}
.mat-mdc-button-base.mat-mdc-unelevated-button.mat-primary {
color: $foreground-text;
color: $foreground-text !important;
}
.mat-mdc-option:hover:not(.mdc-list-item--disabled), .mat-mdc-option.mdc-list-item--selected:not(.mat-mdc-option-multiple):not(.mdc-list-item--disabled) {
& .mdc-list-item__primary-text {
@ -384,7 +384,6 @@
.material-icons {
&.info-icon {
font-size: 100%;
margin: 0 0.25rem;
color: $primary-darker;
&.info-icon-primary {
color: $primary-darker;

@ -311,7 +311,6 @@
.material-icons {
&.mat-icon-no-color, &.info-icon {
font-size: 100%;
margin: 0 0.25rem;
color: $foreground-secondary-text;
&.info-icon-primary {
color: $primary-color;

Loading…
Cancel
Save