pull/260/head
saubyk 4 years ago
commit 35eeb2486a
No known key found for this signature in database
GPG Key ID: 00C9E2BC2E45666F

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -12,5 +12,5 @@
<link rel="stylesheet" href="styles.09fbe043baaff9d23c8b.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.8e5ce25f927cbaca2d37.js" defer></script><script src="polyfills-es5.b8e32dec482ae69710a2.js" nomodule defer></script><script src="polyfills.ebf9033c33aa4a5af12a.js" defer></script><script src="main.e5b7d4371169014e6bcc.js" defer></script></body>
<script src="runtime.0e212222e2308bf3823a.js" defer></script><script src="polyfills-es5.b8e32dec482ae69710a2.js" nomodule defer></script><script src="polyfills.ebf9033c33aa4a5af12a.js" defer></script><script src="main.431678218492b26b8b2b.js" defer></script></body>
</html>

File diff suppressed because one or more lines are too long

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

@ -1 +0,0 @@
!function(e){function r(r){for(var n,i,a=r[0],c=r[1],f=r[2],p=0,s=[];p<a.length;p++)i=a[p],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,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:"77d491bf73b15683870f",6:"b479355282ea9b377ebc",7:"22cd396798191c8cb98f"}[e]+".js"}(e);var c=new Error;u=function(r){a.onerror=a.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=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||[],c=a.push.bind(a);a.push=r,a=a.slice();for(var f=0;f<a.length;f++)r(a[f]);var l=c;t()}([]);

@ -1,6 +1,7 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var swtch = require('./switch');
var options = {};
exports.getFees = (req, res, next) => {
@ -36,18 +37,18 @@ exports.getFees = (req, res, next) => {
let month_start_time = current_time - 2629743;
let week_start_time = current_time - 604800;
let day_start_time = current_time - 86400;
return getFwdTransactions(month_start_time, current_time)
return swtch.getAllForwardingEvents(month_start_time, current_time, 0, 1000)
.then((history) => {
let daily_tx_count = history.filter(event => {
return event.timestamp >= day_start_time;
});
logger.info({fileName: 'Fees', msg: 'Forwarding History Received: ' + JSON.stringify(history)});
let daily_tx_count = history.forwarding_events.filter(event => event.timestamp >= day_start_time);
body.daily_tx_count = daily_tx_count && daily_tx_count.length ? daily_tx_count.length : 0;
let weekly_tx_count = history.filter(event => event.timestamp >= week_start_time);
let weekly_tx_count = history.forwarding_events.filter(event => event.timestamp >= week_start_time);
body.weekly_tx_count = weekly_tx_count && weekly_tx_count.length ? weekly_tx_count.length : 0;
body.monthly_tx_count = history && history.length ? history.length : 0;
body.monthly_tx_count = history.forwarding_events && history.forwarding_events.length ? history.forwarding_events.length : 0;
return res.status(200).json(body);
})
.catch(err => {
logger.error({fileName: 'Fees', lineNum: 54, msg: 'Fetch Fee Error: ' + JSON.stringify(err)});
return res.status(500).json({
message: "Fetching fee failed!",
error: err.error
@ -62,37 +63,3 @@ exports.getFees = (req, res, next) => {
});
});
};
getFwdTransactions = (start_time, end_time) => {
return new Promise(function(resolve, reject) {
options.url = common.getSelLNServerUrl() + '/switch';
options.form = JSON.stringify({
start_time: start_time,
end_time: end_time
});
logger.info({fileName: 'Fees', msg: 'Switch Post Options: ' + JSON.stringify(options)});
request.post(options).then((body) => {
try {
logger.info({fileName: 'Fees', msg: 'Switch Post Response: ' + JSON.stringify(body)});
if(undefined === body || body.error) {
logger.error({fileName: 'Fees', lineNum: 78, msg: 'Switch Post Error: ' + JSON.stringify((undefined === body) ? 'Error From Server!' : body.error)});
res.status(500).json({
message: "Switch post failed!",
error: (undefined === body) ? 'Error From Server!' : body.error
});
} else {
if (undefined !== body.forwarding_events && body.forwarding_events.length > 0) {
body.forwarding_events.forEach(event => {
event.timestamp_str = (undefined === event.timestamp) ? '' : common.convertTimestampToDate(event.timestamp);
});
body.forwarding_events = common.sortDescByKey(body.forwarding_events, 'timestamp');
logger.info({fileName: 'Fees', msg: 'Forwarding History Received: ' + JSON.stringify(body)});
resolve(body.forwarding_events);
}
}
} catch (err) {
resolve(err);
}
})
});
}

@ -3,48 +3,54 @@ var common = require('../../common');
var logger = require('../logger');
var options = {};
exports.forwardingHistory = (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: 'Forwarding History Start Time: ' + options.form.start_time});
logger.info({fileName: 'Switch', msg: 'Forwarding History End Time: ' + options.form.end_time});
request.post(options).then((body) => {
if(undefined === body || body.error) {
logger.error({fileName: 'Switch', lineNum: 27, msg: 'Forwarding History Error: ' + JSON.stringify((undefined === body) ? 'Error From Server!' : body.error)});
res.status(500).json({
message: "Switch post failed!",
error: (undefined === body) ? 'Error From Server!' : body.error
});
} else {
if (undefined !== body.forwarding_events && body.forwarding_events.length > 0) {
body.forwarding_events.forEach(event => {
event.timestamp_str = (undefined === event.timestamp) ? '' : common.convertTimestampToDate(event.timestamp);
exports.getAllForwardingEvents = (start, end, offset, max_events) => {
return new Promise(function(resolve, reject) {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/switch';
options.form = {};
if (start) { options.form.start_time = start; }
if (end) { options.form.end_time = end; }
options.form.num_max_events = max_events ? max_events : 1000;
options.form.index_offset = offset ? offset : 0;
options.form = JSON.stringify(options.form);
logger.info({fileName: 'Switch', msg: 'Forwarding History Params: ' + options.form});
request.post(options).then((body) => {
if(undefined === body || body.error) {
logger.error({fileName: 'Switch', lineNum: 31, msg: 'Forwarding History Error: ' + JSON.stringify((undefined === body) ? 'Error From Server!' : body.error)});
res.status(500).json({
message: "Switch post failed!",
error: (undefined === body) ? 'Error From Server!' : body.error
});
body.forwarding_events = common.sortDescByKey(body.forwarding_events, 'timestamp');
} else {
if (undefined !== body.forwarding_events && body.forwarding_events.length > 0) {
body.forwarding_events.forEach(event => {
event.timestamp_str = (undefined === event.timestamp) ? '' : common.convertTimestampToDate(event.timestamp);
});
body.forwarding_events = common.sortDescByKey(body.forwarding_events, 'timestamp');
}
logger.info({fileName: 'Switch', msg: 'Forwarding History Received: ' + JSON.stringify(body)});
resolve(body);
}
logger.info({fileName: 'Switch', msg: 'Forwarding History Received: ' + JSON.stringify(body)});
res.status(201).json(body);
}
})
.catch(function (err) {
logger.error({fileName: 'Switch', lineNum: 44, msg: 'Forwarding History Error: ' + JSON.stringify(err)});
return res.status(500).json({
})
.catch(function (err) {
logger.error({fileName: 'Switch', lineNum: 48, msg: 'Forwarding History Error: ' + JSON.stringify(err)});
resolve({
message: "Switch post failed!",
error: err.error
});
});
});
}
exports.forwardingHistory = (req, res, next) => {
this.getAllForwardingEvents(req.body.start_time, req.body.end_time, 0, 1000).then(function(values) {
logger.info({fileName: 'Switch', msg: 'All Forwarding Events: ' + JSON.stringify(values)});
res.status(201).json(values);
}).catch(err => {
logger.error({fileName: 'Switch', lineNum: 60, msg: 'Get All Forwarding Events: ' + JSON.stringify(err)});
res.status(500).json({
message: "Switch post failed!",
error: err.error
});
});
});
};

@ -19,6 +19,7 @@ import { CLTransactionsComponent } from './transactions/transactions.component';
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 { 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';
@ -53,6 +54,7 @@ import { CLUnlockedGuard } from '../shared/services/auth.guard';
CLLookupsComponent,
CLRoutingComponent,
CLForwardingHistoryComponent,
CLFailedTransactionsComponent,
CLChannelLookupComponent,
CLNodeLookupComponent,
CLQueryRoutesComponent,

@ -1,7 +1,7 @@
<div fxLayout="column" fxFlex="50" fxLayoutAlign="space-between stretch">
<div>
<h4 fxLayoutAlign="start" class="dashboard-info-title">Total</h4>
<div class="overflow-wrap dashboard-info-value">{{fees?.feeCollected | number}} Sats</div>
<div class="overflow-wrap dashboard-info-value">{{fees?.feeCollected/1000 | number}} Sats</div>
</div>
</div>
<div fxLayout="column" fxFlex="50" fxLayoutAlign="space-between stretch">

@ -1,4 +1,4 @@
import { Component, OnChanges, Input } from '@angular/core';
import { Component, Input } from '@angular/core';
import { FeesCL } from '../../../shared/models/clModels';
@Component({
@ -6,18 +6,8 @@ import { FeesCL } from '../../../shared/models/clModels';
templateUrl: './fee-info.component.html',
styleUrls: ['./fee-info.component.scss']
})
export class CLFeeInfoComponent implements OnChanges {
export class CLFeeInfoComponent {
@Input() fees: FeesCL;
totalFees = [{'name': 'Total', 'value': 0}];
maxFeeValue = 100;
constructor() {}
ngOnChanges() {
if(this.fees.feeCollected) {
this.totalFees = [{'name': 'Total', 'value': this.fees.feeCollected}];
Object.assign(this, this.totalFees);
}
}
}

@ -8,7 +8,7 @@
<div fxLayout="row">
<div fxLayout="column" fxFlex="50" fxLayoutAlign="end start" class="my-1">
<h4 fxLayoutAlign="start" class="font-bold-500">Alias</h4>
<span class="foreground-secondary-text">{{lookupResult.alias}}<span class="ml-2" [ngStyle]="{'background-color': '#' + lookupResult.color}">#{{lookupResult.color}}</span></span>
<span class="foreground-secondary-text">{{lookupResult.alias}}<span class="ml-2" [ngStyle]="{'background-color': '#' + lookupResult.color}">{{lookupResult.color ? '#' + lookupResult.color : ''}}</span></span>
<mat-divider class="my-1"></mat-divider>
</div>
<div fxLayout="column" fxFlex="50" fxLayoutAlign="end start" class="my-1">

@ -1,4 +1,4 @@
<form fxLayout="column" fxFlex="98" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" fxLayoutAlign.gt-sm="space-between start" class="padding-gap overflow-x-hidden">
<form fxLayout="column" fxFlex="98" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" fxLayoutAlign.gt-sm="space-between start" class="padding-gap overflow-x-hidden" (submit)="onSendFunds()" (reset)="resetData()" #form="ngForm">
<mat-form-field fxFlex.gt-sm="55">
<input matInput [(ngModel)]="transaction.address" placeholder="Bitcoin Address" tabindex="1" name="address" required #address="ngModel">
<mat-error *ngIf="!transaction.address">Bitcoin address is required.</mat-error>
@ -31,7 +31,7 @@
</div>
<div fxLayout="column" fxFlex="100" fxFlex.gt-sm="40" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" fxLayoutAlign.gt-sm="space-between start"></div>
<div fxLayout="row" fxFlex="100" fxFlex.gt-sm="30" fxLayoutAlign="space-between stretch" class="mt-2">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7" type="reset" (click)="resetData()">Clear Fields</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit" tabindex="8" (click)="onSendFunds()">Send Funds</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7" type="reset">Clear Fields</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit" tabindex="8">Send Funds</button>
</div>
</form>

@ -1,17 +1,15 @@
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { MatSnackBar } from '@angular/material/snack-bar';
import { SelNodeChild, GetInfoRoot } from '../../../shared/models/RTLconfig';
import { GetInfoCL, BalanceCL, OnChainCL } from '../../../shared/models/clModels';
import { CURRENCY_UNITS, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, AlertTypeEnum, DataTypeEnum, ADDRESS_TYPES, FEE_RATE_TYPES } from '../../../shared/services/consts-enums-functions';
import { CURRENCY_UNITS, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, AlertTypeEnum, ADDRESS_TYPES, FEE_RATE_TYPES } from '../../../shared/services/consts-enums-functions';
import { RTLConfiguration } from '../../../shared/models/RTLconfig';
import { CommonService } from '../../../shared/services/common.service';
import { LoggerService } from '../../../shared/services/logger.service';
import * as sha256 from 'sha256';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
@ -24,6 +22,7 @@ import { MessageDataField } from '../../../shared/models/alertData';
styleUrls: ['./on-chain-send.component.scss']
})
export class CLOnChainSendComponent implements OnInit, OnDestroy {
@ViewChild('form', { static: false }) form: any;
public selNode: SelNodeChild = {};
public appConfig: RTLConfiguration;
public nodeData: GetInfoRoot;
@ -43,7 +42,7 @@ export class CLOnChainSendComponent implements OnInit, OnDestroy {
public currencyUnitFormats = CURRENCY_UNIT_FORMATS;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService, private decimalPipe: DecimalPipe, private snackBar: MatSnackBar) {}
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService, private decimalPipe: DecimalPipe) {}
ngOnInit() {
this.store.select('root')
@ -97,6 +96,7 @@ export class CLOnChainSendComponent implements OnInit, OnDestroy {
this.store.dispatch(new RTLActions.OpenSpinner('Sending Funds...'));
this.store.dispatch(new RTLActions.SetChannelTransactionCL(this.transaction));
this.transaction = {};
this.form.resetForm();
}
get invalidValues(): boolean {

@ -63,7 +63,7 @@ export class CLChannelManageComponent implements OnInit, OnDestroy {
filter((action) => action.type === RTLActions.SET_PEERS_CL))
.subscribe((action: RTLActions.SetPeersCL) => {
if(this.newlyAddedPeer !== '') {
this.snackBar.open('Peer added successfully.');
this.snackBar.open('Peer added successfully. Proceed to open the channel.');
this.selectedPeer = this.newlyAddedPeer;
this.newlyAddedPeer = '';
}

@ -29,9 +29,14 @@
<td mat-cell *matCellDef="let channel"> {{channel?.state}}</td>
</ng-container>
<ng-container matColumnDef="msatoshi_to_us">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> mSatoshi To Us </th>
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Local Balance (Sats) </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">
{{channel?.msatoshi_to_us | number}} </span></td>
{{channel?.msatoshi_to_us/1000 | number:'1.0-0'}} </span></td>
</ng-container>
<ng-container matColumnDef="msatoshi_to_them">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Remote Balance (Sats) </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">
{{channel?.msatoshi_to_them/1000 | number:'1.0-0'}} </span></td>
</ng-container>
<ng-container matColumnDef="msatoshi_total">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Total mSatoshis </th>

@ -12,7 +12,7 @@
width: 22%;
}
.mat-column-short_channel_id, .mat-column-state, .mat-column-msatoshi_to_us, .mat-column-msatoshi_total {
.mat-column-short_channel_id, .mat-column-state, .mat-column-msatoshi_to_us, .mat-column-msatoshi_to_them {
flex: 0 0 15%;
width: 15%;
white-space: nowrap;

@ -46,16 +46,16 @@ export class CLChannelOpenTableComponent implements OnInit, OnDestroy {
this.screenSize = this.commonService.getScreenSize();
if(this.screenSize === ScreenSizeEnum.XS) {
this.flgSticky = false;
this.displayedColumns = ['short_channel_id', 'alias', 'msatoshi_total', 'actions'];
this.displayedColumns = ['short_channel_id', 'alias', 'actions'];
} else if(this.screenSize === ScreenSizeEnum.SM) {
this.flgSticky = false;
this.displayedColumns = ['short_channel_id', 'alias', 'msatoshi_total', 'actions'];
this.displayedColumns = ['short_channel_id', 'alias', 'msatoshi_to_us', 'msatoshi_to_them', 'actions'];
} else if(this.screenSize === ScreenSizeEnum.MD) {
this.flgSticky = false;
this.displayedColumns = ['short_channel_id', 'alias', 'msatoshi_to_us', 'msatoshi_total', 'actions'];
this.displayedColumns = ['short_channel_id', 'alias', 'msatoshi_to_us', 'msatoshi_to_them', 'actions'];
} else {
this.flgSticky = true;
this.displayedColumns = ['short_channel_id', 'alias', 'msatoshi_to_us', 'msatoshi_total', 'balancedness', 'actions'];
this.displayedColumns = ['short_channel_id', 'alias', 'msatoshi_to_us', 'msatoshi_to_them', 'balancedness', 'actions'];
}
}
@ -206,19 +206,20 @@ export class CLChannelOpenTableComponent implements OnInit, OnDestroy {
onChannelClick(selChannel: ChannelCL, event: any) {
const reorderedChannel = [
[{key: 'alias', value: selChannel.alias, title: 'Peer Alias', width: 40},
{key: 'connected', value: selChannel.connected, title: 'Connected', width: 30, type: DataTypeEnum.BOOLEAN},
{key: 'private', value: selChannel.private, title: 'Private', width: 30, type: DataTypeEnum.BOOLEAN}],
[{key: 'id', value: selChannel.id, title: 'Peer Public Key', width: 100}],
[{key: 'short_channel_id', value: selChannel.short_channel_id, title: 'Short Channel ID', width: 100}],
[{key: 'channel_id', value: selChannel.channel_id, title: 'Channel ID', width: 50},
{key: 'state', value: selChannel.state, title: 'State', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'our_channel_reserve_satoshis', value: selChannel.our_channel_reserve_satoshis, title: 'Our Channel Reserve Satoshis', width: 50, type: DataTypeEnum.NUMBER},
{key: 'their_channel_reserve_satoshis', value: selChannel.their_channel_reserve_satoshis, title: 'Their Channel Reserve Satoshis', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'msatoshi_to_us', value: selChannel.msatoshi_to_us, title: 'mSatoshi to Us', width: 50, type: DataTypeEnum.NUMBER},
{key: 'spendable_msatoshi', value: selChannel.spendable_msatoshi, title: 'Spendable mSatoshi', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'msatoshi_total', value: selChannel.msatoshi_total, title: 'Total mSatoshi', width: 50, type: DataTypeEnum.NUMBER},
{key: 'funding_txid', value: selChannel.funding_txid, title: 'Funding Transaction Id', width: 50, type: DataTypeEnum.NUMBER}]
[{key: 'id', value: selChannel.id, title: 'Peer Public Key', width: 100}],
[{key: 'channel_id', value: selChannel.channel_id, title: 'Channel ID', width: 100}],
[{key: 'alias', value: selChannel.alias, title: 'Peer Alias', width: 66},
{key: 'connected', value: selChannel.connected, title: 'Connected', width: 32, type: DataTypeEnum.BOOLEAN}],
[{key: 'private', value: selChannel.private, title: 'Private', width: 32, type: DataTypeEnum.BOOLEAN},
{key: 'state', value: selChannel.state, title: 'State', width: 32, type: DataTypeEnum.NUMBER},
{key: 'funding_txid', value: selChannel.funding_txid, title: 'Funding Transaction Id', width: 32, type: DataTypeEnum.NUMBER}],
[{key: 'msatoshi_to_us', value: selChannel.msatoshi_to_us, title: 'mSatoshi to Us', width: 32, type: DataTypeEnum.NUMBER},
{key: 'msatoshi_to_them', value: selChannel.msatoshi_to_them, title: 'mSatoshi to Us', width: 32, type: DataTypeEnum.NUMBER},
{key: 'msatoshi_total', value: selChannel.msatoshi_total, title: 'Total mSatoshi', width: 32, type: DataTypeEnum.NUMBER}],
[{key: 'our_channel_reserve_satoshis', value: selChannel.our_channel_reserve_satoshis, title: 'Our Channel Reserve Satoshis', width: 32, type: DataTypeEnum.NUMBER},
{key: 'their_channel_reserve_satoshis', value: selChannel.their_channel_reserve_satoshis, title: 'Their Channel Reserve Satoshis', width: 32, type: DataTypeEnum.NUMBER},
{key: 'spendable_msatoshi', value: selChannel.spendable_msatoshi, title: 'Spendable mSatoshi', width: 32, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({ data: {
type: AlertTypeEnum.INFORMATION,

@ -0,0 +1,65 @@
<div fxLayout="column" fxLayoutAlign="start stretch">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container">
<div fxFlex="70"></div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<table mat-table #table [dataSource]="failedEvents" fxFlex="100" matSort class="overflow-auto">
<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="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="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="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="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="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="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 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>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="px-3"><span fxLayoutAlign="end center">Actions</span></th>
<td mat-cell *matCellDef="let fhEvent" class="pl-3">
<button mat-stroked-button color="primary" type="button" tabindex="4" (click)="onForwardingEventClick(fhEvent,$event)">View Info</button>
</td>
</ng-container>
<ng-container matColumnDef="no_event">
<td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="!forwardingHistoryEvents.data || forwardingHistoryEvents.data.length<1">No forwarding event available.</p>
</td>
</ng-container>
<tr mat-footer-row *matFooterRowDef="['no_event']" [ngClass]="{'display-none': forwardingHistoryEvents.data && forwardingHistoryEvents.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 [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator>
</div>

@ -0,0 +1,4 @@
.mat-column-actions {
flex: 0 0 5%;
width: 5%;
}

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CLFailedTransactionsComponent } from './failed-transactions.component';
describe('CLFailedTransactionsComponent', () => {
let component: CLFailedTransactionsComponent;
let fixture: ComponentFixture<CLFailedTransactionsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CLFailedTransactionsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CLFailedTransactionsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,86 @@
import { Component, OnInit, OnChanges, ViewChild, Input } from '@angular/core';
import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { ForwardingEventCL } from '../../../shared/models/clModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-cl-failed-history',
templateUrl: './failed-transactions.component.html',
styleUrls: ['./failed-transactions.component.scss'],
providers: [
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Events') }
]
})
export class CLFailedTransactionsComponent implements OnInit, OnChanges {
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
@Input() failedEvents: any;
public displayedColumns = [];
public forwardingHistoryEvents: any;
public flgSticky = false;
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
public screenSize = '';
public screenSizeEnum = ScreenSizeEnum;
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 = ['status', 'in_msatoshi', 'out_msatoshi', 'actions'];
} else if(this.screenSize === ScreenSizeEnum.SM || this.screenSize === ScreenSizeEnum.MD) {
this.flgSticky = false;
this.displayedColumns = ['status', 'in_msatoshi', 'out_msatoshi', 'fee', 'actions'];
} else {
this.flgSticky = true;
this.displayedColumns = ['status', 'received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'out_msatoshi', 'fee', 'actions'];
}
}
ngOnInit() {}
ngOnChanges() {
this.loadForwardingEventsTable(this.failedEvents);
}
onForwardingEventClick(selFEvent: ForwardingEventCL, event: any) {
const reorderedFHEvent = [
[{key: 'received_time_str', value: selFEvent.received_time_str, title: 'Received Time', width: 50, type: DataTypeEnum.DATE_TIME},
{key: 'resolved_time_str', value: selFEvent.resolved_time_str, title: 'Resolved Time', width: 50, type: DataTypeEnum.DATE_TIME}],
[{key: 'status', value: selFEvent.status, title: 'Status', width: 50, type: DataTypeEnum.STRING},
{key: 'payment_hash', value: selFEvent.payment_hash, title: 'Payment Hash', width: 50, type: DataTypeEnum.STRING}],
[{key: 'in_channel', value: selFEvent.in_channel, title: 'Inbound Channel ID', width: 50, type: DataTypeEnum.STRING},
{key: 'out_channel', value: selFEvent.out_channel, title: 'Outbound Channel ID', width: 50, type: DataTypeEnum.STRING}],
[{key: 'in_msatoshi', value: selFEvent.in_msatoshi, title: 'In (mSatoshi)', width: 50, type: DataTypeEnum.STRING},
{key: 'in_msat', value: selFEvent.in_msat, title: 'In (mSats)', width: 50, type: DataTypeEnum.STRING}],
[{key: 'out_msatoshi', value: selFEvent.out_msatoshi, title: 'Out (mSatoshi)', width: 50, type: DataTypeEnum.STRING},
{key: 'out_msat', value: selFEvent.out_msat, title: 'Out (mSats)', width: 50, type: DataTypeEnum.STRING}],
[{key: 'fee', value: selFEvent.fee, title: 'Fee', width: 50, type: DataTypeEnum.STRING},
{key: 'fee_msat', value: selFEvent.fee_msat, title: 'Fee (mSats)', width: 50, type: DataTypeEnum.STRING}]
];
this.store.dispatch(new RTLActions.OpenAlert({ data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Event Information',
message: reorderedFHEvent
}}));
}
loadForwardingEventsTable(forwardingEvents: ForwardingEventCL[]) {
this.forwardingHistoryEvents = new MatTableDataSource<ForwardingEventCL>([...forwardingEvents]);
this.forwardingHistoryEvents.sort = this.sort;
this.forwardingHistoryEvents.paginator = this.paginator;
this.logger.info(this.forwardingHistoryEvents);
}
applyFilter(selFilter: string) {
this.forwardingHistoryEvents.filter = selFilter;
}
}

@ -28,12 +28,12 @@
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.out_channel}}</td>
</ng-container>
<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>
<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?.in_msatoshi/1000 | number:'1.0-0'}}</span></td>
</ng-container>
<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>
<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?.out_msatoshi/1000 | number:'1.0-0'}}</span></td>
</ng-container>
<ng-container matColumnDef="fee">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Fee mSat</th>

@ -21,7 +21,7 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
export class CLForwardingHistoryComponent implements OnInit, OnChanges {
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
@Input() forwardingHistoryData: any;
@Input() successfulEvents: any;
public displayedColumns = [];
public forwardingHistoryEvents: any;
public flgSticky = false;
@ -34,20 +34,20 @@ export class CLForwardingHistoryComponent implements OnInit, OnChanges {
this.screenSize = this.commonService.getScreenSize();
if(this.screenSize === ScreenSizeEnum.XS) {
this.flgSticky = false;
this.displayedColumns = ['status', 'in_msatoshi', 'out_msatoshi', 'actions'];
this.displayedColumns = ['in_msatoshi', 'out_msatoshi', 'actions'];
} else if(this.screenSize === ScreenSizeEnum.SM || this.screenSize === ScreenSizeEnum.MD) {
this.flgSticky = false;
this.displayedColumns = ['status', 'in_msatoshi', 'out_msatoshi', 'fee', 'actions'];
this.displayedColumns = ['received_time_str', 'in_msatoshi', 'out_msatoshi', 'fee', 'actions'];
} else {
this.flgSticky = true;
this.displayedColumns = ['status', 'received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'out_msatoshi', 'fee', 'actions'];
this.displayedColumns = ['received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'out_msatoshi', 'fee', 'actions'];
}
}
ngOnInit() {}
ngOnChanges() {
this.loadForwardingEventsTable(this.forwardingHistoryData);
this.loadForwardingEventsTable(this.successfulEvents);
}
onForwardingEventClick(selFEvent: ForwardingEventCL, event: any) {

@ -26,11 +26,15 @@
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit" tabindex="4">Fetch Events</button>
</div>
</form>
<div fxLayout="row" fxFlex="100" [ngClass]="{'error-border w-100 routing-tabs-block': flgLoading[0]==='error', 'w-100 routing-tabs-block': true}">
<div *ngIf="filteredData" fxLayout="row" fxFlex="100" [ngClass]="{'error-border w-100 routing-tabs-block': flgLoading[0]==='error', 'w-100 routing-tabs-block': true}">
<mat-tab-group fxLayout="column" fxFlex="100">
<mat-tab label="Forwarding History">
<div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<rtl-cl-forwarding-history *ngIf="errorMessage === '' && eventsData" [forwardingHistoryData]="eventsData"></rtl-cl-forwarding-history>
<rtl-cl-forwarding-history *ngIf="errorMessage === ''" [successfulEvents]="successfulData"></rtl-cl-forwarding-history>
</mat-tab>
<mat-tab label="Failed Transactions">
<div class="p-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<rtl-cl-failed-history *ngIf="errorMessage === ''" [failedEvents]="failedData"></rtl-cl-failed-history>
</mat-tab>
</mat-tab-group>
</div>

@ -19,7 +19,9 @@ import * as fromRTLReducer from '../../store/rtl.reducers';
export class CLRoutingComponent implements OnInit, OnDestroy {
public faMapSigns = faMapSigns;
public lastOffsetIndex = 0;
public eventsData = [];
public successfulData = [];
public failedData = [];
public filteredData = false;
public today = new Date(Date.now());
public lastMonthDay = new Date(
this.today.getFullYear(), this.today.getMonth(), this.today.getDate() - 30,
@ -35,14 +37,15 @@ export class CLRoutingComponent implements OnInit, OnDestroy {
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions) {}
ngOnInit() {
this.onEventsFetch();
this.actions$.pipe(takeUntil(this.unSubs[1]), filter((action) => action.type === RTLActions.RESET_CL_STORE))
.subscribe((resetClStore: RTLActions.ResetCLStore) => {
this.onEventsFetch();
});
// this.onEventsFetch();
// this.actions$.pipe(takeUntil(this.unSubs[1]), filter((action) => action.type === RTLActions.RESET_CL_STORE))
// .subscribe((resetClStore: RTLActions.ResetCLStore) => {
// this.onEventsFetch();
// });
this.store.select('cl')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
this.filteredData = false;
this.errorMessage = '';
rtlStore.effectErrorsCl.forEach(effectsErr => {
if (effectsErr.action === 'GetForwardingHistoryCL') {
@ -50,13 +53,21 @@ export class CLRoutingComponent implements OnInit, OnDestroy {
this.errorMessage = (typeof(effectsErr.message) === 'object') ? JSON.stringify(effectsErr.message) : effectsErr.message;
}
});
if (undefined !== rtlStore.forwardingHistory && undefined !== rtlStore.forwardingHistory.forwarding_events) {
if (rtlStore.forwardingHistory && rtlStore.forwardingHistory.forwarding_events) {
this.lastOffsetIndex = rtlStore.forwardingHistory.last_offset_index;
this.eventsData = rtlStore.forwardingHistory.forwarding_events;
rtlStore.forwardingHistory.forwarding_events.forEach(event => {
if (event.status === 'settled') {
this.successfulData.push(event);
} else {
this.failedData.push(event);
}
});
this.filteredData = true;
} else {
// To reset table after other Forwarding history calls
this.lastOffsetIndex = 0;
this.eventsData = [];
this.successfulData = [];
this.failedData = [];
}
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== rtlStore.forwardingHistory) ? false : true;
@ -83,7 +94,8 @@ export class CLRoutingComponent implements OnInit, OnDestroy {
resetData() {
this.endDate = new Date();
this.startDate = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate() - 1);
this.eventsData = [];
this.successfulData = [];
this.failedData = [];
this.lastOffsetIndex = 0;
}

@ -10,7 +10,7 @@ import { Location } from '@angular/common';
import { environment, API_URL } from '../../../environments/environment';
import { LoggerService } from '../../shared/services/logger.service';
import { SessionService } from '../../shared/services/session.service';
import { GetInfoCL, FeesCL, BalanceCL, LocalRemoteBalanceCL, PaymentCL, FeeRatesCL, ListInvoicesCL, InvoiceCL, GetInfoChainCL } from '../../shared/models/clModels';
import { GetInfoCL, FeesCL, BalanceCL, LocalRemoteBalanceCL, PaymentCL, FeeRatesCL, ListInvoicesCL, InvoiceCL } from '../../shared/models/clModels';
import * as fromRTLReducer from '../../store/rtl.reducers';
import * as RTLActions from '../../store/rtl.actions';
@ -669,21 +669,19 @@ export class CLEffects implements OnDestroy {
mergeMap((action: RTLActions.SetChannelTransactionCL) => {
this.store.dispatch(new RTLActions.ClearEffectErrorCl('SetChannelTransactionCL'));
return this.httpClient.post(this.CHILD_API_URL + environment.ON_CHAIN_API, action.payload)
.pipe(
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.FetchBalanceCL());
return {
type: RTLActions.OPEN_ALERT,
payload: { data: { type: AlertTypeEnum.SUCCESS, titleMessage: 'Fund Sent Successfully!' } }
};
}),
catchError((err: any) => {
this.store.dispatch(new RTLActions.EffectErrorCl({ action: 'SetChannelTransactionCL', code: err.status, message: err.error.error }));
this.handleErrorWithAlert('ERROR', 'Sending Fund Failed', this.CHILD_API_URL + environment.ON_CHAIN_API, err);
return of({type: RTLActions.VOID});
}));
.pipe(
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.FetchBalanceCL());
this.store.dispatch(new RTLActions.OpenSnackBar('Fund Sent Successfully.'));
return { type: RTLActions.VOID };
}),
catchError((err: any) => {
this.store.dispatch(new RTLActions.EffectErrorCl({ action: 'SetChannelTransactionCL', code: err.status, message: err.error.error }));
this.handleErrorWithAlert('ERROR', 'Sending Fund Failed', this.CHILD_API_URL + environment.ON_CHAIN_API, err);
return of({type: RTLActions.VOID});
}));
})
);

@ -25,10 +25,10 @@
<div fxFlex="23" tabindex="6" fxLayoutAlign="start center" *ngIf="showDetails">
<mat-slide-toggle color="primary" [(ngModel)]="private" matTooltip="Include routing hints for private channels" [matTooltipPosition]="'above'" name="private">Private Routing Hints</mat-slide-toggle>
</div>
<div fxLayout="row" fxFlex="100" fxFlex.gt-sm="30" fxLayoutAlign="space-between start" *ngIf="showDetails" class="mt-2">
<button fxFlex="32" fxLayoutAlign="center center" mat-stroked-button color="warn" tabindex="11" type="button" (click)="onDeleteExpiredInvoices()">Delete Expired</button>
<button fxFlex="32" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7" type="reset" (click)="resetData()">Clear Field</button>
<button fxFlex="32" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onAddInvoice(addInvoiceForm)" tabindex="8">Create Invoice</button>
<div fxLayout="row" fxFlex="100" fxFlex.gt-sm="40" fxLayoutAlign="space-between start" *ngIf="showDetails" class="mt-2">
<button fxFlex="31" fxLayoutAlign="center center" mat-stroked-button color="warn" tabindex="11" type="button" (click)="onDeleteExpiredInvoices()">Delete Expired</button>
<button fxFlex="31" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7" type="reset" (click)="resetData()">Clear Field</button>
<button fxFlex="31" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onAddInvoice(addInvoiceForm)" tabindex="8">Create Invoice</button>
</div>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between stretch" *ngIf="!showDetails" class="mt-1">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="9" type="reset" (click)="resetData()">Clear Field</button>
@ -70,8 +70,8 @@
</span></td>
</ng-container>
<ng-container matColumnDef="msatoshi">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Amount </th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center"> {{invoice.msatoshi | number}}
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Amount (Sats) </th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center"> {{invoice.msatoshi/1000 | number:'1.0-0'}}
</span></td>
</ng-container>
<ng-container matColumnDef="msatoshi_received">

@ -70,10 +70,10 @@ export class CLLightningInvoicesComponent implements OnInit, OnDestroy {
this.displayedColumns = ['expires_at_str', 'label', 'msatoshi', 'actions'];
} else if(this.screenSize === ScreenSizeEnum.MD) {
this.flgSticky = false;
this.displayedColumns = ['expires_at_str', 'label', 'msatoshi', 'msatoshi_received', 'actions'];
this.displayedColumns = ['expires_at_str', 'label', 'msatoshi', 'actions'];
} else {
this.flgSticky = true;
this.displayedColumns = ['expires_at_str', 'paid_at_str', 'label', 'msatoshi', 'msatoshi_received', 'actions'];
this.displayedColumns = ['expires_at_str', 'paid_at_str', 'label', 'msatoshi', 'actions'];
}
}

@ -33,35 +33,35 @@
</ng-container>
<ng-container matColumnDef="bolt11">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Bolt11</th>
<td mat-cell *matCellDef="let payment">{{payment?.bolt11 | slice:0:10}}...</td>
<td mat-cell *matCellDef="let payment">{{payment?.bolt11 | slice:0:25}}...</td>
</ng-container>
<ng-container matColumnDef="created_at">
<ng-container matColumnDef="created_at_str">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Created At</th>
<td mat-cell *matCellDef="let payment">{{payment?.created_at_str}}</td>
<td mat-cell *matCellDef="let payment">
<span *ngIf="payment.status === 'complete'" class="dot green" matTooltip="Completed" matTooltipPosition="right" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></span>
<span *ngIf="payment.status !== 'complete'" class="dot yellow" matTooltip="Incomplete" matTooltipPosition="right" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></span>
{{payment?.created_at_str}}
</td>
</ng-container>
<ng-container matColumnDef="destination">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Destination</th>
<td mat-cell *matCellDef="let payment">{{payment?.destination | slice:0:10}}...</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th>
<td mat-cell *matCellDef="let payment">{{payment?.status}}</td>
<td mat-cell *matCellDef="let payment">{{payment?.destination | slice:0:25}}...</td>
</ng-container>
<ng-container matColumnDef="msatoshi">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">mSatoshi</th>
<td mat-cell *matCellDef="let payment"><span
fxLayoutAlign="end center">{{payment?.msatoshi | number}}</span></td>
<ng-container matColumnDef="payment_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell *matCellDef="let payment">
<div>{{payment?.payment_hash}}</div>
</td>
</ng-container>
<ng-container matColumnDef="msatoshi_sent">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">mSatoshi Sent</th>
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Sats Sent</th>
<td mat-cell *matCellDef="let payment"><span
fxLayoutAlign="end center">{{payment?.msatoshi_sent | number}}</span></td>
fxLayoutAlign="end center">{{payment?.msatoshi_sent/1000 | 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 payment">
<div>{{payment?.payment_hash | slice:0:10}}...</div>
</td>
<ng-container matColumnDef="msatoshi">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Sats Received</th>
<td mat-cell *matCellDef="let payment"><span
fxLayoutAlign="end center">{{payment?.msatoshi/1000 | number}}</span></td>
</ng-container>
<ng-container matColumnDef="payment_preimage">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Pre Image</th>

@ -55,20 +55,21 @@ export class CLLightningPaymentsComponent implements OnInit, OnDestroy {
this.screenSize = this.commonService.getScreenSize();
if(this.screenSize === ScreenSizeEnum.XS) {
this.flgSticky = false;
this.displayedColumns = ['creation_date', 'actions'];
this.displayedColumns = ['created_at_str', 'actions'];
} else if(this.screenSize === ScreenSizeEnum.SM) {
this.flgSticky = false;
this.displayedColumns = ['created_at', 'msatoshi', 'msatoshi_sent', 'actions'];
this.displayedColumns = ['created_at_str', 'msatoshi_sent', 'msatoshi', 'actions'];
} else if(this.screenSize === ScreenSizeEnum.MD) {
this.flgSticky = false;
this.displayedColumns = ['created_at', 'status', 'msatoshi', 'msatoshi_sent', 'actions'];
this.displayedColumns = ['created_at_str', 'msatoshi_sent', 'msatoshi', 'actions'];
} else {
this.flgSticky = true;
this.displayedColumns = ['created_at', 'status', 'payment_hash', 'msatoshi', 'msatoshi_sent', 'actions'];
this.displayedColumns = ['created_at_str', 'payment_hash', 'msatoshi_sent', 'msatoshi', 'actions'];
}
}
ngOnInit() {
this.store.dispatch(new RTLActions.FetchPaymentsCL());
this.store.select('cl')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {

@ -1,4 +1,4 @@
<form fxLayout="column" fxFlex="98" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" fxLayoutAlign.gt-sm="space-between start" *ngIf="!sweepAll; else sweepAllBlock;" class="padding-gap overflow-x-hidden">
<form fxLayout="column" fxFlex="98" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" fxLayoutAlign.gt-sm="space-between start" *ngIf="!sweepAll; else sweepAllBlock;" class="padding-gap overflow-x-hidden" (submit)="onSendFunds()" (reset)="resetData()" #form="ngForm">
<mat-form-field fxFlex.gt-sm="55">
<input matInput [(ngModel)]="transaction.address" placeholder="Bitcoin Address" tabindex="1" name="address" required #address="ngModel">
<mat-error *ngIf="!transaction.address">Bitcoin address is required.</mat-error>
@ -32,13 +32,13 @@
</div>
<div fxLayout="column" fxFlex="100" fxFlex.gt-sm="40" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" fxLayoutAlign.gt-sm="space-between start"></div>
<div fxLayout="row" fxFlex="100" fxFlex.gt-sm="30" fxLayoutAlign="space-between stretch" class="mt-2">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7" type="reset" (click)="resetData()">Clear Fields</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit" tabindex="8" (click)="onSendFunds()">Send Funds</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7" type="reset">Clear Fields</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit" tabindex="8">Send Funds</button>
</div>
</form>
<ng-template #sweepAllBlock>
<form fxLayout="column" fxFlex="100" class="padding-gap overflow-x-hidden">
<div fxLayout="column" fxFlex="98" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" fxLayoutAlign.gt-sm="space-between start">
<div fxLayout="column" fxFlex="98" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" fxLayoutAlign.gt-sm="space-between start" (submit)="onSendFunds()" (reset)="resetData()" #formSweepAll>
<mat-form-field fxFlex.gt-sm="55">
<input matInput [(ngModel)]="transaction.address" placeholder="Bitcoin Address" tabindex="1" name="address" required #addressSweep="ngModel">
<mat-error *ngIf="!transaction.address">Bitcoin address is required.</mat-error>
@ -61,8 +61,8 @@
</div>
<div>
<div fxFlex="100" fxFlex.gt-sm="30" fxLayout="row" fxLayoutAlign="space-between stretch" class="mt-2">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7" type="reset" (click)="resetData()">Clear Fields</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit" tabindex="8" (click)="onSendFunds()">Send Funds</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7" type="reset">Clear Fields</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit" tabindex="8">Send Funds</button>
</div>
</div>
</form>

@ -1,4 +1,4 @@
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { Component, Input, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
@ -24,6 +24,8 @@ import { MessageDataField } from '../../../shared/models/alertData';
styleUrls: ['./on-chain-send.component.scss']
})
export class OnChainSendComponent implements OnInit, OnDestroy {
@ViewChild('form', { static: false }) form: any;
@ViewChild('formSweepAll', { static: false }) formSweepAll: any;
@Input() sweepAll = false;
private _sweepBalance = 0;
get sweepBalance() {
@ -144,6 +146,8 @@ export class OnChainSendComponent implements OnInit, OnDestroy {
this.store.dispatch(new RTLActions.OpenSpinner('Sending Funds...'));
this.store.dispatch(new RTLActions.SetChannelTransaction(this.transaction));
this.transaction = {};
if(this.form) { this.form.resetForm(); }
if(this.formSweepAll) { this.formSweepAll.resetForm(); }
}
get invalidValues(): boolean {

@ -62,7 +62,7 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
filter((action) => action.type === RTLActions.SET_PEERS))
.subscribe((action: RTLActions.SetPeers) => {
if(this.newlyAddedPeer !== '') {
this.snackBar.open('Peer added successfully.');
this.snackBar.open('Peer added successfully. Proceed to open the channel.');
this.selectedPeer = this.newlyAddedPeer;
this.newlyAddedPeer = '';
}

@ -22,7 +22,7 @@
<div fxLayout="column" fxFlex="100" fxFlex.gt-md="{{obj.width}}" *ngFor="let obj of objs; index as j;">
<h4 fxLayoutAlign="start" class="font-bold-500">{{obj.title}}</h4>
<span *ngIf="obj && obj.value; else emptyField">
<span [ngSwitch]="obj.type" class="foreground-secondary-text">
<span [ngSwitch]="obj.type" class="foreground-secondary-text" fxLayout="row" fxFlex="100" fxLayoutAlign="start stretch">
<ng-container *ngSwitchCase="dataTypeEnum.ARRAY"><span *ngFor="let arrayObj of obj.value" class="display-block">{{arrayObj}}</span></ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.NUMBER">{{obj.value | number:'1.0-3'}}</ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.BOOLEAN">{{obj.value === true ? 'True' : 'False'}}</ng-container>

@ -25,8 +25,8 @@ export const MENU_DATA: MenuRootNode = {
{id: 32, parentId: 3, name: 'Transactions', iconType: 'FA', icon: faExchangeAlt, link: '/cl/transactions', userPersona: UserPersonaEnum.ALL},
{id: 34, parentId: 3, name: 'Routing', iconType: 'FA', icon: faMapSigns, link: '/cl/routing', userPersona: UserPersonaEnum.ALL},
{id: 35, parentId: 3, name: 'Graph Lookup', iconType: 'FA', icon: faSearch, link: '/cl/lookups', userPersona: UserPersonaEnum.ALL},
{id: 36, parentId: 3, name: 'Rates', iconType: 'FA', icon: faPercentage, link: '/cl/rates', userPersona: UserPersonaEnum.OPERATOR},
{id: 37, parentId: 3, name: 'Node/Rates', iconType: 'FA', icon: faServer, link: '/cl/rates', userPersona: UserPersonaEnum.MERCHANT}
{id: 36, parentId: 3, name: 'Fee Rates', iconType: 'FA', icon: faPercentage, link: '/cl/rates', userPersona: UserPersonaEnum.OPERATOR},
{id: 37, parentId: 3, name: 'Node/Fee Rates', iconType: 'FA', icon: faServer, link: '/cl/rates', userPersona: UserPersonaEnum.MERCHANT}
]},
{id: 7, parentId: 0, name: 'Settings', iconType: 'FA', icon: faTools, link: '/settings', userPersona: UserPersonaEnum.ALL},
{id: 8, parentId: 0, name: 'Help', iconType: 'FA', icon: faQuestion, link: '/help', userPersona: UserPersonaEnum.ALL}

Loading…
Cancel
Save