Forwarding History

Forwarding History
pull/209/head
Shahana Farooqui 5 years ago
parent c671f9d751
commit 56d47b7afa

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

@ -9,5 +9,5 @@
<link rel="stylesheet" href="styles.13a9674cdbdfd014a4cf.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.3096ec57d9439bc5d703.js"></script><script src="polyfills-es5.763f4f23e8aee5ec234d.js" nomodule></script><script src="polyfills.e59b6f9dc696bd89cf7f.js"></script><script src="main.264978b883129045db62.js"></script></body>
<script src="runtime.04b3d5b5c3fa2d5708c0.js"></script><script src="polyfills-es5.763f4f23e8aee5ec234d.js" nomodule></script><script src="polyfills.e59b6f9dc696bd89cf7f.js"></script><script src="main.1c9e26206d1b7d79ae0c.js"></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

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

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

@ -102,47 +102,32 @@ exports.getLocalRemoteBalance = (req, res, next) => {
exports.listForwards = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/switch';
options.form = {};
if (undefined !== req.body.num_max_events) {
options.form.num_max_events = req.body.num_max_events;
}
if (undefined !== req.body.index_offset) {
options.form.index_offset = req.body.index_offset;
}
if (undefined !== req.body.end_time) {
options.form.end_time = req.body.end_time;
}
if (undefined !== req.body.start_time) {
options.form.start_time = req.body.start_time;
}
options.form = JSON.stringify(options.form);
logger.info({fileName: 'Switch', msg: 'Switch Post Options: ' + JSON.stringify(options)});
request.post(options).then((body) => {
logger.info({fileName: 'Switch', msg: 'Switch Post Response: ' + JSON.stringify(body)});
options.url = common.getSelLNServerUrl() + '/channel/listForwards/';
request.get(options).then((body) => {
logger.info({fileName: 'Channels', msg: 'Forwarding History Response: ' + JSON.stringify(body)});
if(undefined === body || body.error) {
logger.error({fileName: 'Switch', lineNum: 27, msg: 'Switch Post Erroe: ' + JSON.stringify((undefined === body) ? 'Error From Server!' : body.error)});
logger.error({fileName: 'Channels', lineNum: 27, msg: 'Forwarding History Error: ' + JSON.stringify((undefined === body) ? 'Error From Server!' : body.error)});
res.status(500).json({
message: "Switch post failed!",
message: "Forwarding History Failed!",
error: (undefined === body) ? 'Error From Server!' : body.error
});
} else {
if (undefined !== body.forwarding_events) {
body.forwarding_events.forEach(event => {
event.timestamp_str = (undefined === event.timestamp) ? '' : common.convertTimestampToDate(event.timestamp);
if (body.length > 0) {
body.forEach(event => {
event.received_time_str = (undefined === event.received_time) ? '' : common.convertTimestampToDate(event.received_time);
event.resolved_time_str = (undefined === event.resolved_time) ? '' : common.convertTimestampToDate(event.resolved_time);
});
body.forwarding_events = common.sortDescByKey(body.forwarding_events, 'timestamp');
body = common.sortDescByKey(body, 'received_time');
}
logger.info({fileName: 'Switch', msg: 'Forwarding History Received: ' + JSON.stringify(body)});
res.status(201).json(body);
logger.info({fileName: 'Channels', msg: 'Forwarding History Received: ' + JSON.stringify(body)});
res.status(200).json({ last_offset_index: 0, forwarding_events: body });
}
})
.catch(function (err) {
logger.error({fileName: 'Switch', lineNum: 44, msg: 'Switch Post Error: ' + JSON.stringify(err)});
logger.error({fileName: 'Channels', lineNum: 44, msg: 'Forwarding History Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Switch post failed!",
message: "Forwarding History Failed!",
error: err.error
});
});
};

@ -16,7 +16,7 @@ import { CLOnChainComponent } from './on-chain/on-chain.component';
import { CLQueryRoutesComponent } from './payments/query-routes/query-routes.component';
import { CLPaymentsComponent } from './payments/send-receive/payments.component';
import { CLPeersComponent } from './peers/peers.component';
import { CLForwardingHistoryComponent } from './switch/forwarding-history.component';
import { CLForwardingHistoryComponent } from './forwarding-history/forwarding-history.component';
import { CommonService } from '../shared/services/common.service';
import { LoggerService, ConsoleLoggerService } from '../shared/services/logger.service';

@ -6,13 +6,11 @@ import { CLHomeComponent } from './home/home.component';
import { CLChannelsComponent } from './channels/channels.component';
import { CLInvoicesComponent } from './invoices/invoices.component';
import { CLLookupsComponent } from './lookups/lookups.component';
import { CLChannelLookupComponent } from './lookups/channel-lookup/channel-lookup.component';
import { CLNodeLookupComponent } from './lookups/node-lookup/node-lookup.component';
import { CLOnChainComponent } from './on-chain/on-chain.component';
import { CLQueryRoutesComponent } from './payments/query-routes/query-routes.component';
import { CLPaymentsComponent } from './payments/send-receive/payments.component';
import { CLPeersComponent } from './peers/peers.component';
import { CLForwardingHistoryComponent } from './switch/forwarding-history.component';
import { CLForwardingHistoryComponent } from './forwarding-history/forwarding-history.component';
import { CLUnlockedGuard } from '../shared/services/auth.guard';
import { NotFoundComponent } from '../shared/components/not-found/not-found.component';
@ -27,7 +25,7 @@ export const ClRoutes: Routes = [
{ path: 'paymentsend', component: CLPaymentsComponent, canActivate: [CLUnlockedGuard] },
{ path: 'queryroutes', component: CLQueryRoutesComponent, canActivate: [CLUnlockedGuard] },
{ path: 'invoices', component: CLInvoicesComponent, canActivate: [CLUnlockedGuard] },
{ path: 'switch', component: CLForwardingHistoryComponent, canActivate: [CLUnlockedGuard] },
{ path: 'forwardinghistory', component: CLForwardingHistoryComponent, canActivate: [CLUnlockedGuard] },
{ path: 'lookups', component: CLLookupsComponent, canActivate: [CLUnlockedGuard] },
{ path: '**', component: NotFoundComponent }
]}

@ -1,5 +1,5 @@
<!-- <div fxLayout="column">
<div fxFlex="100" class="padding-gap">
<div fxLayout="column">
<!-- <div fxFlex="100" class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
@ -33,48 +33,56 @@
</form>
</mat-card-content>
</mat-card>
</div>
</div> -->
<div class="padding-gap">
<mat-card>
<mat-card-content class="table-card-content">
<div fxLayout="row" fxLayoutAlign="start start">
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="forwardingHistoryEvents" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
<ng-container matColumnDef="timestamp">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Timestamp</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent.timestamp_str}}</td>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.status}}</td>
</ng-container>
<ng-container matColumnDef="chan_id_in">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Chan Id In</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent.chan_id_in}}</td>
<ng-container matColumnDef="received_time_str">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Received Time</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.received_time_str}}</td>
</ng-container>
<ng-container matColumnDef="alias_in">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias In</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent.alias_in}}</td>
<ng-container matColumnDef="resolved_time_str">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Resolved Time</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.resolved_time_str}}</td>
</ng-container>
<ng-container matColumnDef="chan_id_out">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Chan Id Out</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent.chan_id_out}}</td>
<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}}</td>
</ng-container>
<ng-container matColumnDef="alias_out">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias Out</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent.alias_out}}</td>
<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}}</td>
</ng-container>
<ng-container matColumnDef="amt_out">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Amount
Out (Sats)</th>
<td mat-cell *matCellDef="let fhEvent"><span fxLayoutAlign="end center">{{fhEvent.amt_out | number}}</span></td>
<ng-container matColumnDef="in_msatoshi">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">In mSatoshi</th>
<td mat-cell *matCellDef="let fhEvent"><span fxLayoutAlign="end center">{{fhEvent?.in_msatoshi | number}}</span></td>
</ng-container>
<ng-container matColumnDef="amt_in">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Amount
In (Sats)</th>
<td mat-cell *matCellDef="let fhEvent"><span fxLayoutAlign="end center">{{fhEvent.amt_in | number}}</span></td>
<ng-container matColumnDef="out_msatoshi">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Out mSatoshi</th>
<td mat-cell *matCellDef="let fhEvent"><span fxLayoutAlign="end center">{{fhEvent?.out_msatoshi | number}}</span></td>
</ng-container>
<ng-container matColumnDef="fee">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Fee
(Sats)</th>
<td mat-cell *matCellDef="let fhEvent"><span fxLayoutAlign="end center">{{fhEvent.fee | number}}</span></td>
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Fee mSat</th>
<td mat-cell *matCellDef="let fhEvent"><span fxLayoutAlign="end center">{{fhEvent?.fee | number}}</span></td>
</ng-container>
<ng-container matColumnDef="payment_hash">
<th mat-header-cell class="pl-4" *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell class="pl-4" *matCellDef="let fhEvent">
<div>{{fhEvent?.payment_hash | slice:0:10}}...</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
@ -84,5 +92,4 @@
</mat-card-content>
</mat-card>
</div>
</div> -->
<h3>FORWARDING HISTORY</h3>
</div>

@ -0,0 +1,140 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { ForwardingEventCL } from '../../shared/models/clModels';
import { LoggerService } from '../../shared/services/logger.service';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
@Component({
selector: 'rtl-cl-forwarding-history',
templateUrl: './forwarding-history.component.html',
styleUrls: ['./forwarding-history.component.scss']
})
export class CLForwardingHistoryComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public displayedColumns = [];
public forwardingHistoryEvents: any;
public lastOffsetIndex = 0;
public flgLoading: Array<Boolean | 'error'> = [true];
public today = new Date(Date.now());
public yesterday = new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate() - 1, this.today.getHours(), this.today.getMinutes(), this.today.getSeconds());
public endDate = this.today;
public startDate = this.yesterday;
public flgSticky = false;
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions) {
switch (true) {
case (window.innerWidth <= 415):
this.displayedColumns = ['status', 'in_msatoshi', 'out_msatoshi'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['status', 'in_msatoshi', 'out_msatoshi', 'fee'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['status', 'received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'out_msatoshi', 'fee', 'payment_hash'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['status', 'received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'out_msatoshi', 'fee', 'payment_hash'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['status', 'received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'out_msatoshi', 'fee', 'payment_hash'];
break;
}
}
ngOnInit() {
this.onForwardingHistoryFetchCL();
this.actions$.pipe(takeUntil(this.unsub[2]), filter((action) => action.type === RTLActions.RESET_CL_STORE)).subscribe((resetClStore: RTLActions.ResetCLStore) => {
this.onForwardingHistoryFetchCL();
});
this.store.select('cl')
.pipe(takeUntil(this.unsub[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsCl.forEach(effectsErr => {
if (effectsErr.action === 'GetForwardingHistoryCL') {
this.flgLoading[0] = 'error';
}
});
if (undefined !== rtlStore.forwardingHistory.forwarding_events && rtlStore.forwardingHistory.forwarding_events.length > 0) {
this.lastOffsetIndex = rtlStore.forwardingHistory.last_offset_index;
this.loadForwardingEventsTable(rtlStore.forwardingHistory.forwarding_events);
} else {
// To reset table after other Forwarding history calls
this.lastOffsetIndex = 0;
this.loadForwardingEventsTable([]);
}
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== rtlStore.forwardingHistory.forwarding_events) ? false : true;
}
this.logger.info(rtlStore);
});
}
onForwardingEventClick(selRow: ForwardingEventCL, event: any) {
const selFEvent = this.forwardingHistoryEvents.data.filter(fhEvent => {
return (fhEvent.received_time === selRow.received_time && fhEvent.in_channel === selRow.in_channel);
})[0];
const reorderedFHEvent = JSON.parse(JSON.stringify(selFEvent, [
'status', 'received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'in_msat', 'out_msatoshi', 'out_msat', 'fee', 'fee_msat', 'payment_hash'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedFHEvent)
}}));
}
loadForwardingEventsTable(forwardingEvents: ForwardingEventCL[]) {
this.forwardingHistoryEvents = new MatTableDataSource<ForwardingEventCL>([...forwardingEvents]);
this.forwardingHistoryEvents.sort = this.sort;
this.forwardingHistoryEvents.data.forEach(event => {
event.received_time_str = (event.received_time_str === '') ? '' : formatDate(event.received_time_str, 'MMM/dd/yy HH:mm:ss', 'en-US');
event.resolved_time_str = (event.resolved_time_str === '') ? '' : formatDate(event.resolved_time_str, 'MMM/dd/yy HH:mm:ss', 'en-US');
});
this.logger.info(this.forwardingHistoryEvents);
}
onForwardingHistoryFetchCL() {
if (undefined === this.endDate || this.endDate == null) {
this.endDate = new Date();
}
if (undefined === this.startDate || this.startDate == null) {
this.startDate = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate() - 1);
}
this.store.dispatch(new RTLActions.GetForwardingHistoryCL(
// { end_time: Math.round(this.endDate.getTime() / 1000).toString(), start_time: Math.round(this.startDate.getTime() / 1000).toString() }
));
}
resetData() {
// this.endDate = new Date();
// this.startDate = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate() - 1);
if (undefined !== this.forwardingHistoryEvents) {
this.forwardingHistoryEvents.data = [];
}
}
applyFilter(selFilter: string) {
this.forwardingHistoryEvents.filter = selFilter;
}
ngOnDestroy() {
this.resetData();
this.unsub.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -1,64 +1,64 @@
<mat-card [ngClass]="{'custom-card error-border': flgLoading==='error','custom-card': true}">
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
<mat-card-title class="m-0 pt-2">
<h5>Per {{feeRateStyle}} Fee Rates</h5>
<h5>Fee Rates - per{{feeRateStyle}}</h5>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<div fxLayout="column" class="pl-4">
<div fxLayout="column" class="pl-2">
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
<mat-list-item fxFlex="55" fxLayoutAlign="start start">Urgent</mat-list-item>
<mat-list-item fxFlex="25" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.urgent}}</p>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Urgent</mat-list-item>
<mat-list-item fxFlex="45" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.urgent | number}}</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
<mat-list-item fxFlex="55" fxLayoutAlign="start start">Normal</mat-list-item>
<mat-list-item fxFlex="25" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.normal}}</p>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Normal</mat-list-item>
<mat-list-item fxFlex="45" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.normal | number}}</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
<mat-list-item fxFlex="55" fxLayoutAlign="start start">Slow</mat-list-item>
<mat-list-item fxFlex="25" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.slow}}</p>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Slow</mat-list-item>
<mat-list-item fxFlex="45" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.slow | number}}</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
<mat-list-item fxFlex="55" fxLayoutAlign="start start">Min Acceptable</mat-list-item>
<mat-list-item fxFlex="25" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.min_acceptable}}</p>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Min Acceptable</mat-list-item>
<mat-list-item fxFlex="45" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.min_acceptable | number}}</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
<mat-list-item fxFlex="55" fxLayoutAlign="start start">Max Acceptable</mat-list-item>
<mat-list-item fxFlex="25" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.max_acceptable}}</p>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Max Acceptable</mat-list-item>
<mat-list-item fxFlex="45" fxLayoutAlign="start start">
<p class="mat-button-text">{{perkbw?.max_acceptable | number}}</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
<mat-list-item fxFlex="55" fxLayoutAlign="start start">Opening Channel</mat-list-item>
<mat-list-item fxFlex="25" fxLayoutAlign="start start">
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.opening_channel_satoshis}}</p>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Opening Channel</mat-list-item>
<mat-list-item fxFlex="45" fxLayoutAlign="start start">
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.opening_channel_satoshis | number}}</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
<mat-list-item fxFlex="55" fxLayoutAlign="start start">Mutual Close</mat-list-item>
<mat-list-item fxFlex="25" fxLayoutAlign="start start">
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.mutual_close_satoshis}}</p>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Mutual Close</mat-list-item>
<mat-list-item fxFlex="45" fxLayoutAlign="start start">
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.mutual_close_satoshis | number}}</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
<mat-list-item fxFlex="55" fxLayoutAlign="start start">Unilateral Close</mat-list-item>
<mat-list-item fxFlex="25" fxLayoutAlign="start start">
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.unilateral_close_satoshis}}</p>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Unilateral Close</mat-list-item>
<mat-list-item fxFlex="45" fxLayoutAlign="start start">
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.unilateral_close_satoshis | number}}</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>

@ -122,12 +122,6 @@
</div>
</div>
<div fxLayout="column" fxLayout.gt-sm="row wrap">
<div fxFlex="20" class="padding-gap">
<rtl-cl-fee-rates [flgLoading]="flgLoading[4]" [feeRates]="feeRatesPerKB" [feeRateStyle]="'KB'"></rtl-cl-fee-rates>
</div>
<div fxFlex="20" class="padding-gap">
<rtl-cl-fee-rates [flgLoading]="flgLoading[4]" [feeRates]="feeRatesPerKW" [feeRateStyle]="'KW'"></rtl-cl-fee-rates>
</div>
<div fxFlex="60" class="padding-gap">
<mat-card [ngClass]="{'custom-card error-border': flgLoading[3]==='error','custom-card': true}">
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
@ -149,6 +143,12 @@
</mat-card-content>
</mat-card>
</div>
<div fxFlex="20" class="padding-gap">
<rtl-cl-fee-rates [flgLoading]="flgLoading[4]" [feeRates]="feeRatesPerKB" [feeRateStyle]="'KB'"></rtl-cl-fee-rates>
</div>
<div fxFlex="20" class="padding-gap">
<rtl-cl-fee-rates [flgLoading]="flgLoading[4]" [feeRates]="feeRatesPerKW" [feeRateStyle]="'KW'"></rtl-cl-fee-rates>
</div>
</div>
<ng-template #withoutData>
<h3>Sats</h3>

@ -529,6 +529,32 @@ export class CLEffects implements OnDestroy {
})
);
@Effect()
fetchForwardingHistoryCL = this.actions$.pipe(
ofType(RTLActions.GET_FORWARDING_HISTORY_CL),
mergeMap((action: RTLActions.GetForwardingHistoryCL) => {
this.store.dispatch(new RTLActions.ClearEffectErrorCl('GetForwardingHistoryCL'));
// const queryHeaders: SwitchReq = {
// num_max_events: action.payload.num_max_events, index_offset: action.payload.index_offset, end_time: action.payload.end_time, start_time: action.payload.start_time
// };
// return this.httpClient.post(this.CHILD_API_URL + environment.SWITCH_API, queryHeaders)
return this.httpClient.get(this.CHILD_API_URL + environment.CHANNELS_API + '/listForwards')
.pipe(
map((fhRes: any) => {
this.logger.info(fhRes);
return {
type: RTLActions.SET_FORWARDING_HISTORY_CL,
payload: fhRes
};
}),
catchError((err: any) => {
this.store.dispatch(new RTLActions.EffectErrorCl({ action: 'GetForwardingHistory', code: err.status, message: err.error.error }));
return this.handleErrorWithAlert('ERROR', 'Get Forwarding History Failed', this.CHILD_API_URL + environment.CHANNELS_API + '/listForwards', err);
})
);
})
);
handleErrorWithoutAlert(actionName: string, err: {status: number, error: any}) {
this.logger.error(err);
if(err.status === 401) {

@ -1,5 +1,5 @@
import { SelNodeChild } from '../../shared/models/RTLconfig';
import { GetInfoCL, FeesCL, BalanceCL, LocalRemoteBalanceCL, AddressTypeCL, PeerCL, PaymentCL, ChannelCL, FeeRatesCL } from '../../shared/models/clModels';
import { GetInfoCL, FeesCL, BalanceCL, LocalRemoteBalanceCL, AddressTypeCL, PeerCL, PaymentCL, ChannelCL, FeeRatesCL, ForwardingHistoryResCL } from '../../shared/models/clModels';
import { ErrorPayload } from '../../shared/models/errorPayload';
import * as RTLActions from '../../store/rtl.actions';
@ -15,6 +15,7 @@ export interface CLState {
peers: PeerCL[];
allChannels: ChannelCL[];
payments: PaymentCL[];
forwardingHistory: ForwardingHistoryResCL;
addressTypes: AddressTypeCL[];
}
@ -30,6 +31,7 @@ export const initCLState: CLState = {
peers: [],
allChannels: [],
payments: [],
forwardingHistory: {},
addressTypes: [
{ addressId: '0', addressTp: 'bech32', addressDetails: 'bech32' },
{ addressId: '1', addressTp: 'p2sh-segwit', addressDetails: 'p2sh-segwit (default)' }
@ -55,7 +57,7 @@ export function CLReducer(state = initCLState, action: RTLActions.RTLActions) {
...state,
effectErrorsCl: [...state.effectErrorsCl, action.payload]
};
case RTLActions.RESET_STORE_CL:
case RTLActions.RESET_CL_STORE:
return {
...initCLState,
nodeSettings: action.payload,
@ -140,7 +142,12 @@ export function CLReducer(state = initCLState, action: RTLActions.RTLActions) {
...state,
payments: action.payload
};
default:
case RTLActions.SET_FORWARDING_HISTORY_CL:
return {
...state,
forwardingHistory: action.payload
};
default:
return state;
}

@ -1,9 +0,0 @@
.mat-column-amt_in {
flex: 0 0 15%;
min-width: 120px;
padding-right: 20px;
}
table {
width:100%;
}

@ -1,135 +0,0 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { ForwardingEventCL } from '../../shared/models/clModels';
import { LoggerService } from '../../shared/services/logger.service';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
@Component({
selector: 'rtl-cl-forwarding-history',
templateUrl: './forwarding-history.component.html',
styleUrls: ['./forwarding-history.component.scss']
})
export class CLForwardingHistoryComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public displayedColumns = [];
public forwardingHistoryEvents: any;
public lastOffsetIndex = 0;
public flgLoading: Array<Boolean | 'error'> = [true];
public today = new Date(Date.now());
public yesterday = new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate() - 1, this.today.getHours(), this.today.getMinutes(), this.today.getSeconds());
public endDate = this.today;
public startDate = this.yesterday;
public flgSticky = false;
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
ngOnInit() {}
// constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions) {
// switch (true) {
// case (window.innerWidth <= 415):
// this.displayedColumns = ['timestamp', 'amt_out', 'amt_in'];
// break;
// case (window.innerWidth > 415 && window.innerWidth <= 730):
// this.displayedColumns = ['timestamp', 'amt_out', 'amt_in', 'fee'];
// break;
// case (window.innerWidth > 730 && window.innerWidth <= 1024):
// this.displayedColumns = ['timestamp', 'chan_id_in', 'chan_id_out', 'amt_out', 'amt_in', 'fee'];
// break;
// case (window.innerWidth > 1024 && window.innerWidth <= 1280):
// this.flgSticky = true;
// this.displayedColumns = ['timestamp', 'chan_id_in', 'chan_id_out', 'amt_out', 'amt_in', 'fee'];
// break;
// default:
// this.flgSticky = true;
// this.displayedColumns = ['timestamp', 'chan_id_in', 'chan_id_out', 'amt_out', 'amt_in', 'fee'];
// break;
// }
// }
// ngOnInit() {
// this.onForwardingHistoryFetch();
// this.actions$.pipe(takeUntil(this.unsub[2]), filter((action) => action.type === RTLActions.RESET_LND_STORE)).subscribe((resetLndStore: RTLActions.ResetLNDStore) => {
// this.onForwardingHistoryFetch();
// });
// this.store.select('cl')
// .pipe(takeUntil(this.unsub[0]))
// .subscribe((rtlStore) => {
// rtlStore.effectErrorsCl.forEach(effectsErr => {
// if (effectsErr.action === 'GetForwardingHistory') {
// this.flgLoading[0] = 'error';
// }
// });
// if (undefined !== rtlStore.forwardingHistory && undefined !== rtlStore.forwardingHistory.forwarding_events) {
// this.lastOffsetIndex = rtlStore.forwardingHistory.last_offset_index;
// this.loadForwardingEventsTable(rtlStore.forwardingHistory.forwarding_events);
// } else {
// // To reset table after other Forwarding history calls
// this.lastOffsetIndex = 0;
// this.loadForwardingEventsTable([]);
// }
// if (this.flgLoading[0] !== 'error') {
// this.flgLoading[0] = (undefined !== rtlStore.forwardingHistory) ? false : true;
// }
// this.logger.info(rtlStore);
// });
// }
// onForwardingEventClick(selRow: ForwardingEventCL, event: any) {
// const selFEvent = this.forwardingHistoryEvents.data.filter(fhEvent => {
// return (fhEvent.chan_id_in === selRow.chan_id_in && fhEvent.timestamp === selRow.timestamp);
// })[0];
// const reorderedFHEvent = JSON.parse(JSON.stringify(selFEvent, ['timestamp_str', 'chan_id_in', 'alias_in', 'chan_id_out', 'alias_out', 'amt_out', 'amt_in', 'fee'] , 2));
// this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
// type: 'INFO',
// message: JSON.stringify(reorderedFHEvent)
// }}));
// }
// loadForwardingEventsTable(forwardingEvents: ForwardingEventCL[]) {
// this.forwardingHistoryEvents = new MatTableDataSource<ForwardingEventCL>([...forwardingEvents]);
// this.forwardingHistoryEvents.sort = this.sort;
// this.forwardingHistoryEvents.data.forEach(event => {
// event.timestamp_str = (event.timestamp_str === '') ? '' : formatDate(event.timestamp_str, 'MMM/dd/yy HH:mm:ss', 'en-US');
// });
// this.logger.info(this.forwardingHistoryEvents);
// }
// onForwardingHistoryFetch() {
// if (undefined === this.endDate || this.endDate == null) {
// this.endDate = new Date();
// }
// if (undefined === this.startDate || this.startDate == null) {
// this.startDate = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate() - 1);
// }
// this.store.dispatch(new RTLActions.GetForwardingHistory({
// end_time: Math.round(this.endDate.getTime() / 1000).toString(),
// start_time: Math.round(this.startDate.getTime() / 1000).toString()
// }));
// }
resetData() {
this.endDate = new Date();
this.startDate = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate() - 1);
if (undefined !== this.forwardingHistoryEvents) {
this.forwardingHistoryEvents.data = [];
}
}
ngOnDestroy() {
this.resetData();
this.unsub.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -143,15 +143,25 @@ export interface PayRequestCL {
}
export interface ForwardingEventCL {
timestamp?: string;
timestamp_str?: string;
chan_id_out?: string;
alias_out?: string;
amt_out?: string;
amt_in?: string;
chan_id_in?: string;
alias_in?: string;
fee?: string;
payment_hash?: string;
in_channel?: string;
out_channel?: string;
in_msatoshi?: number;
in_msat?: string;
out_msatoshi?: number;
out_msat?: string;
fee?: number;
fee_msat?: string;
status?: string;
received_time?: number;
received_time_str?: string;
resolved_time?: number;
resolved_time_str?: string;
}
export interface ForwardingHistoryResCL {
last_offset_index?: number;
forwarding_events?: ForwardingEventCL[];
}
export interface QueryRoutesCL {

@ -33,7 +33,7 @@ export const MENU_DATA: MenuRootNode = {
{id: 52, parentId: 5, name: 'Query Routes', icon: 'explore', link: '/cl/queryroutes'}
]},
{id: 6, parentId: 0, name: 'Invoices', icon: 'receipt', link: '/cl/invoices'},
{id: 7, parentId: 0, name: 'Forwarding History', icon: 'timeline', link: '/cl/switch'},
{id: 7, parentId: 0, name: 'Forwarding History', icon: 'timeline', link: '/cl/forwardinghistory'},
{id: 9, parentId: 0, name: 'Lookups', icon: 'search', link: '/cl/lookups'},
{id: 10, parentId: 0, name: 'Node Config', icon: 'perm_data_setting', link: '../sconfig'},
{id: 11, parentId: 0, name: 'Help', icon: 'help', link: '../help'}

@ -3,7 +3,7 @@ import { Action } from '@ngrx/store';
import { ErrorPayload } from '../shared/models/errorPayload';
import { RTLConfiguration, Settings, LightningNode, GetInfoRoot, SelNodeChild } from '../shared/models/RTLconfig';
import { GetInfoCL, FeesCL, AddressTypeCL, PeerCL, PaymentCL, PayRequestCL, QueryRoutesCL, ChannelCL, FeeRatesCL } from '../shared/models/clModels';
import { GetInfoCL, FeesCL, AddressTypeCL, PeerCL, PaymentCL, PayRequestCL, QueryRoutesCL, ChannelCL, FeeRatesCL, ForwardingHistoryResCL } from '../shared/models/clModels';
import {
GetInfo, Peer, Balance, NetworkInfo, Fees, Channel, Invoice, ListInvoices, Payment, GraphNode, AddressType,
PayRequest, ChannelsTransaction, PendingChannels, ClosedChannel, Transaction, SwitchReq, SwitchRes, QueryRoutes
@ -95,7 +95,7 @@ export const SET_FORWARDING_HISTORY = 'SET_FORWARDING_HISTORY';
export const GET_QUERY_ROUTES = 'GET_QUERY_ROUTES';
export const SET_QUERY_ROUTES = 'SET_QUERY_ROUTES';
export const RESET_STORE_CL = 'RESET_STORE_CL';
export const RESET_CL_STORE = 'RESET_CL_STORE';
export const CLEAR_EFFECT_ERROR_CL = 'CLEAR_EFFECT_ERROR_CL';
export const EFFECT_ERROR_CL = 'EFFECT_ERROR_CL';
export const FETCH_INFO_CL = 'FETCH_INFO_CL';
@ -133,6 +133,8 @@ export const PEER_LOOKUP_CL = 'PEER_LOOKUP_CL';
export const CHANNEL_LOOKUP_CL = 'CHANNEL_LOOKUP_CL';
export const INVOICE_LOOKUP_CL = 'INVOICE_LOOKUP_CL';
export const SET_LOOKUP_CL = 'SET_LOOKUP_CL';
export const GET_FORWARDING_HISTORY_CL = 'GET_FORWARDING_HISTORY_CL';
export const SET_FORWARDING_HISTORY_CL = 'SET_FORWARDING_HISTORY_CL';
export class VoidAction implements Action {
readonly type = VOID;
@ -207,7 +209,7 @@ export class ResetLNDStore implements Action {
}
export class ResetCLStore implements Action {
readonly type = RESET_STORE_CL;
readonly type = RESET_CL_STORE;
constructor(public payload: SelNodeChild) {}
}
@ -716,6 +718,16 @@ export class SetLookupCL implements Action {
constructor(public payload: any) {} // payload = lookup Response (Peer/Channel/Invoice)
}
export class GetForwardingHistoryCL implements Action {
readonly type = GET_FORWARDING_HISTORY_CL;
// constructor(public payload: SwitchReq) {}
}
export class SetForwardingHistoryCL implements Action {
readonly type = SET_FORWARDING_HISTORY_CL;
constructor(public payload: ForwardingHistoryResCL) {}
}
export type RTLActions =
ClearEffectErrorRoot | EffectErrorRoot | ClearEffectErrorLnd | EffectErrorLnd | ClearEffectErrorCl | EffectErrorCl |
VoidAction | OpenSpinner | CloseSpinner | FetchRTLConfig | SetRTLConfig | SaveSettings |
@ -746,4 +758,5 @@ export type RTLActions =
FetchChannelsCL | SetChannelsCL | UpdateChannelsCL | SaveNewChannelCL | CloseChannelCL | RemoveChannelCL |
FetchPaymentsCL | SetPaymentsCL | SendPaymentCL | DecodePaymentCL | SetDecodedPaymentCL |
GetQueryRoutesCL | SetQueryRoutesCL |
PeerLookupCL | ChannelLookupCL | InvoiceLookupCL | SetLookupCL;
PeerLookupCL | ChannelLookupCL | InvoiceLookupCL | SetLookupCL |
GetForwardingHistoryCL | SetForwardingHistoryCL;

Loading…
Cancel
Save