CL UX
pull/260/head
Shahana Farooqui 4 years ago
parent f6254c01d8
commit 85b639629f

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.fc36fcae8eb3636c1114.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.e9128a76f55c487a9b24.js" defer></script><script src="polyfills-es5.b8e32dec482ae69710a2.js" nomodule defer></script><script src="polyfills.ebf9033c33aa4a5af12a.js" defer></script><script src="main.567798a446f68c375f5e.js" defer></script></body>
<script src="runtime.f5b171b45657a19a4591.js" defer></script><script src="polyfills-es5.b8e32dec482ae69710a2.js" nomodule defer></script><script src="polyfills.ebf9033c33aa4a5af12a.js" defer></script><script src="main.5bfb336cbdd2b95045e5.js" defer></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

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

@ -12,7 +12,7 @@ exports.listChannels = (req, res, next) => {
local = (channel.msatoshi_to_us) ? channel.msatoshi_to_us : 0;
remote = (channel.msatoshi_to_them) ? channel.msatoshi_to_them : 0;
total = channel.msatoshi_total ? channel.msatoshi_total : 0;
channel.balancedness = (1 - Math.abs((local-remote)/total)).toFixed(3);
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local-remote)/total)).toFixed(3);
})
res.status(200).json(body);
})

@ -29,7 +29,7 @@ exports.getAllChannels = (req, res, next) => {
local = (channel.local_balance) ? +channel.local_balance : 0;
remote = (channel.remote_balance) ? +channel.remote_balance : 0;
total = local + remote;
channel.balancedness = (1 - Math.abs((local-remote)/total)).toFixed(3);
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local-remote)/total)).toFixed(3);
return getAliasForChannel(channel);
})
)

@ -2,12 +2,12 @@
<div fxLayout="column" fxFlex="9" fxLayoutAlign="end start">
<span class="dashboard-capacity-header this-channel-capacity">Total Capacity</span>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
<mat-hint fxFlex="40" fxLayoutAlign="start center" class="font-size-90"><strong class="font-weight-900 mr-5px">Local:</strong>{{channelBalances.localBalance || 0 | number}} Sats</mat-hint>
<mat-hint fxFlex="40" fxLayoutAlign="start center" class="font-size-90"><strong class="font-weight-900 mr-5px">Local:</strong>{{channelBalances.localBalance || 0 | number:'1.0-0'}} Sats</mat-hint>
<mat-hint fxFlex="20" fxLayoutAlign="center center" class="font-size-90">
<fa-icon [icon]="faBalanceScale" class="mr-3px" matTooltip="Balance Score"></fa-icon>
({{channelBalances.balancedness || 0 | number}})
</mat-hint>
<mat-hint fxFlex="40" fxLayoutAlign="end center" class="font-size-90"><strong class="font-weight-900 mr-5px">Remote:</strong>{{channelBalances.remoteBalance || 0 | number}} Sats</mat-hint>
<mat-hint fxFlex="40" fxLayoutAlign="end center" class="font-size-90"><strong class="font-weight-900 mr-5px">Remote:</strong>{{channelBalances.remoteBalance || 0 | number:'1.0-0'}} Sats</mat-hint>
</div>
<mat-progress-bar class="dashboard-progress-bar this-channel-bar" mode="determinate" color="accent" value="{{channelBalances.localBalance && channelBalances.localBalance > 0 ? ((+channelBalances.localBalance/((+channelBalances.localBalance)+(+channelBalances.remoteBalance)))*100) : 0}}"></mat-progress-bar>
</div>
@ -17,12 +17,12 @@
<div *ngFor="let channel of allChannels" class="mt-2">
<span class="dashboard-capacity-header" matTooltip="{{channel.alias || channel.id}}" matTooltipDisabled="{{(channel.alias || channel.id).length < 26}}">{{(channel.alias || channel.id) | slice:0:24}}{{(channel.alias || channel.id).length > 25 ? '...' : ''}}</span>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
<mat-hint fxFlex="40" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Local:</strong>{{channel.msatoshi_to_us/1000 || 0 | number}} Sats</mat-hint>
<mat-hint fxFlex="40" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Local:</strong>{{channel.msatoshi_to_us/1000 || 0 | number:'1.0-0'}} Sats</mat-hint>
<mat-hint fxFlex="20" fxLayoutAlign="center center" class="font-size-90 color-primary">
<fa-icon [icon]="faBalanceScale" class="color-primary mr-3px" matTooltip="Balance Score"></fa-icon>
({{channel.balancedness || 0 | number}})
</mat-hint>
<mat-hint fxFlex="40" fxLayoutAlign="end center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Remote:</strong>{{channel.msatoshi_to_them/1000 || 0 | number}} Sats</mat-hint>
<mat-hint fxFlex="40" fxLayoutAlign="end center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Remote:</strong>{{channel.msatoshi_to_them/1000 || 0 | number:'1.0-0'}} Sats</mat-hint>
</div>
<mat-progress-bar class="dashboard-progress-bar" mode="determinate" value="{{channel.msatoshi_to_us && channel.msatoshi_to_us > 0 ? ((+channel.msatoshi_to_us/((+channel.msatoshi_to_us)+(+channel.msatoshi_to_them)))*100) : 0}}"></mat-progress-bar>
</div>

@ -1,7 +1,7 @@
<div fxLayout="column" fxLayoutAlign="space-between stretch" fxFlex="100">
<div fxLayout="column" fxFlex="9" fxLayoutAlign="end start">
<span class="dashboard-capacity-header this-channel-capacity">Total Capacity</span>
<mat-hint class="font-size-90">{{totalLiquidity | number}} Sats</mat-hint>
<mat-hint class="font-size-90">{{totalLiquidity | number:'1.0-0'}} Sats</mat-hint>
<mat-progress-bar class="dashboard-progress-bar this-channel-bar" mode="determinate" color="accent" value="100"></mat-progress-bar>
</div>
<div fxLayout="column" fxFlex="3" fxLayoutAlign="end stretch"><mat-divider class="dashboard-divider"></mat-divider></div>
@ -10,8 +10,8 @@
<div *ngFor="let channel of allChannels" class="mt-2">
<span class="dashboard-capacity-header" matTooltip="{{channel.alias || channel.id}}" matTooltipDisabled="{{(channel.alias || channel.id).length < 26}}">{{(channel.alias || channel.id) | slice:0:24}}{{(channel.alias || channel.id).length > 25 ? '...' : ''}}</span>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
<mat-hint *ngIf="direction === 'In'" fxFlex="100" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Capacity: </strong>{{channel.msatoshi_to_them/1000 || 0 | number}} Sats</mat-hint>
<mat-hint *ngIf="direction === 'Out'" fxFlex="100" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Capacity: </strong>{{channel.msatoshi_to_us/1000 || 0 | number}} Sats</mat-hint>
<mat-hint *ngIf="direction === 'In'" fxFlex="100" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Capacity: </strong>{{channel.msatoshi_to_them/1000 || 0 | number:'1.0-0'}} Sats</mat-hint>
<mat-hint *ngIf="direction === 'Out'" fxFlex="100" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Capacity: </strong>{{channel.msatoshi_to_us/1000 || 0 | number:'1.0-0'}} Sats</mat-hint>
</div>
<mat-progress-bar *ngIf="direction === 'In'" class="dashboard-progress-bar" mode="determinate" value="{{(totalLiquidity > 0) ? ((+channel.msatoshi_to_them/1000 || 0)/(totalLiquidity) * 100) : 0}}"></mat-progress-bar>
<mat-progress-bar *ngIf="direction === 'Out'" class="dashboard-progress-bar" mode="determinate" value="{{(totalLiquidity > 0) ? ((+channel.msatoshi_to_us/1000 || 0)/(totalLiquidity) * 100) : 0}}"></mat-progress-bar>

@ -168,26 +168,20 @@ export class CLHomeComponent implements OnInit, OnDestroy {
}
this.channelsStatus = {
active: { channels: rtlStore.information.num_active_channels, capacity: 0 },
inactive: { channels: rtlStore.information.num_inactive_channels, capacity: 0 },
pending: { channels: rtlStore.information.num_pending_channels, capacity: 0 }
active: { channels: rtlStore.information.num_active_channels, capacity: rtlStore.localRemoteBalance.localBalance },
inactive: { channels: rtlStore.information.num_inactive_channels, capacity: rtlStore.localRemoteBalance.pendingBalance | 0 },
pending: { channels: rtlStore.information.num_pending_channels, capacity: rtlStore.localRemoteBalance.inactiveBalance | 0 }
};
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.allChannels = rtlStore.allChannels.filter(channel => channel.connected);
this.allChannels = rtlStore.allChannels.filter(channel => channel.state === 'CHANNELD_NORMAL' && channel.connected);
this.allChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels, 'balancedness')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels.filter(channel => channel.msatoshi_to_them > 0), 'msatoshi_to_them')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels.filter(channel => channel.msatoshi_to_us > 0), 'msatoshi_to_us')));
this.allChannels.forEach(channel => {
this.totalInboundLiquidity = this.totalInboundLiquidity + channel.msatoshi_to_them;
this.totalOutboundLiquidity = this.totalOutboundLiquidity + channel.msatoshi_to_us;
this.totalInboundLiquidity = this.totalInboundLiquidity + Math.ceil(channel.msatoshi_to_them/1000);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + Math.floor(channel.msatoshi_to_us/1000);
});
if (this.totalInboundLiquidity>0) {
this.totalInboundLiquidity = this.totalInboundLiquidity / 1000;
}
if (this.totalOutboundLiquidity>0) {
this.totalOutboundLiquidity = this.totalOutboundLiquidity / 1000;
}
if (this.flgLoading[5] !== 'error') {
this.flgLoading[5] = (this.allChannels && this.allChannels.length) ? false : true;
}

@ -23,13 +23,13 @@
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="4" type="submit" (click)="onLookup()">Lookup</button>
</div>
</form>
<div fxFlex="100" fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" *ngIf="lookupValue && flgSetLookupValue" class="w-100 mt-2">
<div fxFlex="100" fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" *ngIf="flgSetLookupValue" class="w-100 mt-2">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="start center">
<span class="page-title font-bold-500">{{lookupFields[selectedFieldId].name}} Details</span>
</div>
<div [ngSwitch]="selectedFieldId" fxLayout="row" fxFlex="100" fxLayoutAlign="start center">
<span fxFlex="100" *ngSwitchCase="0"><rtl-cl-node-lookup [lookupResult]="lookupValue"></rtl-cl-node-lookup></span>
<span fxFlex="100" *ngSwitchCase="1"><rtl-cl-channel-lookup [lookupResult]="lookupValue"></rtl-cl-channel-lookup></span>
<span fxFlex="100" *ngSwitchCase="0"><div *ngIf="nodeLookupValue.nodeid !== ''; else errorBlock"><rtl-cl-node-lookup [lookupResult]="nodeLookupValue"></rtl-cl-node-lookup></div></span>
<span fxFlex="100" *ngSwitchCase="1"><div *ngIf="channelLookupValue.length>0; else errorBlock"><rtl-cl-channel-lookup [lookupResult]="channelLookupValue"></rtl-cl-channel-lookup></div></span>
<span fxFlex="100" *ngSwitchDefault><h3>Error! Unable to find details!</h3></span>
</div>
</div>
@ -37,3 +37,6 @@
</mat-card>
</div>
</div>
<ng-template #errorBlock>
<h3>Error! Unable to find details!</h3>
</ng-template>

@ -20,7 +20,8 @@ import { CommonService } from '../../shared/services/common.service';
export class CLLookupsComponent implements OnInit, OnDestroy {
@ViewChild('form', { static: false }) form: any;
public lookupKey = '';
public lookupValue = {};
public nodeLookupValue = {nodeid: ''};
public channelLookupValue = [];
public flgSetLookupValue = false;
public temp: any;
public messageObj = [];
@ -49,16 +50,17 @@ export class CLLookupsComponent implements OnInit, OnDestroy {
this.flgLoading[0] = true;
switch (this.selectedFieldId) {
case 0:
this.lookupValue = JSON.parse(JSON.stringify(resLookup.payload[0]));
this.nodeLookupValue = resLookup.payload[0] ? JSON.parse(JSON.stringify(resLookup.payload[0])) : {nodeid: ''};
break;
case 1:
this.lookupValue = JSON.parse(JSON.stringify(resLookup.payload));
this.channelLookupValue = resLookup.payload ? JSON.parse(JSON.stringify(resLookup.payload)) : [];
break;
default:
break;
}
this.flgSetLookupValue = true;
this.logger.info(this.lookupValue);
this.logger.info(this.nodeLookupValue);
this.logger.info(this.channelLookupValue);
}
if (resLookup.type === RTLActions.EFFECT_ERROR_CL && resLookup.payload.action === 'LookupCL') {
this.flgLoading[0] = 'error';
@ -69,14 +71,15 @@ export class CLLookupsComponent implements OnInit, OnDestroy {
onLookup() {
if(!this.lookupKey) { return true; }
this.flgSetLookupValue = false;
this.lookupValue = {};
this.nodeLookupValue = {nodeid: ''};
this.channelLookupValue = [];
this.store.dispatch(new RTLActions.OpenSpinner('Searching ' + this.lookupFields[this.selectedFieldId].name + '...'));
switch (this.selectedFieldId) {
case 0:
this.store.dispatch(new RTLActions.PeerLookupCL(this.lookupKey.trim()));
break;
case 1:
this.store.dispatch(new RTLActions.ChannelLookupCL(this.lookupKey.trim()));
this.store.dispatch(new RTLActions.ChannelLookupCL({shortChannelID: this.lookupKey.trim(), showError: false}));
break;
default:
break;
@ -89,18 +92,16 @@ export class CLLookupsComponent implements OnInit, OnDestroy {
}
resetData() {
this.form.resetForm();
this.flgSetLookupValue = false;
this.selectedFieldId = 0;
this.lookupKey = '';
this.lookupValue = {};
this.flgLoading.forEach((flg, i) => {
this.flgLoading[i] = true;
});
this.nodeLookupValue = {nodeid: ''};
this.channelLookupValue = [];
this.form.resetForm();
}
clearLookupValue() {
this.lookupValue = {};
this.nodeLookupValue = {nodeid: ''};
this.channelLookupValue = [];
this.flgSetLookupValue = false;
}

@ -17,7 +17,8 @@ export class CLNodeLookupComponent implements OnInit {
constructor() { }
ngOnInit() {
this.addresses = new MatTableDataSource<any>([...this.lookupResult.addresses]);
this.addresses = this.lookupResult.addresses ? new MatTableDataSource<any>([...this.lookupResult.addresses]) : new MatTableDataSource([]);
this.addresses.data = this.lookupResult.addresses ? this.lookupResult.addresses : [];
this.addresses.sort = this.sort;
}

@ -54,7 +54,7 @@
<div fxLayout="row">
<mat-hint fxFlex="100" fxLayoutAlign="center center" class="font-size-80">{{channel.balancedness || 0 | number}}</mat-hint>
</div>
<mat-progress-bar mode="determinate" value="{{channel.local_balance && channel.local_balance > 0 ? ((+channel.local_balance/((+channel.local_balance)+(+channel.remote_balance)))*100) : 0}}"></mat-progress-bar>
<mat-progress-bar mode="determinate" value="{{channel.msatoshi_to_us && channel.msatoshi_to_us > 0 ? ((+channel.msatoshi_to_us/((+channel.msatoshi_to_us)+(+channel.msatoshi_to_them)))*100) : 0}}"></mat-progress-bar>
</td>
</ng-container>
<ng-container matColumnDef="actions">

@ -72,7 +72,7 @@ export class CLChannelOpenTableComponent implements OnInit, OnDestroy {
this.numPeers = (rtlStore.peers && rtlStore.peers.length) ? rtlStore.peers.length : 0;
this.totalBalance = rtlStore.balance.totalBalance;
if (rtlStore.allChannels) {
this.loadChannelsTable(rtlStore.allChannels.filter(channel => channel.state === 'CHANNELD_NORMAL'));
this.loadChannelsTable(rtlStore.allChannels.filter(channel => channel.state === 'CHANNELD_NORMAL' && channel.connected));
}
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (rtlStore.allChannels) ? false : true;
@ -82,10 +82,11 @@ export class CLChannelOpenTableComponent implements OnInit, OnDestroy {
}
onViewRemotePolicy(selChannel: ChannelCL) {
this.store.dispatch(new RTLActions.ChannelLookupCL(selChannel.short_channel_id));
this.store.dispatch(new RTLActions.ChannelLookupCL({shortChannelID: selChannel.short_channel_id, showError: true}));
this.clEffects.setLookupCL
.pipe(take(1))
.subscribe((resLookup: ChannelEdgeCL[]) => {
if(resLookup.length === 0) { return false; }
let remoteNode: ChannelEdgeCL = {};
if(resLookup[0].source !== this.information.id) {
remoteNode = resLookup[0];

@ -72,7 +72,7 @@ export class CLChannelPendingTableComponent implements OnInit, OnDestroy {
this.numPeers = (rtlStore.peers && rtlStore.peers.length) ? rtlStore.peers.length : 0;
this.totalBalance = rtlStore.balance.totalBalance;
if (rtlStore.allChannels) {
this.loadChannelsTable(rtlStore.allChannels.filter(channel => channel.state !== 'CHANNELD_NORMAL'));
this.loadChannelsTable(rtlStore.allChannels.filter(channel => !(channel.state === 'CHANNELD_NORMAL' && channel.connected)));
}
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (rtlStore.allChannels) ? false : true;

@ -8,7 +8,7 @@
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<span matBadge="{{pendingChannels}}" matBadgeOverlap="false" class="tab-badge">Pending</span>
<span matBadge="{{pendingChannels}}" matBadgeOverlap="false" class="tab-badge">Pending/Inactive</span>
</ng-template>
<rtl-cl-channel-pending-table></rtl-cl-channel-pending-table>
</mat-tab>

@ -26,7 +26,7 @@ export class CLChannelsTablesComponent implements OnInit, OnDestroy {
this.openChannels = 0;
this.pendingChannels = 0;
rtlStore.allChannels.forEach(channel => {
if(channel.state === 'CHANNELD_NORMAL') {
if(channel.state === 'CHANNELD_NORMAL' && channel.connected) {
this.openChannels++;
} else {
this.pendingChannels++;

@ -511,7 +511,7 @@ export class CLEffects implements OnDestroy {
ofType(RTLActions.CHANNEL_LOOKUP_CL),
mergeMap((action: RTLActions.ChannelLookupCL) => {
this.store.dispatch(new RTLActions.ClearEffectErrorCl('LookupCL'));
return this.httpClient.get(this.CHILD_API_URL + environment.NETWORK_API + '/listChannel/' + action.payload)
return this.httpClient.get(this.CHILD_API_URL + environment.NETWORK_API + '/listChannel/' + action.payload.shortChannelID)
.pipe(
map((resChannel) => {
this.logger.info(resChannel);
@ -522,8 +522,13 @@ export class CLEffects implements OnDestroy {
};
}),
catchError((err: any) => {
this.store.dispatch(new RTLActions.EffectErrorCl({ action: 'LookupCL', code: err.status, message: err.error.message }));
this.handleErrorWithAlert('ERROR', 'Channel Lookup Failed', this.CHILD_API_URL + environment.NETWORK_API + '/listChannel/' + action.payload, err);
if(action.payload.showError) {
this.store.dispatch(new RTLActions.EffectErrorCl({ action: 'LookupCL', code: err.status, message: err.error.message }));
this.handleErrorWithAlert('ERROR', 'Channel Lookup Failed', this.CHILD_API_URL + environment.NETWORK_API + '/listChannel/' + action.payload.shortChannelID, err);
} else {
this.store.dispatch(new RTLActions.CloseSpinner());
}
this.store.dispatch(new RTLActions.SetLookupCL([]));
return of({type: RTLActions.VOID});
})
);

@ -35,19 +35,19 @@
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onAddInvoice(addInvoiceForm)" tabindex="10">Create Invoice</button>
</div>
</form>
<div fxLayout="column" fxLayoutAlign="start stretch" *ngIf="showDetails">
<div fxLayout="column" fxLayoutAlign="start stretch" [ngClass]="{'display-none': !showDetails}">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container mt-2">
<div fxFlex="70">
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Invoices History</span>
<span class="page-title">Payments History</span>
</div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container">
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container w-100">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="invoices" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<table mat-table #table fxFlex="100" [dataSource]="invoices" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="expires_at_str">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Expiry Date </th>
<td mat-cell *matCellDef="let invoice">
@ -64,25 +64,11 @@
<th mat-header-cell *matHeaderCellDef mat-sort-header> Label </th>
<td mat-cell *matCellDef="let invoice">{{invoice.label}}</td>
</ng-container>
<ng-container matColumnDef="pay_index">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Pay Index </th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center"> {{invoice?.pay_index | number}}
</span></td>
</ng-container>
<ng-container matColumnDef="msatoshi">
<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">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Received mSatoshi </th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center">
{{invoice.msatoshi_received | number}} </span></td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell class="pl-4" *matHeaderCellDef mat-sort-header> Description </th>
<td mat-cell class="pl-4" *matCellDef="let invoice">{{invoice.description}}</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="pl-3 pr-3"><span fxLayoutAlign="end center">Actions</span></th>
<td mat-cell *matCellDef="let invoice" [ngClass]="{'pl-3': screenSize !== screenSizeEnum.XS}">
@ -96,9 +82,9 @@
</ng-container>
<tr mat-footer-row *matFooterRowDef="['no_invoice']" [ngClass]="{'display-none': invoices.data && invoices.data.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.label == newlyAddedInvoiceMemo && row.value == newlyAddedInvoiceValue && flgAnimate) ? 'added' : 'notAdded'" class="row-invoices"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.label == newlyAddedInvoiceMemo && row.value == newlyAddedInvoiceValue && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table>
<mat-paginator [length]="totalInvoices" [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" (page)="onPageChange($event)" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator>
</div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator>
</div>
</div>

@ -4,9 +4,9 @@ import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginatorIntl } from '@angular/material';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { TimeUnitEnum, CurrencyUnitEnum, TIME_UNITS, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
import { TimeUnitEnum, CurrencyUnitEnum, TIME_UNITS, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfoCL, InvoiceCL } from '../../../shared/models/clModels';
import { LoggerService } from '../../../shared/services/logger.service';
@ -30,6 +30,7 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
export class CLLightningInvoicesComponent implements OnInit, OnDestroy {
@Input() showDetails = true;
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
faHistory = faHistory;
public selNode: SelNodeChild = {};
public newlyAddedInvoiceMemo = '';
@ -43,6 +44,7 @@ export class CLLightningInvoicesComponent implements OnInit, OnDestroy {
public displayedColumns = [];
public invoicePaymentReq = '';
public invoices: any;
public invoiceJSONArr: InvoiceCL[] = [];
public information: GetInfoCL = {};
public flgLoading: Array<Boolean | 'error'> = [true];
public flgSticky = false;
@ -54,8 +56,6 @@ export class CLLightningInvoicesComponent implements OnInit, OnDestroy {
public timeUnitEnum = TimeUnitEnum;
public timeUnits = TIME_UNITS;
public selTimeUnit = TimeUnitEnum.SECS;
private firstOffset = -1;
private lastOffset = -1;
public screenSize = '';
public screenSizeEnum = ScreenSizeEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
@ -90,10 +90,15 @@ export class CLLightningInvoicesComponent implements OnInit, OnDestroy {
this.selNode = rtlStore.nodeSettings;
this.information = rtlStore.information;
this.totalInvoices = rtlStore.totalInvoices;
this.firstOffset = +rtlStore.invoices.first_index_offset;
this.lastOffset = +rtlStore.invoices.last_index_offset;
this.logger.info(rtlStore);
this.loadInvoicesTable(rtlStore.invoices.invoices ? rtlStore.invoices.invoices : []);
this.invoiceJSONArr = (rtlStore.invoices.invoices && rtlStore.invoices.invoices.length > 0) ? rtlStore.invoices.invoices : [];
this.invoices = (rtlStore.invoices.invoices) ? new MatTableDataSource([]) : new MatTableDataSource<InvoiceCL>([...this.invoiceJSONArr]);
this.invoices.data = this.invoiceJSONArr;
this.invoices.sort = this.sort;
this.invoices.paginator = this.paginator;
setTimeout(() => { this.flgAnimate = false; }, 5000);
this.logger.info(this.invoices);
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== rtlStore.invoices) ? false : true;
}
@ -150,13 +155,6 @@ export class CLLightningInvoicesComponent implements OnInit, OnDestroy {
}}));
}
loadInvoicesTable(invoices) {
this.invoices = new MatTableDataSource<InvoiceCL>([...invoices]);
this.invoices.sort = this.sort;
setTimeout(() => { this.flgAnimate = false; }, 5000);
this.logger.info(this.invoices);
}
resetData() {
this.label = '';
this.description = '';
@ -171,20 +169,6 @@ export class CLLightningInvoicesComponent implements OnInit, OnDestroy {
this.invoices.filter = selFilter;
}
onPageChange(event: any) {
let reversed = true;
let index_offset = this.firstOffset;
if (event.pageIndex < event.previousPageIndex) {
reversed = false;
index_offset = this.lastOffset;
}
if (event.pageIndex === event.previousPageIndex) {
reversed = true;
index_offset = 0;
}
this.store.dispatch(new RTLActions.FetchInvoicesCL({num_max_invoices: event.pageSize, index_offset: index_offset, reversed: reversed}));
}
onInvoiceValueChange() {
if(this.invoiceValue > 99) {
this.invoiceValueHint = '';

@ -6,8 +6,8 @@ import { Store } from '@ngrx/store';
import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { GetInfoCL, PaymentCL, PayRequestCL, ChannelCL } from '../../../shared/models/clModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, FEE_LIMIT_TYPES } from '../../../shared/services/consts-enums-functions';
import { GetInfoCL, PaymentCL, PayRequestCL } from '../../../shared/models/clModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service';

@ -84,8 +84,9 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
onViewRemotePolicy(selChannel: Channel) {
this.store.dispatch(new RTLActions.ChannelLookup(selChannel.chan_id.toString() + '/' + this.information.identity_pubkey));
this.lndEffects.setLookup
.pipe(take(1))
.subscribe(resLookup => {
.pipe(take(1))
.subscribe(resLookup => {
if(!resLookup.fee_base_msat && !resLookup.fee_rate_milli_msat && !resLookup.time_lock_delta) { return false; }
const reorderedChannelPolicy = [
[{key: 'fee_base_msat', value: resLookup.fee_base_msat, title: 'Base Fees (mSats)', width: 34, type: DataTypeEnum.NUMBER},
{key: 'fee_rate_milli_msat', value: resLookup.fee_rate_milli_msat, title: 'Fee Rate (milli mSats)', width: 33, type: DataTypeEnum.NUMBER},

@ -991,6 +991,7 @@ export class LNDEffects implements OnDestroy {
catchError((err: any) => {
this.store.dispatch(new RTLActions.EffectErrorLnd({ action: 'Lookup', code: err.status, message: err.error.message }));
this.handleErrorWithAlert('ERROR', 'Channel Lookup Failed', this.CHILD_API_URL + environment.NETWORK_API + '/edge/' + action.payload, err);
this.store.dispatch(new RTLActions.SetLookup({}));
return of({type: RTLActions.VOID});
})
);

@ -140,20 +140,20 @@ export function LNDReducer(state = initLNDState, action: RTLActions.RTLActions)
case RTLActions.SET_ALL_CHANNELS:
let localBal = 0, remoteBal = 0, activeChannels = 0, inactiveChannels = 0, totalCapacityActive = 0, totalCapacityInactive = 0;
if (action.payload) {
action.payload.filter(channel => {
if (channel.local_balance) {
localBal = +localBal + +channel.local_balance;
} else {
channel.local_balance = 0;
}
if (channel.remote_balance) {
remoteBal = +remoteBal + +channel.remote_balance;
} else {
channel.remote_balance = 0;
}
action.payload.forEach(channel => {
if (channel.active === true) {
totalCapacityActive = totalCapacityActive + +channel.local_balance;
activeChannels = activeChannels + 1;
if (channel.local_balance) {
localBal = +localBal + +channel.local_balance;
} else {
channel.local_balance = 0;
}
if (channel.remote_balance) {
remoteBal = +remoteBal + +channel.remote_balance;
} else {
channel.remote_balance = 0;
}
} else {
totalCapacityInactive = totalCapacityInactive + +channel.local_balance;
inactiveChannels = inactiveChannels + 1;

@ -8,9 +8,12 @@
<div fxFlex="100" *ngFor="let helpTopic of helpTopics">
<mat-expansion-panel class="flat-expansion-panel help-expansion mb-2px">
<mat-expansion-panel-header>
<mat-panel-title>{{helpTopic.question}}</mat-panel-title>
<mat-panel-title>{{helpTopic.help.question}}</mat-panel-title>
</mat-expansion-panel-header>
<mat-panel-description><span class="pre-wrap" [innerHTML]="helpTopic.answer" target></span></mat-panel-description>
<mat-panel-description fxLayout="column" fxFlex="100" fxLayoutAlign="start start">
<span class="pre-wrap" [innerHTML]="helpTopic.help.answer"></span>
<a class="mt-2" [routerLink]="flgLoggedIn ? LNPLink + helpTopic.help.link : '/login'">{{!flgLoggedIn ? 'Login to go to the page' : helpTopic.help.linkCaption}}</a>
</mat-panel-description>
</mat-expansion-panel>
</div>
</div>

@ -1,88 +1,141 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { faQuestion } from '@fortawesome/free-solid-svg-icons';
export class HelpTopic {
question: string;
answer: string;
import { HelpTopic, LightningNode } from '../../models/RTLconfig';
import { SessionService } from '../../services/session.service';
constructor(ques: string, ans: string) {
this.question = ques;
this.answer = ans;
}
}
import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-help',
templateUrl: './help.component.html',
styleUrls: ['./help.component.scss']
})
export class HelpComponent implements OnInit {
export class HelpComponent implements OnInit, OnDestroy {
public helpTopics: Array<HelpTopic> = [];
public faQuestion = faQuestion;
public selNode: LightningNode;
public LNPLink = '/lnd/';
public flgLoggedIn = false;
private unSubs = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor() {}
constructor(private store: Store<fromRTLReducer.RTLState>, private sessionService: SessionService) {
this.helpTopics.push(new HelpTopic({
question: 'Getting started',
answer: 'Funding your node is the first step to get started.\n' +
'Go to the "On-chain" page of the app:\n' +
'1. Generate a new address on the "Recieve" tab.\n'+
'2. Send funds to the address.\n' +
'3. Wait for the balance to be confirmed on-chain before proceeding further.\n' +
'3. Connecting with network peers and opening channels is next.\n',
link: 'onchain',
linkCaption: 'On-Chain page'
}));
this.helpTopics.push(new HelpTopic({
question: 'Connect with peers',
answer: 'Connect with network peers to open channels with them.\n' +
'Go to "Peer/Channels" page under the "Lightning" menu :\n' +
'1. Get the peer pubkey and host address in the pubkey@ip:port format.\n' +
'2. On the "Peers" enter the peer address and connect.\n' +
'3. Once the peer is connected, you can open channel with the peer.\n'+
'4. A variety of actions can be performed on the connected peers page for each peer:\n'+
' a. View Info - View the peer details.\n' +
' b. Open Channel - Open channel with the peer.\n' +
' c. Disconnect - Disconnect from the peer.\n',
link: 'peerschannels',
linkCaption: 'Peers/Channels page'
}));
this.helpTopics.push(new HelpTopic({
question: 'Opening Channels',
answer: 'Open channels with a connected network peer.\n' +
'Go to "Peer/Channels" page under the "Lightning" menu:\n' +
'1. On the "Channels" section, select the alias of the connected peer from the drop-down\n' +
'2. Specify the amount to commit to the channel and click on "Open Channel".\n' +
'3. There are a variety of options available while opening a channel. \n' +
' a. Private Channel - When this option is selected, a private channel is opened with the peer. \n' +
' b. Priority (advanced option) - Specify either Target confirmation Block or Fee in Sat/Byte. \n' +
' c. Spend Unconfirmd Output (advanced option) - Allow channels to be opened with unconfirmed UTXOs.\n' +
'4. Track the pending open channels under the "Pending" tab . \n' +
'5. Wait for the channel to be confirmed. Only a confimed channel can be used for payments or routing. \n',
link: 'peerschannels',
linkCaption: 'Peers/Channels page'}));
this.helpTopics.push(new HelpTopic({
question: 'Channel Management',
answer: 'Channel maintenance and balance score.\n' +
'Go to "Peer/Channels" page under the "Lightning" menu:\n' +
'1. A variety of actions can be perfomed on the open channels under the "Open" tab, with the "Actions" button:\n' +
' a. View Info - View the channel details.\n' +
' b. View Remote Fee - View the fee policy on the channel of the remote peer.\n' +
' c. Update Fee Policy - Modify the fee policy on the channel.\n' +
' d. Close Channel - Close the channel.\n' +
'2. Balance Score is balancedness metric score for the channel:\n' +
' a. It helps measure how balanced the remote and local balance on a channel is.\n' +
' b. A perfectly balanced channel has a score of one, where a completely lopsided one has a score of zero.\n' +
' c. The formular for calculating the score is "1 - abs((local bal - remote bal)/total bal)".\n',
link: 'peerschannels',
linkCaption: 'Peers/Channels page'
}));
this.helpTopics.push(new HelpTopic({
question: 'Lightning Transactions - Payments',
answer: 'Sending Payments from your node.\n' +
'Go to "Transactions" page under the "Lightning" menu :\n' +
'Payments - Payments tab is for making payments via your node\n' +
' 1. Input a non-expired lightning invoice (Bolt11 format) in the "Payment request" field and click on "Send Payment" to send.\n' +
' 2. Advanced option # 1 - Specify a limit on the routing fee you are willing to pay for the payment.\n' +
' 3. Advanced option # 2 - Specify the outgoing channel through which you want the payment to go out.\n',
link: 'transactions',
linkCaption: 'Transactions page'
}));
this.helpTopics.push(new HelpTopic({
question: 'Lightning Transactions - Invoices',
answer: 'Receiving Payments on your node.\n' +
'Go to "Transactions" page under the "Lightning" menu :\n' +
'Invoices - Invoices tab is for receiving payments on your node.\n' +
' 1. Memo - Description you want to provide on the invoice.\n' +
' 2. Expiry - The time period, after which the invoice will be invalid.\n' +
' 3. Private Routing Hints - Generate an invoice with routing hints for private channels.\n',
link: 'transactions',
linkCaption: 'Transactions page'
}));
this.helpTopics.push(new HelpTopic({
question: 'Lightning Transactions - Query Route',
answer: 'Querying Payment Routes.\n' +
'Go to "Transactions" page under the "Lightning" menu :\n' +
'Query Routes - Query Routes tab is for querying a potential path to a node and a routing fee estimate for a payment amount.\n'+
' 1. Destination Pubkey - Pubkey of the node, you want to send the payment to.\n' +
' 2. Amount - Amount in Sats, which you want to send to the node.\n',
link: 'transactions',
linkCaption: 'Transactions page'
}));
}
ngOnInit() {
this.helpTopics.push(new HelpTopic('Getting started', 'Funding your node is the first step to get started.\n' +
'Go to the "On-chain" page of the app:\n' +
'1. Generate a new address on the "Recieve" tab.\n'+
'2. Send funds to the address.\n' +
'3. Wait for the balance to be confirmed on-chain before proceeding further.\n' +
'3. Connecting with network peers and opening channels is next.\n' +
'<a href="http://localhost:3000/rtl/lnd/onchain">On-Chain page</a>'));
this.helpTopics.push(new HelpTopic('Connect with peers', 'Connect with network peers to open channels with them.\n' +
'Go to "Peer/Channels" page under the "Lightning" menu :\n' +
'1. Get the peer pubkey and host address in the pubkey@ip:port format.\n' +
'2. On the "Peers" enter the peer address and connect.\n' +
'3. Once the peer is connected, you can open channel with the peer.\n'+
'4. A variety of actions can be performed on the connected peers page for each peer:\n'+
' a. View Info - View the peer details.\n' +
' b. Open Channel - Open channel with the peer.\n' +
' c. Disconnect - Disconnect from the peer.\n' +
'<a href="http://localhost:3000/rtl/lnd/peerschannels">Peers/Channels page</a>'));
this.helpTopics.push(new HelpTopic('Opening Channels', 'Open channels with a connected network peer.\n' +
'Go to "Peer/Channels" page under the "Lightning" menu:\n' +
'1. On the "Channels" section, select the alias of the connected peer from the drop-down\n' +
'2. Specify the amount to commit to the channel and click on "Open Channel".\n' +
'3. There are a variety of options available while opening a channel. \n' +
' a. Private Channel - When this option is selected, a private channel is opened with the peer. \n' +
' b. Priority (advanced option) - Specify either Target confirmation Block or Fee in Sat/Byte. \n' +
' c. Spend Unconfirmd Output (advanced option) - Allow channels to be opened with unconfirmed UTXOs.\n' +
'4. Track the pending open channels under the "Pending" tab . \n' +
'5. Wait for the channel to be confirmed. Only a confimed channel can be used for payments or routing. \n' +
'<a href="http://localhost:3000/rtl/lnd/peerschannels">Peers/Channels page</a>'));
this.helpTopics.push(new HelpTopic('Channel Management', 'Channel maintenance and balance score.\n' +
'Go to "Peer/Channels" page under the "Lightning" menu:\n' +
'1. A variety of actions can be perfomed on the open channels under the "Open" tab, with the "Actions" button:\n' +
' a. View Info - View the channel details.\n' +
' b. View Remote Fee - View the fee policy on the channel of the remote peer.\n' +
' c. Update Fee Policy - Modify the fee policy on the channel.\n' +
' d. Close Channel - Close the channel.\n' +
'2. Balance Score is balancedness metric score for the channel:\n' +
' a. It helps measure how balanced the remote and local balance on a channel is.\n' +
' b. A perfectly balanced channel has a score of one, where a completely lopsided one has a score of zero.\n' +
' c. The formular for calculating the score is "1 - abs((local bal - remote bal)/total bal)".\n' +
'<a href="http://localhost:3000/rtl/lnd/peerschannels">Peers/Channels page</a>'));
this.helpTopics.push(new HelpTopic('Lightning Transactions - Payments', 'Sending Payments from your node.\n' +
'Go to "Transactions" page under the "Lightning" menu :\n' +
'Payments - Payments tab is for making payments via your node\n' +
' 1. Input a non-expired lightning invoice (Bolt11 format) in the "Payment request" field and click on "Send Payment" to send.\n' +
' 2. Advanced option # 1 - Specify a limit on the routing fee you are willing to pay for the payment.\n' +
' 3. Advanced option # 2 - Specify the outgoing channel through which you want the payment to go out.\n' +
'<a href="http://localhost:3000/rtl/lnd/transactions">Transactions page</a>'));
this.helpTopics.push(new HelpTopic('Lightning Transactions - Invoices', 'Receiving Payments on your node.\n' +
'Go to "Transactions" page under the "Lightning" menu :\n' +
'Invoices - Invoices tab is for receiving payments on your node.\n' +
' 1. Memo - Description you want to provide on the invoice.\n' +
' 2. Expiry - The time period, after which the invoice will be invalid.\n' +
' 3. Private Routing Hints - Generate an invoice with routing hints for private channels.\n' +
'<a href="http://localhost:3000/rtl/lnd/transactions">Transactions page</a>'));
this.helpTopics.push(new HelpTopic('Lightning Transactions - Query Route', 'Querying Payment Routes.\n' +
'Go to "Transactions" page under the "Lightning" menu :\n' +
'Query Routes - Query Routes tab is for querying a potential path to a node and a routing fee estimate for a payment amount.\n'+
' 1. Destination Pubkey - Pubkey of the node, you want to send the payment to.\n' +
' 2. Amount - Amount in Sats, which you want to send to the node.\n' +
'<a href="http://localhost:3000/rtl/lnd/transactions">Transactions page</a>'));
this.store.select('root')
.pipe(takeUntil(this.unSubs[0]))
.subscribe(rtlStore => {
this.selNode = rtlStore.selNode;
if(this.selNode.lnImplementation.toUpperCase() === 'CLT') {
this.LNPLink = '/cl/';
} else {
this.LNPLink = '/lnd/';
}
});
this.sessionService.watchSession()
.pipe(takeUntil(this.unSubs[1]))
.subscribe(session => {
this.flgLoggedIn = (session.token) ? true : false;
});
if (this.sessionService.getItem('token')) { this.flgLoggedIn = true; }
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -28,8 +28,7 @@ export class HorizontalNavigationComponent implements OnInit, OnDestroy {
public information: GetInfoRoot = {};
private unSubs = [new Subject(), new Subject(), new Subject()];
constructor(private sessionService: SessionService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects) {
}
constructor(private sessionService: SessionService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects) {}
ngOnInit() {
this.store.select('root')

@ -72,3 +72,7 @@ export interface SelNodeChild {
selCurrencyUnit?: string;
currencyUnits?: string[];
}
export class HelpTopic {
constructor(public help: {question: string, answer: string, link?: string, linkCaption?: string}) { }
}

@ -65,8 +65,12 @@ export interface BalanceCL {
export interface LocalRemoteBalanceCL {
localBalance: number;
remoteBalance: number;
pendingBalance?: number;
inactiveBalance?: number;
btc_localBalance?: number;
btc_remoteBalance?: number;
btc_pendingBalance?: number;
btc_inactiveBalance?: number;
}
export interface PeerCL {

@ -764,7 +764,7 @@ export class PeerLookupCL implements Action {
export class ChannelLookupCL implements Action {
readonly type = CHANNEL_LOOKUP_CL;
constructor(public payload: string) {} // payload = channel_short_id
constructor(public payload: {shortChannelID: string, showError: boolean}) {}
}
export class InvoiceLookupCL implements Action {

Loading…
Cancel
Save