CLT Routing Peers #711 (#760)

CLT Routing Peers #711
pull/762/head
ShahanaFarooqui 3 years ago committed by GitHub
parent 06ec43eefa
commit 6cf292f401
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -121,7 +121,7 @@
"no-undef-init": "error",
"no-undefined": "error",
"block-spacing": "error",
"brace-style": "error",
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
"comma-style": "error",
"func-call-spacing": "error",
"func-name-matching": "error",
@ -133,7 +133,7 @@
"lines-around-comment": "error",
"max-depth": "error",
"max-nested-callbacks": "error",
"max-statements-per-line": "error",
"max-statements-per-line": ["error", { "max": 2 }],
"no-array-constructor": "error",
"no-bitwise": "error",
"no-continue": "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

@ -13,6 +13,6 @@
<style>@font-face{font-family:Roboto;src:url(Roboto-Thin.dbd56bd3357dc3617fe5.woff2) format("woff2"),url(Roboto-Thin.e7f7c82374bd0ebef14b.woff) format("woff");font-weight:100;font-style:normal;}@font-face{font-family:Roboto;src:url(Roboto-ThinItalic.a8cef84f735ef887abdc.woff2) format("woff2"),url(Roboto-ThinItalic.5dd9349c940073834e9a.woff) format("woff");font-weight:100;font-style:italic;}@font-face{font-family:Roboto;src:url(Roboto-Light.c27d89ac77468ae18f28.woff2) format("woff2"),url(Roboto-Light.d923dfafc0c5183b59aa.woff) format("woff");font-weight:300;font-style:normal;}@font-face{font-family:Roboto;src:url(Roboto-LightItalic.506274c7228cf81cae4d.woff2) format("woff2"),url(Roboto-LightItalic.d4b8c137518d9d92bb28.woff) format("woff");font-weight:300;font-style:italic;}@font-face{font-family:Roboto;src:url(Roboto-Regular.64cfb66c866ea50cad47.woff2) format("woff2"),url(Roboto-Regular.e02e9d6ff5547f7e9962.woff) format("woff");font-weight:400;font-style:normal;}@font-face{font-family:Roboto;src:url(Roboto-RegularItalic.4dd2af1e8df532f41db8.woff2) format("woff2"),url(Roboto-RegularItalic.5ea38fff9eebef99c5df.woff) format("woff");font-weight:400;font-style:italic;}@font-face{font-family:Roboto;src:url(Roboto-Medium.1d3bced88509b0838984.woff2) format("woff2"),url(Roboto-Medium.092c6130df8fd2199888.woff) format("woff");font-weight:500;font-style:normal;}@font-face{font-family:Roboto;src:url(Roboto-MediumItalic.d620b8f53f75966fe42e.woff2) format("woff2"),url(Roboto-MediumItalic.18ff1628c628080166c1.woff) format("woff");font-weight:500;font-style:italic;}@font-face{font-family:Roboto;src:url(Roboto-Bold.92fbd4e93cf0a5dbebaa.woff2) format("woff2"),url(Roboto-Bold.73288d91c325e82a5b92.woff) format("woff");font-weight:700;font-style:normal;}@font-face{font-family:Roboto;src:url(Roboto-BoldItalic.5f600d98a73d800ae575.woff2) format("woff2"),url(Roboto-BoldItalic.6d89acbd21d7e3fbecb2.woff) format("woff");font-weight:700;font-style:italic;}@font-face{font-family:Roboto;src:url(Roboto-Black.41ed1105a6ebb8ffe34e.woff2) format("woff2"),url(Roboto-Black.937491dfcbe64ca9a9f1.woff) format("woff");font-weight:900;font-style:normal;}@font-face{font-family:Roboto;src:url(Roboto-BlackItalic.50ca4c51ebc27e7e7d2f.woff2) format("woff2"),url(Roboto-BlackItalic.2e1ee657996854c6f427.woff) format("woff");font-weight:900;font-style:italic;}html{width:100%;height:99%;line-height:1.5;overflow-x:hidden;font-family:Roboto,sans-serif!important;font-size:62.5%;}body{box-sizing:border-box;margin:0;}body{height:100%;overflow:hidden;}*{margin:0;padding:0;}</style><link rel="stylesheet" href="styles.08f05775866285e5b944.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.08f05775866285e5b944.css"></noscript></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.9aa9406c117fcac5f6b2.js" defer></script><script src="polyfills.a979cbbe16939013cdcf.js" defer></script><script src="main.5e46b79054d2ba64d8b4.js" defer></script>
<script src="runtime.685250420a13de37bff1.js" defer></script><script src="polyfills.a979cbbe16939013cdcf.js" defer></script><script src="main.ffe6d8aeb31791ae0a01.js" defer></script>
</body></html>

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
(()=>{"use strict";var e,r,t,o={},a={};function n(e){var r=a[e];if(void 0!==r)return r.exports;var t=a[e]={id:e,loaded:!1,exports:{}};return o[e].call(t.exports,t,t.exports,n),t.loaded=!0,t.exports}n.m=o,e=[],n.O=(r,t,o,a)=>{if(!t){var l=1/0;for(s=0;s<e.length;s++){for(var[t,o,a]=e[s],d=!0,i=0;i<t.length;i++)(!1&a||l>=a)&&Object.keys(n.O).every(e=>n.O[e](t[i]))?t.splice(i--,1):(d=!1,a<l&&(l=a));d&&(e.splice(s--,1),r=o())}return r}a=a||0;for(var s=e.length;s>0&&e[s-1][2]>a;s--)e[s]=e[s-1];e[s]=[t,o,a]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.f={},n.e=e=>Promise.all(Object.keys(n.f).reduce((r,t)=>(n.f[t](e,r),r),[])),n.u=e=>e+"."+{358:"77037545e0b6cfdc05f9",432:"edc184470c776a31dec4",891:"5f9b365bcec35211e41e",958:"a55d8156c48e68ddc825"}[e]+".js",n.miniCssF=e=>"styles.08f05775866285e5b944.css",n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="rtl:",n.l=(e,o,a,l)=>{if(r[e])r[e].push(o);else{var d,i;if(void 0!==a)for(var s=document.getElementsByTagName("script"),c=0;c<s.length;c++){var u=s[c];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==t+a){d=u;break}}d||(i=!0,(d=document.createElement("script")).charset="utf-8",d.timeout=120,n.nc&&d.setAttribute("nonce",n.nc),d.setAttribute("data-webpack",t+a),d.src=e),r[e]=[o];var f=(t,o)=>{d.onerror=d.onload=null,clearTimeout(p);var a=r[e];if(delete r[e],d.parentNode&&d.parentNode.removeChild(d),a&&a.forEach(e=>e(o)),t)return t(o)},p=setTimeout(f.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=f.bind(null,d.onerror),d.onload=f.bind(null,d.onload),i&&document.head.appendChild(d)}},n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),n.p="",(()=>{var e={666:0};n.f.j=(r,t)=>{var o=n.o(e,r)?e[r]:void 0;if(0!==o)if(o)t.push(o[2]);else if(666!=r){var a=new Promise((t,a)=>o=e[r]=[t,a]);t.push(o[2]=a);var l=n.p+n.u(r),d=new Error;n.l(l,t=>{if(n.o(e,r)&&(0!==(o=e[r])&&(e[r]=void 0),o)){var a=t&&("load"===t.type?"missing":t.type),l=t&&t.target&&t.target.src;d.message="Loading chunk "+r+" failed.\n("+a+": "+l+")",d.name="ChunkLoadError",d.type=a,d.request=l,o[1](d)}},"chunk-"+r,r)}else e[r]=0},n.O.j=r=>0===e[r];var r=(r,t)=>{var o,a,[l,d,i]=t,s=0;for(o in d)n.o(d,o)&&(n.m[o]=d[o]);if(i)var c=i(n);for(r&&r(t);s<l.length;s++)n.o(e,a=l[s])&&e[a]&&e[a][0](),e[l[s]]=0;return n.O(c)},t=self.webpackChunkrtl=self.webpackChunkrtl||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();

@ -1 +0,0 @@
(()=>{"use strict";var e,r,t,a={},o={};function n(e){var r=o[e];if(void 0!==r)return r.exports;var t=o[e]={id:e,loaded:!1,exports:{}};return a[e].call(t.exports,t,t.exports,n),t.loaded=!0,t.exports}n.m=a,e=[],n.O=(r,t,a,o)=>{if(!t){var l=1/0;for(s=0;s<e.length;s++){for(var[t,a,o]=e[s],d=!0,i=0;i<t.length;i++)(!1&o||l>=o)&&Object.keys(n.O).every(e=>n.O[e](t[i]))?t.splice(i--,1):(d=!1,o<l&&(l=o));d&&(e.splice(s--,1),r=a())}return r}o=o||0;for(var s=e.length;s>0&&e[s-1][2]>o;s--)e[s]=e[s-1];e[s]=[t,a,o]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.f={},n.e=e=>Promise.all(Object.keys(n.f).reduce((r,t)=>(n.f[t](e,r),r),[])),n.u=e=>e+"."+{432:"d41638407d6f035aaed4",646:"04e55a7f093b0837f9ef",891:"49f1365f7587aa4498c1",958:"a55d8156c48e68ddc825"}[e]+".js",n.miniCssF=e=>"styles.08f05775866285e5b944.css",n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="rtl:",n.l=(e,a,o,l)=>{if(r[e])r[e].push(a);else{var d,i;if(void 0!==o)for(var s=document.getElementsByTagName("script"),u=0;u<s.length;u++){var f=s[u];if(f.getAttribute("src")==e||f.getAttribute("data-webpack")==t+o){d=f;break}}d||(i=!0,(d=document.createElement("script")).charset="utf-8",d.timeout=120,n.nc&&d.setAttribute("nonce",n.nc),d.setAttribute("data-webpack",t+o),d.src=e),r[e]=[a];var c=(t,a)=>{d.onerror=d.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],d.parentNode&&d.parentNode.removeChild(d),o&&o.forEach(e=>e(a)),t)return t(a)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=c.bind(null,d.onerror),d.onload=c.bind(null,d.onload),i&&document.head.appendChild(d)}},n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),n.p="",(()=>{var e={666:0};n.f.j=(r,t)=>{var a=n.o(e,r)?e[r]:void 0;if(0!==a)if(a)t.push(a[2]);else if(666!=r){var o=new Promise((t,o)=>a=e[r]=[t,o]);t.push(a[2]=o);var l=n.p+n.u(r),d=new Error;n.l(l,t=>{if(n.o(e,r)&&(0!==(a=e[r])&&(e[r]=void 0),a)){var o=t&&("load"===t.type?"missing":t.type),l=t&&t.target&&t.target.src;d.message="Loading chunk "+r+" failed.\n("+o+": "+l+")",d.name="ChunkLoadError",d.type=o,d.request=l,a[1](d)}},"chunk-"+r,r)}else e[r]=0},n.O.j=r=>0===e[r];var r=(r,t)=>{var a,o,[l,d,i]=t,s=0;for(a in d)n.o(d,a)&&(n.m[a]=d[a]);if(i)var u=i(n);for(r&&r(t);s<l.length;s++)n.o(e,o=l[s])&&e[o]&&e[o][0](),e[l[s]]=0;return n.O(u)},t=self.webpackChunkrtl=self.webpackChunkrtl||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();

@ -20,6 +20,7 @@ import { CLLookupsComponent } from './lookups/lookups.component';
import { CLRoutingComponent } from './routing/routing.component';
import { CLForwardingHistoryComponent } from './routing/forwarding-history/forwarding-history.component';
import { CLFailedTransactionsComponent } from './routing/failed-transactions/failed-transactions.component';
import { CLRoutingPeersComponent } from './routing/routing-peers/routing-peers.component';
import { CLChannelLookupComponent } from './lookups/channel-lookup/channel-lookup.component';
import { CLNodeLookupComponent } from './lookups/node-lookup/node-lookup.component';
import { CLQueryRoutesComponent } from './transactions/query-routes/query-routes.component';
@ -68,6 +69,7 @@ import { CLUnlockedGuard } from '../shared/services/auth.guard';
CLRoutingComponent,
CLForwardingHistoryComponent,
CLFailedTransactionsComponent,
CLRoutingPeersComponent,
CLChannelLookupComponent,
CLNodeLookupComponent,
CLQueryRoutesComponent,

@ -23,6 +23,8 @@ import { CLSignComponent } from './sign-verify-message/sign/sign.component';
import { CLVerifyComponent } from './sign-verify-message/verify/verify.component';
import { CLForwardingHistoryComponent } from './routing/forwarding-history/forwarding-history.component';
import { CLFailedTransactionsComponent } from './routing/failed-transactions/failed-transactions.component';
import { CLRoutingPeersComponent } from './routing/routing-peers/routing-peers.component';
import { CLReportsComponent } from './reports/reports.component';
import { CLFeeReportComponent } from './reports/fee/fee-report.component';
import { CLTransactionsReportComponent } from './reports/transactions/transactions-report.component';
@ -63,7 +65,8 @@ export const ClRoutes: Routes = [
{ path: 'routing', component: CLRoutingComponent, canActivate: [CLUnlockedGuard], children: [
{ path: '', pathMatch: 'full', redirectTo: 'forwardinghistory' },
{ path: 'forwardinghistory', component: CLForwardingHistoryComponent, canActivate: [CLUnlockedGuard] },
{ path: 'failedtransactions', component: CLFailedTransactionsComponent, canActivate: [CLUnlockedGuard] }
{ path: 'failedtransactions', component: CLFailedTransactionsComponent, canActivate: [CLUnlockedGuard] },
{ path: 'routingpeers', component: CLRoutingPeersComponent, canActivate: [CLUnlockedGuard] }
] },
{ path: 'reports', component: CLReportsComponent, canActivate: [CLUnlockedGuard], children: [
{ path: '', pathMatch: 'full', redirectTo: 'routingfees' },

@ -19,7 +19,7 @@
</ng-container>
<ng-container matColumnDef="in_channel">
<th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.in_channel_alias || fhEvent?.in_channel}}</td>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.in_channel_alias}}</td>
</ng-container>
<ng-container matColumnDef="in_msatoshi">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Amount In (Sats)</th>

@ -87,7 +87,7 @@ export class CLFailedTransactionsComponent implements OnInit, AfterViewInit, OnD
[{ key: 'payment_hash', value: selFEvent.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING }],
[{ key: 'status', value: (selFEvent.status === 'settled' ? 'Settled' : 'Unsettled'), title: 'Status', width: 50, type: DataTypeEnum.STRING },
{ key: 'received_time', value: selFEvent.received_time, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME }],
[{ key: 'in_channel', value: selFEvent.in_channel_alias ? selFEvent.in_channel_alias : selFEvent.in_channel, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING },
[{ key: 'in_channel', value: selFEvent.in_channel_alias, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING },
{ key: 'in_msatoshi', value: selFEvent.in_msatoshi, title: 'In (mSats)', width: 50, type: DataTypeEnum.NUMBER }]
];
this.store.dispatch(new RTLActions.OpenAlert({ data: {

@ -23,11 +23,11 @@
</ng-container>
<ng-container matColumnDef="in_channel">
<th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.in_channel_alias || fhEvent?.in_channel}}</td>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.in_channel_alias}}</td>
</ng-container>
<ng-container matColumnDef="out_channel">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.out_channel_alias || fhEvent?.out_channel}}</td>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.out_channel_alias}}</td>
</ng-container>
<ng-container matColumnDef="in_msatoshi">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Amount In (Sats)</th>

@ -106,8 +106,8 @@ export class CLForwardingHistoryComponent implements OnInit, OnChanges, AfterVie
{ key: 'fee', value: selFEvent.fee, 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 ? selFEvent.in_channel_alias : selFEvent.in_channel, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING },
{ key: 'out_channel', value: selFEvent.out_channel_alias ? selFEvent.out_channel_alias : selFEvent.out_channel, title: 'Outbound Channel', width: 50, type: DataTypeEnum.STRING }],
[{ 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, title: 'In (mSats)', width: 50, type: DataTypeEnum.NUMBER },
{ key: 'out_msatoshi', value: selFEvent.out_msatoshi, title: 'Out (mSats)', width: 50, type: DataTypeEnum.NUMBER }]
];

@ -0,0 +1,95 @@
<div fxLayout="column" fxLayoutAlign="start stretch" class="padding-gap-x">
<div class="p-2 error-border my-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-md="row" fxFlex="100" fxLayoutAlign="space-between stretch" class="page-sub-title-container">
<div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}">
<div fxFlex="70">Incoming</div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyIncomingFilter($event.target)" placeholder="Filter">
</mat-form-field>
</div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableIn [dataSource]="RoutingPeersIncoming" matSort class="overflow-auto incoming-table">
<ng-container matColumnDef="channel_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '5rem' : '10rem'}">{{rPeer.channel_id}}</td>
</ng-container>
<ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th>
<td mat-cell *matCellDef="let rPeer" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '5rem' : '10rem'}">{{rPeer.alias}}</td>
</ng-container>
<ng-container matColumnDef="events">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Events</th>
<td mat-cell *matCellDef="let rPeer"><span fxLayoutAlign="end center">{{rPeer.events | number}}</span>
</td>
</ng-container>
<ng-container matColumnDef="total_amount">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Amount (Sats)</th>
<td mat-cell *matCellDef="let rPeer"><span fxLayoutAlign="end center">{{rPeer.total_amount | number}}</span></td>
</ng-container>
<ng-container matColumnDef="total_fee">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Fee (Sats)</th>
<td mat-cell *matCellDef="let rPeer"><span fxLayoutAlign="end center">{{rPeer.total_fee | number}}</span></td>
</ng-container>
<ng-container matColumnDef="no_incoming_event">
<td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.COMPLETED">No incoming routing peer available.</p>
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.INITIATED">Getting incoming routing peers...</p>
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td>
</ng-container>
<tr mat-footer-row *matFooterRowDef="['no_incoming_event']" [ngClass]="{'display-none': RoutingPeersIncoming?.data && RoutingPeersIncoming?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<mat-paginator #paginatorIn [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div>
<div fxLayout="column" fxFlex="49" fxLayoutAlign="end stretch">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}">
<div fxFlex="70">Outgoing</div>
<mat-form-field fxFlex="30">
<input matInput #filterOut (keyup)="applyOutgoingFilter($event.target)" placeholder="Filter">
</mat-form-field>
</div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableOut [dataSource]="RoutingPeersOutgoing" matSort class="overflow-auto outgoing-table">
<ng-container matColumnDef="channel_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '5rem' : '10rem'}">{{rPeer.channel_id}}</td>
</ng-container>
<ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th>
<td mat-cell *matCellDef="let rPeer" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '5rem' : '10rem'}">{{rPeer.alias}}</td>
</ng-container>
<ng-container matColumnDef="events">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Events</th>
<td mat-cell *matCellDef="let rPeer"><span fxLayoutAlign="end center">{{rPeer.events | number}}</span>
</td>
</ng-container>
<ng-container matColumnDef="total_amount">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Amount (Sats)</th>
<td mat-cell *matCellDef="let rPeer"><span fxLayoutAlign="end center">{{rPeer.total_amount | number}}</span></td>
</ng-container>
<ng-container matColumnDef="total_fee">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Fee (Sats)</th>
<td mat-cell *matCellDef="let rPeer"><span fxLayoutAlign="end center">{{rPeer.total_fee | number}}</span></td>
</ng-container>
<ng-container matColumnDef="no_outgoing_event">
<td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.COMPLETED">No outgoing routing peer available.</p>
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.INITIATED">Getting outgoing routing peers...</p>
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td>
</ng-container>
<tr mat-footer-row *matFooterRowDef="['no_outgoing_event']" [ngClass]="{'display-none': RoutingPeersOutgoing?.data && RoutingPeersOutgoing?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator #paginatorOut [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div>
</div>
</div>
</div>

@ -0,0 +1,6 @@
.mat-column-channelId, .mat-column-alias {
flex: 1 1 10%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

@ -0,0 +1,52 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { StoreModule } from '@ngrx/store';
import { RTLReducer } from '../../../store/rtl.reducers';
import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service';
import { CLRoutingPeersComponent } from './routing-peers.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SharedModule } from '../../../shared/shared.module';
import { DataService } from '../../../shared/services/data.service';
import { mockDataService, mockLoggerService } from '../../../shared/test-helpers/mock-services';
describe('CLRoutingPeersComponent', () => {
let component: CLRoutingPeersComponent;
let fixture: ComponentFixture<CLRoutingPeersComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [CLRoutingPeersComponent],
imports: [
BrowserAnimationsModule,
SharedModule,
StoreModule.forRoot(RTLReducer, {
runtimeChecks: {
strictStateImmutability: false,
strictActionImmutability: false
}
})
],
providers: [
CommonService,
{ provide: LoggerService, useClass: mockLoggerService },
{ provide: DataService, useClass: mockDataService }
]
}).
compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CLRoutingPeersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
afterEach(() => {
TestBed.resetTestingModule();
});
});

@ -0,0 +1,164 @@
import { Component, OnInit, AfterViewInit, ViewChild, OnDestroy, Input, SimpleChanges, OnChanges } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { MatSort } from '@angular/material/sort';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum } from '../../../shared/services/consts-enums-functions';
import { ForwardingEvent, RoutingPeer } from '../../../shared/models/clModels';
import { ApiCallsListCL } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service';
import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-cl-routing-peers',
templateUrl: './routing-peers.component.html',
styleUrls: ['./routing-peers.component.scss'],
providers: [
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Peers') }
]
})
export class CLRoutingPeersComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
@ViewChild('tableIn', { read: MatSort, static: false }) sortIn: MatSort;
@ViewChild('tableOut', { read: MatSort, static: false }) sortOut: MatSort;
@ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator|undefined;
@ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator|undefined;
@Input() eventsData = [];
@Input() filterValue = '';
public successfulEvents = [];
public displayedColumns: any[] = [];
public RoutingPeersIncoming: any = [];
public RoutingPeersOutgoing: any = [];
public flgSticky = false;
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
public screenSize = '';
public screenSizeEnum = ScreenSizeEnum;
public errorMessage = '';
public apisCallStatus: ApiCallsListCL = null;
public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<fromRTLReducer.RTLState>) {
this.screenSize = this.commonService.getScreenSize();
if (this.screenSize === ScreenSizeEnum.XS) {
this.flgSticky = false;
this.displayedColumns = ['alias', 'total_fee'];
} else if (this.screenSize === ScreenSizeEnum.SM) {
this.flgSticky = false;
this.displayedColumns = ['alias', 'events', 'total_fee'];
} else if (this.screenSize === ScreenSizeEnum.MD) {
this.flgSticky = false;
this.displayedColumns = ['alias', 'events', 'total_amount', 'total_fee'];
} else {
this.flgSticky = true;
this.displayedColumns = ['channel_id', 'alias', 'events', 'total_amount', 'total_fee'];
}
}
ngOnInit() {
this.store.select('cl').
pipe(takeUntil(this.unSubs[0])).
subscribe((rtlStore) => {
if (this.eventsData.length <= 0) {
this.errorMessage = '';
this.apisCallStatus = rtlStore.apisCallStatus;
if (this.apisCallStatus.GetForwardingHistory.status === APICallStatusEnum.ERROR) {
this.errorMessage = (typeof (this.apisCallStatus.GetForwardingHistory.message) === 'object') ? JSON.stringify(this.apisCallStatus.GetForwardingHistory.message) : this.apisCallStatus.GetForwardingHistory.message;
}
this.successfulEvents = (rtlStore.forwardingHistory && rtlStore.forwardingHistory.forwarding_events && rtlStore.forwardingHistory.forwarding_events.length > 0) ? this.filterSuccessfulEvents(rtlStore.forwardingHistory.forwarding_events) : [];
if (this.successfulEvents.length > 0 && this.sortIn && this.paginatorIn && this.sortOut && this.paginatorOut) {
this.loadRoutingPeersTable(this.successfulEvents);
}
this.logger.info(rtlStore);
}
});
}
ngAfterViewInit() {
if (this.successfulEvents.length > 0) {
this.loadRoutingPeersTable(this.successfulEvents);
}
}
ngOnChanges(changes: SimpleChanges) {
if (changes.eventsData) {
this.eventsData = changes.eventsData.currentValue;
this.successfulEvents = this.eventsData;
if (!changes.eventsData.firstChange) {
this.loadRoutingPeersTable(this.successfulEvents);
}
}
}
filterSuccessfulEvents(events) {
return events.filter((event) => event.status === 'settled');
}
loadRoutingPeersTable(events: ForwardingEvent[]) {
if (events.length > 0) {
const results = this.groupRoutingPeers(events);
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeer[]>(results[0]);
this.RoutingPeersIncoming.sort = this.sortIn;
this.RoutingPeersIncoming.filterPredicate = (rpIn: RoutingPeer, fltr: string) => JSON.stringify(rpIn).toLowerCase().includes(fltr);
this.RoutingPeersIncoming.paginator = this.paginatorIn;
this.logger.info(this.RoutingPeersIncoming);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeer[]>(results[1]);
this.RoutingPeersOutgoing.sort = this.sortOut;
this.RoutingPeersOutgoing.filterPredicate = (rpOut: RoutingPeer, fltr: string) => JSON.stringify(rpOut).toLowerCase().includes(fltr);
this.RoutingPeersOutgoing.paginator = this.paginatorOut;
this.logger.info(this.RoutingPeersOutgoing);
} else {
// To reset table after other Forwarding history calls
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeer>([]);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeer>([]);
}
this.logger.info(this.RoutingPeersIncoming);
this.logger.info(this.RoutingPeersOutgoing);
}
groupRoutingPeers(forwardingEvents: ForwardingEvent[]) {
const incomingResults: RoutingPeer[] = [];
const outgoingResults: RoutingPeer[] = [];
forwardingEvents.forEach((event) => {
const incoming = incomingResults.find((result) => result.channel_id === event.in_channel);
const outgoing = 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, total_fee: (event.in_msatoshi - event.out_msatoshi) });
} else {
incoming.events++;
incoming.total_amount = +incoming.total_amount + +event.in_msatoshi;
incoming.total_fee = +incoming.total_fee + (event.in_msatoshi - event.out_msatoshi);
}
if (!outgoing) {
outgoingResults.push({ channel_id: event.out_channel, alias: event.out_channel_alias, events: 1, total_amount: event.out_msatoshi, total_fee: (event.in_msatoshi - event.out_msatoshi) });
} else {
outgoing.events++;
outgoing.total_amount = +outgoing.total_amount + +event.out_msatoshi;
outgoing.total_fee = +outgoing.total_fee + (event.in_msatoshi - event.out_msatoshi);
}
});
return [this.commonService.sortDescByKey(incomingResults, 'total_fee'), this.commonService.sortDescByKey(outgoingResults, 'total_fee')];
}
applyIncomingFilter(selFilter: any) {
this.RoutingPeersIncoming.filter = selFilter.value.trim().toLowerCase();
}
applyOutgoingFilter(selFilter: any) {
this.RoutingPeersOutgoing.filter = selFilter.value.trim().toLowerCase();
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(null);
completeSub.complete();
});
}
}

@ -1,4 +1,4 @@
<div fxLayout="column">
<div fxLayout="column" class="mb-2">
<div fxLayout="row" fxLayoutAlign="start center" class="page-title-container">
<fa-icon [icon]="faMapSigns" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Routing</span>

@ -12,7 +12,7 @@ import { faMapSigns } from '@fortawesome/free-solid-svg-icons';
export class CLRoutingComponent implements OnInit, OnDestroy {
public faMapSigns = faMapSigns;
public links = [{ link: 'forwardinghistory', name: 'Forwarding History' }, { link: 'failedtransactions', name: 'Failed Transactions' }];
public links = [{ link: 'forwardinghistory', name: 'Forwarding History' }, { link: 'failedtransactions', name: 'Failed Transactions' }, { link: 'routingpeers', name: 'Routing Peers' }];
public activeLink = this.links[0].link;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];

@ -156,25 +156,28 @@ export function CLReducer(state = initCLState, action: CLActions.CLActions) {
const modifiedFeeWithTxCount = state.fees;
if (action.payload.forwarding_events && action.payload.forwarding_events.length > 0) {
const storedChannels = [...state.allChannels];
action.payload.forwarding_events.forEach((event) => {
action.payload.forwarding_events.forEach((fhEvent, i) => {
if (storedChannels && storedChannels.length > 0) {
for (let idx = 0; idx < storedChannels.length; idx++) {
if (storedChannels[idx].short_channel_id && storedChannels[idx].short_channel_id === event.in_channel) {
event.in_channel_alias = storedChannels[idx].alias ? storedChannels[idx].alias : event.in_channel;
if (event.out_channel_alias) {
return;
}
if (storedChannels[idx].short_channel_id && storedChannels[idx].short_channel_id === fhEvent.in_channel) {
fhEvent.in_channel_alias = storedChannels[idx].alias ? storedChannels[idx].alias : fhEvent.in_channel;
if (fhEvent.out_channel_alias) { return; }
}
if (storedChannels[idx].short_channel_id && storedChannels[idx].short_channel_id.toString() === event.out_channel) {
event.out_channel_alias = storedChannels[idx].alias ? storedChannels[idx].alias : event.out_channel;
if (event.in_channel_alias) {
return;
}
if (storedChannels[idx].short_channel_id && storedChannels[idx].short_channel_id.toString() === fhEvent.out_channel) {
fhEvent.out_channel_alias = storedChannels[idx].alias ? storedChannels[idx].alias : fhEvent.out_channel;
if (fhEvent.in_channel_alias) { return; }
}
if (idx === storedChannels.length - 1) {
if (!fhEvent.in_channel_alias) { fhEvent.in_channel_alias = fhEvent.in_channel; }
if (!fhEvent.out_channel_alias) { fhEvent.out_channel_alias = fhEvent.out_channel; }
}
}
} else {
fhEvent.in_channel_alias = fhEvent.in_channel;
fhEvent.out_channel_alias = fhEvent.out_channel;
}
});
modifiedFeeWithTxCount.totalTxCount = action.payload.forwarding_events.filter((event) => event.status === 'settled').length;
modifiedFeeWithTxCount.totalTxCount = action.payload.forwarding_events.filter((fhEvent) => fhEvent.status === 'settled').length;
} else {
action.payload = {};
}

@ -10,7 +10,7 @@
</div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apisCallStatus?.FetchPayments.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableIn fxFlex="100" [dataSource]="RoutingPeersIncoming" matSort class="overflow-auto incoming-table">
<table mat-table #tableIn [dataSource]="RoutingPeersIncoming" matSort class="overflow-auto incoming-table">
<ng-container matColumnDef="channelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '5rem' : '10rem'}">{{rPeer.channelId}}</td>
@ -55,7 +55,7 @@
</div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apisCallStatus?.FetchPayments.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableOut fxFlex="100" [dataSource]="RoutingPeersOutgoing" matSort class="overflow-auto outgoing-table">
<table mat-table #tableOut [dataSource]="RoutingPeersOutgoing" matSort class="overflow-auto outgoing-table">
<ng-container matColumnDef="channelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '5rem' : '10rem'}">{{rPeer.channelId}}</td>

@ -24,7 +24,7 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
})
export class ECLRoutingPeersComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild(MatSort, { static: false }) sortIn: MatSort;
@ViewChild('tableIn', { read: MatSort, static: false }) sortIn: MatSort;
@ViewChild('tableOut', { read: MatSort, static: false }) sortOut: MatSort;
@ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator|undefined;
@ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator|undefined;

@ -147,39 +147,39 @@ export function ECLReducer(state = initECLState, action: ECLActions.ECLActions)
case ECLActions.SET_PAYMENTS_ECL:
if (action.payload && action.payload.relayed) {
const storedChannels = [...state.activeChannels, ...state.pendingChannels, ...state.inactiveChannels];
action.payload.relayed.forEach((event) => {
action.payload.relayed.forEach((rlEvent) => {
if (storedChannels && storedChannels.length > 0) {
for (let idx = 0; idx < storedChannels.length; idx++) {
if (storedChannels[idx].channelId.toString() === event.fromChannelId) {
event.fromChannelAlias = storedChannels[idx].alias ? storedChannels[idx].alias : event.fromChannelId;
event.fromShortChannelId = storedChannels[idx].shortChannelId ? storedChannels[idx].shortChannelId : '';
if (event.toChannelAlias) {
if (storedChannels[idx].channelId.toString() === rlEvent.fromChannelId) {
rlEvent.fromChannelAlias = storedChannels[idx].alias ? storedChannels[idx].alias : rlEvent.fromChannelId;
rlEvent.fromShortChannelId = storedChannels[idx].shortChannelId ? storedChannels[idx].shortChannelId : '';
if (rlEvent.toChannelAlias) {
return;
}
}
if (storedChannels[idx].channelId.toString() === event.toChannelId) {
event.toChannelAlias = storedChannels[idx].alias ? storedChannels[idx].alias : event.toChannelId;
event.toShortChannelId = storedChannels[idx].shortChannelId ? storedChannels[idx].shortChannelId : '';
if (event.fromChannelAlias) {
if (storedChannels[idx].channelId.toString() === rlEvent.toChannelId) {
rlEvent.toChannelAlias = storedChannels[idx].alias ? storedChannels[idx].alias : rlEvent.toChannelId;
rlEvent.toShortChannelId = storedChannels[idx].shortChannelId ? storedChannels[idx].shortChannelId : '';
if (rlEvent.fromChannelAlias) {
return;
}
}
if (idx === storedChannels.length - 1) {
if (!event.fromChannelAlias) {
event.fromChannelAlias = event.fromChannelId.substring(0, 17) + '...';
event.fromShortChannelId = '';
if (!rlEvent.fromChannelAlias) {
rlEvent.fromChannelAlias = rlEvent.fromChannelId.substring(0, 17) + '...';
rlEvent.fromShortChannelId = '';
}
if (!event.toChannelAlias) {
event.toChannelAlias = event.toChannelId.substring(0, 17) + '...';
event.toShortChannelId = '';
if (!rlEvent.toChannelAlias) {
rlEvent.toChannelAlias = rlEvent.toChannelId.substring(0, 17) + '...';
rlEvent.toShortChannelId = '';
}
}
}
} else {
event.fromChannelAlias = event.fromChannelId.substring(0, 17) + '...';
event.fromShortChannelId = '';
event.toChannelAlias = event.toChannelId.substring(0, 17) + '...';
event.toShortChannelId = '';
rlEvent.fromChannelAlias = rlEvent.fromChannelId.substring(0, 17) + '...';
rlEvent.fromShortChannelId = '';
rlEvent.toChannelAlias = rlEvent.toChannelId.substring(0, 17) + '...';
rlEvent.toShortChannelId = '';
}
});
}

@ -5,12 +5,12 @@
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}">
<div fxFlex="70">Incoming</div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyIncomingFilter($event.target)" placeholder="Filter">
<input matInput [(ngModel)]="filterIn" (keyup)="applyIncomingFilter($event.target)" placeholder="Filter">
</mat-form-field>
</div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableIn fxFlex="100" [dataSource]="RoutingPeersIncoming" matSort class="overflow-auto incoming-table">
<table mat-table #tableIn [dataSource]="RoutingPeersIncoming" matSort class="overflow-auto incoming-table">
<ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '28rem'}">{{rPeer.chan_id}}</td>
@ -46,17 +46,18 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<mat-paginator #paginatorIn [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div>
<div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch" class="mb-4">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}">
<div fxFlex="70">Outgoing</div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyOutgoingFilter($event.target)" placeholder="Filter">
<input matInput [(ngModel)]="filterOut" (keyup)="applyOutgoingFilter($event.target)" placeholder="Filter">
</mat-form-field>
</div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apisCallStatus?.GetForwardingHistory.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableOut fxFlex="100" [dataSource]="RoutingPeersOutgoing" matSort class="overflow-auto outgoing-table">
<table mat-table #tableOut [dataSource]="RoutingPeersOutgoing" matSort class="overflow-auto outgoing-table">
<ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '28rem'}">{{rPeer.chan_id}}</td>
@ -92,6 +93,7 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<mat-paginator #paginatorOut [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
</div>
</div>
</div>

@ -4,9 +4,10 @@ import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { ForwardingEvent, RoutingPeers } from '../../../shared/models/lndModels';
import { AlertTypeEnum, APICallStatusEnum, DataTypeEnum, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
import { AlertTypeEnum, APICallStatusEnum, DataTypeEnum, getPaginatorLabel, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
import { ApiCallsListLND } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service';
@ -17,20 +18,29 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-routing-peers',
templateUrl: './routing-peers.component.html',
styleUrls: ['./routing-peers.component.scss']
styleUrls: ['./routing-peers.component.scss'],
providers: [
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Peers') }
]
})
export class RoutingPeersComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: false }) sortIn: MatSort;
@ViewChild('tableIn', { read: MatSort, static: false }) sortIn: MatSort;
@ViewChild('tableOut', { read: MatSort, static: false }) sortOut: MatSort;
@ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator|undefined;
@ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator|undefined;
public routingPeersData = [];
public displayedColumns: any[] = [];
public RoutingPeersIncoming: any;
public RoutingPeersOutgoing: any;
public flgSticky = false;
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
public screenSize = '';
public screenSizeEnum = ScreenSizeEnum;
public errorMessage = '';
public filterIn = '';
public filterOut = '';
public apisCallStatus: ApiCallsListLND = null;
public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
@ -66,7 +76,9 @@ export class RoutingPeersComponent implements OnInit, OnDestroy {
} else {
this.routingPeersData = [];
}
this.loadRoutingPeersTable(this.routingPeersData);
if (this.routingPeersData.length > 0 && this.sortIn && this.paginatorIn && this.sortOut && this.paginatorOut) {
this.loadRoutingPeersTable(this.routingPeersData);
}
this.logger.info(rtlStore);
});
}
@ -92,15 +104,19 @@ export class RoutingPeersComponent implements OnInit, OnDestroy {
}
loadRoutingPeersTable(forwardingEvents: ForwardingEvent[]) {
this.filterIn = '';
this.filterOut = '';
if (forwardingEvents.length > 0) {
const results = this.groupRoutingPeers(forwardingEvents);
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeers>(results[0]);
this.RoutingPeersIncoming.sort = this.sortIn;
this.RoutingPeersIncoming.filterPredicate = (rpIn: RoutingPeers, fltr: string) => JSON.stringify(rpIn).toLowerCase().includes(fltr);
this.RoutingPeersIncoming.paginator = this.paginatorIn;
this.logger.info(this.RoutingPeersIncoming);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeers>(results[1]);
this.RoutingPeersOutgoing.sort = this.sortOut;
this.RoutingPeersOutgoing.filterPredicate = (rpOut: RoutingPeers, fltr: string) => JSON.stringify(rpOut).toLowerCase().includes(fltr);
this.RoutingPeersOutgoing.paginator = this.paginatorOut;
this.logger.info(this.RoutingPeersOutgoing);
} else {
// To reset table after other Forwarding history calls

@ -267,33 +267,33 @@ export function LNDReducer(state = initLNDState, action: LNDActions.LNDActions)
case LNDActions.SET_FORWARDING_HISTORY_LND:
if (action.payload.forwarding_events) {
const storedChannels = [...state.allChannels, ...state.closedChannels];
action.payload.forwarding_events.forEach((event) => {
action.payload.forwarding_events.forEach((fhEvent) => {
if (storedChannels && storedChannels.length > 0) {
for (let idx = 0; idx < storedChannels.length; idx++) {
if (storedChannels[idx].chan_id.toString() === event.chan_id_in) {
event.alias_in = storedChannels[idx].remote_alias ? storedChannels[idx].remote_alias : event.chan_id_in;
if (event.alias_out) {
if (storedChannels[idx].chan_id.toString() === fhEvent.chan_id_in) {
fhEvent.alias_in = storedChannels[idx].remote_alias ? storedChannels[idx].remote_alias : fhEvent.chan_id_in;
if (fhEvent.alias_out) {
return;
}
}
if (storedChannels[idx].chan_id.toString() === event.chan_id_out) {
event.alias_out = storedChannels[idx].remote_alias ? storedChannels[idx].remote_alias : event.chan_id_out;
if (event.alias_in) {
if (storedChannels[idx].chan_id.toString() === fhEvent.chan_id_out) {
fhEvent.alias_out = storedChannels[idx].remote_alias ? storedChannels[idx].remote_alias : fhEvent.chan_id_out;
if (fhEvent.alias_in) {
return;
}
}
if (idx === storedChannels.length - 1) {
if (!event.alias_in) {
event.alias_in = event.chan_id_in;
if (!fhEvent.alias_in) {
fhEvent.alias_in = fhEvent.chan_id_in;
}
if (!event.alias_out) {
event.alias_out = event.chan_id_out;
if (!fhEvent.alias_out) {
fhEvent.alias_out = fhEvent.chan_id_out;
}
}
}
} else {
event.alias_in = event.chan_id_in;
event.alias_out = event.chan_id_out;
fhEvent.alias_in = fhEvent.chan_id_in;
fhEvent.alias_out = fhEvent.chan_id_out;
}
});
} else {

@ -268,3 +268,11 @@ export interface UTXO {
address?: string;
amount_msat?: string;
}
export interface RoutingPeer {
channel_id?: string;
alias?: string;
events?: number;
total_amount?: number;
total_fee?: number;
}

Loading…
Cancel
Save