Release 0.8.3 (#396)

Channel Rebalance and UI alignement fix #384 & 385
Force close inactive channel with priority disabled
Replace CLT forwarding history short channel id with alias & show node alias on welcome message.
Showing pending htlc length in channel info
This commit is contained in:
ShahanaFarooqui 2020-08-02 12:05:40 -04:00 committed by GitHub
parent 2f5dbd9ae2
commit da24d3fcc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 136 additions and 97 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -15,5 +15,5 @@
<link rel="stylesheet" href="styles.7f0a84d9b012559f3600.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.5e033f239370b1b56229.js" defer></script><script src="polyfills-es5.2ac0d98b22574ae745b1.js" nomodule defer></script><script src="polyfills.5ae721a6ae5ab597a53d.js" defer></script><script src="main.6a3e5304c0ea3345640b.js" defer></script></body>
<script src="runtime.1f2c455b4c4cb8842ded.js" defer></script><script src="polyfills-es5.2ac0d98b22574ae745b1.js" nomodule defer></script><script src="polyfills.5ae721a6ae5ab597a53d.js" defer></script><script src="main.c7f99ef7fef5590a6077.js" defer></script></body>
</html>

File diff suppressed because one or more lines are too long

View file

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

2
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "rtl",
"version": "0.8.2-beta",
"version": "0.8.3-beta",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "rtl",
"version": "0.8.2-beta",
"version": "0.8.3-beta",
"license": "MIT",
"scripts": {
"ng": "ng",

View file

@ -12,8 +12,8 @@
<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>
<div fxLayout="column" fxFlex="3" fxLayoutAlign="end stretch"><mat-divider class="dashboard-divider"></mat-divider></div>
<div fxLayout="column" fxFlex.gt-sm="88" fxFlex="84" fxLayoutAlign="start start" class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" class="w-100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock">
<div class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock">
<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">
@ -30,7 +30,7 @@
</div>
</div>
<ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="10" fxLayoutAlign="space-between center" class="w-100 mt-1">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1">
No channels available.
<button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div>

View file

@ -20,7 +20,7 @@
</div>
</div>
<ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="10" fxLayoutAlign="space-between center" class="w-100 mt-1">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between center" class="mt-1">
No channels available.
<button *ngIf="direction === 'Out'" mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div>

View file

@ -1,7 +1,7 @@
<div fxLayout="column" *ngIf="selNode.userPersona === userPersonaEnum.OPERATOR; else merchantDashboard">
<div fxLayout="row" fxLayoutAlign="start end" class="padding-gap-x page-title-container mb-0">
<fa-icon [icon]="!flgLoading[0] ? faSmile : faFrown" class="page-title-img mr-1"></fa-icon>
<span class="page-title">{{!flgLoading[0] ? 'Welcome! Your node is up and running.' : 'Error! Please check the server connection.'}}</span>
<span class="page-title">{{!flgLoading[0] ? 'Welcome ' + information.alias + '! Your node is up and running.' : 'Error! Please check the server connection.'}}</span>
</div>
<mat-grid-list cols="10" [rowHeight]="operatorCardHeight">
<mat-grid-tile *ngFor="let card of operatorCards" [colspan]="card.cols" [rowspan]="card.rows">
@ -36,7 +36,7 @@
<ng-template #merchantDashboard>
<div fxLayout="row" fxLayoutAlign="start end" class="padding-gap-x page-title-container mb-0">
<fa-icon [icon]="faSmile" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Welcome! Your node is up and running.</span>
<span class="page-title">Welcome {{information.alias}}! Your node is up and running.</span>
</div>
<mat-grid-list cols="6" [rowHeight]="merchantCardHeight">
<mat-grid-tile *ngFor="let card of merchantCards" [colspan]="card.cols" [rowspan]="card.rows">

View file

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

View file

@ -57,8 +57,8 @@ export class CLFailedTransactionsComponent implements OnInit, OnChanges {
[{key: 'payment_hash', value: selFEvent.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING}],
[{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: '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_channel', value: selFEvent.in_channel_alias ? selFEvent.in_channel_alias : selFEvent.in_channel, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING},
{key: 'out_channel', value: selFEvent.out_channel_alias ? selFEvent.out_channel_alias : selFEvent.out_channel, title: 'Outbound Channel', width: 50, type: DataTypeEnum.STRING}],
[{key: 'status', value: (selFEvent.status=== 'settled' ? 'Settled' : 'Unsettled'), title: 'Status', width: 50, type: DataTypeEnum.STRING},
{key: 'fee', value: selFEvent.fee, title: 'Fee (mSats)', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'in_msatoshi', value: selFEvent.in_msatoshi, title: 'In (mSats)', width: 50, type: DataTypeEnum.NUMBER},

View file

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

View file

@ -57,8 +57,8 @@ export class CLForwardingHistoryComponent implements OnInit, OnChanges {
[{key: 'payment_hash', value: selFEvent.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING}],
[{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: '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_channel', value: selFEvent.in_channel_alias ? selFEvent.in_channel_alias : selFEvent.in_channel, title: 'Inbound Channel', width: 50, type: DataTypeEnum.STRING},
{key: 'out_channel', value: selFEvent.out_channel_alias ? selFEvent.out_channel_alias : selFEvent.out_channel, title: 'Outbound Channel', width: 50, type: DataTypeEnum.STRING}],
[{key: 'status', value: (selFEvent.status === 'settled' ? 'Settled' : 'Failed'), title: 'Status', width: 50, type: DataTypeEnum.STRING},
{key: 'fee', value: selFEvent.fee, title: 'Fee (mSats)', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'in_msatoshi', value: selFEvent.in_msatoshi, title: 'In (mSats)', width: 50, type: DataTypeEnum.NUMBER},

View file

@ -39,10 +39,10 @@ export class CLRoutingComponent implements OnInit, OnDestroy {
ngOnInit() {
this.onEventsFetch();
// this.actions$.pipe(takeUntil(this.unSubs[1]), filter((action) => action.type === RTLActions.RESET_STORE))
// .subscribe((resetClStore: RTLActions.ResetCLStore) => {
// this.onEventsFetch();
// });
this.actions$.pipe(takeUntil(this.unSubs[1]), filter((action) => action.type === CLActions.SET_CHANNELS_CL))
.subscribe((action: CLActions.SetChannels) => {
this.onEventsFetch();
});
this.store.select('cl')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
@ -56,6 +56,8 @@ export class CLRoutingComponent implements OnInit, OnDestroy {
});
if (rtlStore.forwardingHistory && rtlStore.forwardingHistory.forwarding_events) {
this.lastOffsetIndex = rtlStore.forwardingHistory.last_offset_index;
this.successfulData = [];
this.failedData = [];
rtlStore.forwardingHistory.forwarding_events.forEach(event => {
if (event.status === 'settled') {
this.successfulData.push(event);
@ -78,18 +80,9 @@ export class CLRoutingComponent implements OnInit, OnDestroy {
}
onEventsFetch() {
if (!this.endDate) {
this.endDate = new Date();
}
if (!this.startDate) {
this.startDate = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate() - 30);
}
this.store.dispatch(new CLActions.GetForwardingHistory(
// {
// end_time: Math.round(this.endDate.getTime() / 1000).toString(),
// start_time: Math.round(this.startDate.getTime() / 1000).toString()
// }
));
if (!this.endDate) { this.endDate = new Date(); }
if (!this.startDate) { this.startDate = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate() - 30); }
this.store.dispatch(new CLActions.GetForwardingHistory());
}
resetData() {

View file

@ -37,7 +37,8 @@ export class CLEffects implements OnDestroy {
this.store.select('cl')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
if(rtlStore.initialAPIResponseCounter > 7) {
if(rtlStore.initialAPIResponseStatus[0] === 'INCOMPLETE' && rtlStore.initialAPIResponseStatus.length > 7) {
rtlStore.initialAPIResponseStatus[0] = 'COMPLETE';
this.store.dispatch(new RTLActions.CloseSpinner());
}
});
@ -573,10 +574,6 @@ export class CLEffects implements OnDestroy {
ofType(CLActions.GET_FORWARDING_HISTORY_CL),
mergeMap((action: CLActions.GetForwardingHistory) => {
this.store.dispatch(new CLActions.ClearEffectError('GetForwardingHistory'));
// const queryHeaders: SwitchReq = {
// num_max_events: action.payload.num_max_events, index_offset: action.payload.index_offset, end_time: action.payload.end_time, start_time: action.payload.start_time
// };
// return this.httpClient.post(this.CHILD_API_URL + environment.SWITCH_API, queryHeaders)
return this.httpClient.get(this.CHILD_API_URL + environment.CHANNELS_API + '/listForwards')
.pipe(
map((fhRes: any) => {
@ -725,7 +722,6 @@ export class CLEffects implements OnDestroy {
this.store.dispatch(new CLActions.FetchFeeRates('perkw'));
this.store.dispatch(new CLActions.FetchFeeRates('perkb'));
this.store.dispatch(new CLActions.FetchPeers());
this.store.dispatch(new CLActions.GetForwardingHistory());
let newRoute = this.location.path();
if(newRoute.includes('/lnd/')) {
newRoute = newRoute.replace('/lnd/', '/cl/');

View file

@ -6,7 +6,7 @@ import * as CLActions from '../store/cl.actions';
import * as RTLActions from '../../store/rtl.actions';
export interface CLState {
initialAPIResponseCounter: number;
initialAPIResponseStatus: String[];
effectErrors: ErrorPayload[];
nodeSettings: SelNodeChild;
information: GetInfo;
@ -24,7 +24,7 @@ export interface CLState {
}
export const initCLState: CLState = {
initialAPIResponseCounter: 0,
initialAPIResponseStatus: ['INCOMPLETE'], //[0] for All Data Status
effectErrors: [],
nodeSettings: { userPersona: UserPersonaEnum.OPERATOR, selCurrencyUnit: 'USD', fiatConversion: false, channelBackupPath: '', currencyUnits: [] },
information: {},
@ -42,6 +42,8 @@ export const initCLState: CLState = {
}
export function CLReducer(state = initCLState, action: CLActions.CLActions) {
let newAPIStatus = state.initialAPIResponseStatus;
switch (action.type) {
case CLActions.CLEAR_EFFECT_ERROR_CL:
const clearedEffectErrors = [...state.effectErrors];
@ -76,22 +78,25 @@ export function CLReducer(state = initCLState, action: CLActions.CLActions) {
information: action.payload
};
case CLActions.SET_FEES_CL:
newAPIStatus = [...state.initialAPIResponseStatus, 'FEES'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
fees: action.payload
};
case CLActions.SET_FEE_RATES_CL:
if (action.payload.perkb) {
newAPIStatus = [...state.initialAPIResponseStatus, 'FEERATEKB'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
feeRatesPerKB: action.payload
};
} else if (action.payload.perkw) {
newAPIStatus = [...state.initialAPIResponseStatus, 'FEERATEKW'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
feeRatesPerKW: action.payload
};
} else {
@ -100,21 +105,24 @@ export function CLReducer(state = initCLState, action: CLActions.CLActions) {
}
}
case CLActions.SET_BALANCE_CL:
newAPIStatus = [...state.initialAPIResponseStatus, 'BALANCE'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
balance: action.payload
};
case CLActions.SET_LOCAL_REMOTE_BALANCE_CL:
newAPIStatus = [...state.initialAPIResponseStatus, 'CHANNELBALANCE'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
localRemoteBalance: action.payload
};
case CLActions.SET_PEERS_CL:
newAPIStatus = [...state.initialAPIResponseStatus, 'PEERS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
peers: action.payload
};
case CLActions.ADD_PEER_CL:
@ -135,9 +143,10 @@ export function CLReducer(state = initCLState, action: CLActions.CLActions) {
peers: modifiedPeers
};
case CLActions.SET_CHANNELS_CL:
newAPIStatus = [...state.initialAPIResponseStatus, 'CHANNELS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
allChannels: action.payload,
};
case CLActions.REMOVE_CHANNEL_CL:
@ -158,9 +167,28 @@ export function CLReducer(state = initCLState, action: CLActions.CLActions) {
payments: action.payload
};
case CLActions.SET_FORWARDING_HISTORY_CL:
if (action.payload.forwarding_events) {
const storedChannels = [...state.allChannels];
action.payload.forwarding_events.forEach(event => {
if (storedChannels && storedChannels.length > 0) {
for (let idx = 0; idx < storedChannels.length; idx++) {
if (storedChannels[idx].short_channel_id === event.in_channel) {
event.in_channel_alias = storedChannels[idx].alias ? storedChannels[idx].alias : event.in_channel;
if (event.out_channel_alias) { return; }
}
if (storedChannels[idx].short_channel_id.toString() === event.out_channel) {
event.out_channel_alias = storedChannels[idx].alias ? storedChannels[idx].alias : event.out_channel;
if (event.in_channel_alias) { return; }
}
}
}
});
} else {
action.payload = {};
}
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
forwardingHistory: action.payload
};
case CLActions.ADD_INVOICE_CL:

View file

@ -55,12 +55,12 @@
<ng-container matColumnDef="msatoshi_sent">
<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/1000 | number}}</span></td>
fxLayoutAlign="end center">{{payment?.msatoshi_sent/1000 | number:'1.0-0'}}</span></td>
</ng-container>
<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>
fxLayoutAlign="end center">{{payment?.msatoshi/1000 | number:'1.0-0'}}</span></td>
</ng-container>
<ng-container matColumnDef="payment_preimage">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Pre Image</th>

View file

@ -12,8 +12,8 @@
<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>
<div fxLayout="column" fxFlex="3" fxLayoutAlign="end stretch"><mat-divider class="dashboard-divider"></mat-divider></div>
<div fxLayout="column" fxFlex.gt-sm="88" fxFlex="84" fxLayoutAlign="start start" class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" class="w-100" *ngIf="allChannels && allChannels?.length > 0; else noChannelBlock">
<div class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" *ngIf="allChannels && allChannels?.length > 0; else noChannelBlock">
<div *ngFor="let channel of allChannels" class="mt-2">
<span class="dashboard-capacity-header" matTooltip="{{channel.alias || channel.shortChannelId}}" matTooltipDisabled="{{(channel.alias || channel.shortChannelId).length < 26}}">{{(channel?.alias || channel?.shortChannelId) | slice:0:24}}{{(channel?.alias || channel?.shortChannelId).length > 25 ? '...' : ''}}</span>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
@ -30,7 +30,7 @@
</div>
</div>
<ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="10" fxLayoutAlign="space-between center" class="w-100 mt-1">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1">
No channels available.
<button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div>

View file

@ -20,7 +20,7 @@
</div>
</div>
<ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="10" fxLayoutAlign="space-between center" class="w-100 mt-1">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between center" class="mt-1">
No channels available.
<button *ngIf="direction === 'Out'" mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div>

View file

@ -2,7 +2,7 @@
<div fxLayout="row" fxLayoutAlign="start end" class="padding-gap-x page-title-container mb-0">
<fa-icon [icon]="!flgLoading[0] ? faSmile : faFrown" class="page-title-img mr-1"></fa-icon>
<span
class="page-title">{{!flgLoading[0] ? 'Welcome! Your node is up and running.' : 'Error! Please check the server connection.'}}</span>
class="page-title">{{!flgLoading[0] ? 'Welcome ' + information.alias + '! Your node is up and running.' : 'Error! Please check the server connection.'}}</span>
</div>
<mat-grid-list cols="10" [rowHeight]="operatorCardHeight">
<mat-grid-tile *ngFor="let card of operatorCards" [colspan]="card.cols" [rowspan]="card.rows">
@ -46,7 +46,7 @@
<ng-template #merchantDashboard>
<div fxLayout="row" fxLayoutAlign="start end" class="padding-gap-x page-title-container mb-0">
<fa-icon [icon]="faSmile" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Welcome! Your node is up and running.</span>
<span class="page-title">Welcome {{information.alias}}! Your node is up and running.</span>
</div>
<mat-grid-list cols="6" [rowHeight]="merchantCardHeight">
<mat-grid-tile *ngFor="let card of merchantCards" [colspan]="card.cols" [rowspan]="card.rows">

View file

@ -36,7 +36,8 @@ export class ECLEffects implements OnDestroy {
this.store.select('ecl')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
if(rtlStore.initialAPIResponseCounter > 4) {
if(rtlStore.initialAPIResponseStatus[0] === 'INCOMPLETE' && rtlStore.initialAPIResponseStatus.length > 5) {
rtlStore.initialAPIResponseStatus[0] = 'COMPLETE';
this.store.dispatch(new RTLActions.CloseSpinner());
}
});

View file

@ -5,7 +5,7 @@ import { UserPersonaEnum } from '../../shared/services/consts-enums-functions';
import * as ECLActions from './ecl.actions';
export interface ECLState {
initialAPIResponseCounter: number;
initialAPIResponseStatus: String[];
effectErrors: ErrorPayload[];
nodeSettings: SelNodeChild;
information: GetInfo;
@ -24,7 +24,7 @@ export interface ECLState {
}
export const initECLState: ECLState = {
initialAPIResponseCounter: 0,
initialAPIResponseStatus: ['INCOMPLETE'], //[0] for All Data Status
effectErrors: [],
nodeSettings: { userPersona: UserPersonaEnum.OPERATOR, selCurrencyUnit: 'USD', fiatConversion: false, channelBackupPath: '', currencyUnits: [] },
information: {},
@ -43,6 +43,8 @@ export const initECLState: ECLState = {
}
export function ECLReducer(state = initECLState, action: ECLActions.ECLActions) {
let newAPIStatus = state.initialAPIResponseStatus;
switch (action.type) {
case ECLActions.CLEAR_EFFECT_ERROR_ECL:
const clearedEffectErrors = [...state.effectErrors];
@ -77,9 +79,10 @@ export function ECLReducer(state = initECLState, action: ECLActions.ECLActions)
information: action.payload
};
case ECLActions.SET_FEES_ECL:
newAPIStatus = [...state.initialAPIResponseStatus, 'FEES'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
fees: action.payload
};
case ECLActions.SET_ACTIVE_CHANNELS_ECL:
@ -98,9 +101,10 @@ export function ECLReducer(state = initECLState, action: ECLActions.ECLActions)
inactiveChannels: action.payload,
};
case ECLActions.SET_CHANNELS_STATUS_ECL:
newAPIStatus = [...state.initialAPIResponseStatus, 'CHANNELS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
channelsStatus: action.payload,
};
case ECLActions.SET_CHANNEL_STATS_ECL:
@ -109,9 +113,10 @@ export function ECLReducer(state = initECLState, action: ECLActions.ECLActions)
channelStats: action.payload,
};
case ECLActions.SET_ONCHAIN_BALANCE_ECL:
newAPIStatus = [...state.initialAPIResponseStatus, 'ONCHAINBALANCE'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
onchainBalance: action.payload
};
case ECLActions.SET_LIGHTNING_BALANCE_ECL:
@ -120,9 +125,10 @@ export function ECLReducer(state = initECLState, action: ECLActions.ECLActions)
lightningBalance: action.payload
};
case ECLActions.SET_PEERS_ECL:
newAPIStatus = [...state.initialAPIResponseStatus, 'PEERS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
peers: action.payload
};
case ECLActions.REMOVE_PEER_ECL:
@ -150,9 +156,10 @@ export function ECLReducer(state = initECLState, action: ECLActions.ECLActions)
activeChannels: modifiedChannels
};
case ECLActions.SET_PAYMENTS_ECL:
newAPIStatus = [...state.initialAPIResponseStatus, 'PAYMENTS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
payments: action.payload
};
case ECLActions.SET_TRANSACTIONS_ECL:

View file

@ -12,8 +12,8 @@
<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>
<div fxLayout="column" fxFlex="3" fxLayoutAlign="end stretch"><mat-divider class="dashboard-divider"></mat-divider></div>
<div fxLayout="column" fxFlex.gt-sm="88" fxFlex="84" fxLayoutAlign="start start" class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" class="w-100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock">
<div class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock">
<div *ngFor="let channel of allChannels" class="mt-2">
<span class="dashboard-capacity-header" matTooltip="{{channel.remote_alias || channel.remote_pubkey}}" matTooltipDisabled="{{(channel.remote_alias || channel.remote_pubkey).length < 26}}">{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}</span>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
@ -30,7 +30,7 @@
</div>
</div>
<ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="10" fxLayoutAlign="space-between center" class="w-100 mt-1">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" class="mt-1">
No channels available.
<button mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div>

View file

@ -21,7 +21,7 @@
</div>
</div>
<ng-template #noChannelBlock>
<div fxLayout="row" fxFlex="10" fxLayoutAlign="space-between center" class="w-100 mt-1">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between center" class="mt-1">
No channels available.
<button *ngIf="direction === 'Out'" mat-stroked-button color="primary" (click)="goToChannels()" tabindex="1">Open Channel</button>
</div>

View file

@ -1,7 +1,7 @@
<div fxLayout="column" *ngIf="selNode.userPersona === userPersonaEnum.OPERATOR; else merchantDashboard">
<div fxLayout="row" fxLayoutAlign="start end" class="padding-gap-x page-title-container mb-0">
<fa-icon [icon]="!flgLoading[0] ? faSmile : faFrown" class="page-title-img mr-1"></fa-icon>
<span class="page-title">{{!flgLoading[0] ? 'Welcome! Your node is up and running.' : 'Error! Please check the server connection.'}}</span>
<span class="page-title">{{!flgLoading[0] ? 'Welcome ' + information.alias + '! Your node is up and running.' : 'Error! Please check the server connection.'}}</span>
</div>
<mat-grid-list cols="10" [rowHeight]="operatorCardHeight" [ngClass]="{'mb-6': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}">
<mat-grid-tile *ngFor="let card of operatorCards" [colspan]="card.cols" [rowspan]="card.rows">
@ -36,7 +36,7 @@
<ng-template #merchantDashboard>
<div fxLayout="row" fxLayoutAlign="start end" class="padding-gap-x page-title-container mb-0">
<fa-icon [icon]="faSmile" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Welcome! Your node is up and running.</span>
<span class="page-title">Welcome {{information.alias}}! Your node is up and running.</span>
</div>
<mat-grid-list cols="6" [rowHeight]="merchantCardHeight" [ngClass]="{'mb-6': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}">
<mat-grid-tile *ngFor="let card of merchantCards" [colspan]="card.cols" [rowspan]="card.rows">

View file

@ -126,7 +126,7 @@
</div>
<div fxFlex="25">
<h4 fxLayoutAlign="start" class="font-bold-500">Pending HTLCs</h4>
<span class="overflow-wrap foreground-secondary-text">{{channel.pending_htlcs | number}}</span>
<span class="overflow-wrap foreground-secondary-text">{{channel?.pending_htlcs?.length | number}}</span>
</div>
</div>
<mat-divider [inset]="true" class="my-1"></mat-divider>

View file

@ -30,10 +30,11 @@
{{activeChannel.remote_alias || activeChannel.chan_id}}
</mat-option>
</mat-select>
<mat-error *ngIf="inputFormGroup.controls.selRebalancePeer.errors?.required">Peer is required.</mat-error>
</mat-form-field>
</div>
<div class="mt-2" fxLayout="row" fxLayoutAlign="start center" fxFlex="100">
<button mat-stroked-button color="primary" tabindex="3" type="button" (click)="onEstimateFee()">Estimate Fee</button>
<button mat-stroked-button color="primary" tabindex="3" type="submit" (click)="onEstimateFee()">Estimate Fee</button>
</div>
</form>
</mat-step>
@ -68,7 +69,7 @@
</div>
</div>
<div class="mt-2" fxLayout="row" fxLayoutAlign="start center" fxFlex="100">
<button mat-stroked-button color="primary" tabindex="8" type="button" (click)="onRebalance()">Rebalance</button>
<button mat-stroked-button color="primary" tabindex="8" type="submit" (click)="onRebalance()">Rebalance</button>
</div>
</form>
</mat-step>

View file

@ -153,7 +153,7 @@ export class ChannelRebalanceComponent implements OnInit, OnDestroy {
}
onRebalance() {
if (!this.inputFormGroup.controls.rebalanceAmount.value || this.inputFormGroup.controls.rebalanceAmount.value <= 0 || this.inputFormGroup.controls.rebalanceAmount.value > +this.selChannel.local_balance || this.feeFormGroup.controls.feeLimit.value < 0 || !this.inputFormGroup.controls.selRebalancePeer.value.remote_pubkey) { return true; }
if (!this.inputFormGroup.controls.rebalanceAmount.value || this.inputFormGroup.controls.rebalanceAmount.value <= 0 || this.inputFormGroup.controls.rebalanceAmount.value > +this.selChannel.local_balance || !this.feeFormGroup.controls.feeLimit.value || this.feeFormGroup.controls.feeLimit.value < 0 || !this.inputFormGroup.controls.selRebalancePeer.value.remote_pubkey) { return true; }
this.feeFormGroup.controls.hiddenFeeLimit.setValue(this.feeFormGroup.controls.feeLimit.value);
this.stepper.next();
this.flgEditable = false;

View file

@ -12,7 +12,7 @@
<p fxLayoutAlign="start center" class="pb-1 word-break">Closing channel: {{channelToClose.channel_point}}</p>
<div fxLayoutAlign="space-between center">
<mat-form-field fxFlex.gt-sm="48">
<mat-select [(value)]="selTransType" tabindex="1">
<mat-select [(value)]="selTransType" tabindex="1" [disabled]="!channelToClose.active">
<mat-option *ngFor="let transType of transTypes" [value]="transType.id">
{{transType.name}}
</mat-option>

View file

@ -42,7 +42,8 @@ export class LNDEffects implements OnDestroy {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
if(rtlStore.initialAPIResponseCounter > 8) {
if(rtlStore.initialAPIResponseStatus[0] === 'INCOMPLETE' && rtlStore.initialAPIResponseStatus.length > 8) {
rtlStore.initialAPIResponseStatus[0] = 'COMPLETE';
this.store.dispatch(new RTLActions.CloseSpinner());
}
});

View file

@ -5,10 +5,11 @@ import {
PendingChannels, ClosedChannel, Transaction, SwitchRes, PendingChannelsGroup, SwapStatus
} from '../../shared/models/lndModels';
import { UserPersonaEnum } from '../../shared/services/consts-enums-functions';
import * as LNDActions from './lnd.actions';
export interface LNDState {
initialAPIResponseCounter: number;
initialAPIResponseStatus: String[];
effectErrors: ErrorPayload[];
nodeSettings: SelNodeChild;
information: GetInfo;
@ -36,7 +37,7 @@ export interface LNDState {
}
export const initLNDState: LNDState = {
initialAPIResponseCounter: 0,
initialAPIResponseStatus: ['INCOMPLETE'], //[0] for All Data Status
effectErrors: [],
nodeSettings: { userPersona: UserPersonaEnum.OPERATOR, fiatConversion: false, channelBackupPath: '', currencyUnits: [], selCurrencyUnit: '', lnImplementation: '', swapServerUrl: '' },
information: {},
@ -64,6 +65,8 @@ export const initLNDState: LNDState = {
}
export function LNDReducer(state = initLNDState, action: LNDActions.LNDActions) {
let newAPIStatus = state.initialAPIResponseStatus;
switch (action.type) {
case LNDActions.CLEAR_EFFECT_ERROR_LND:
const clearedEffectErrors = [...state.effectErrors];
@ -98,9 +101,10 @@ export function LNDReducer(state = initLNDState, action: LNDActions.LNDActions)
information: action.payload
};
case LNDActions.SET_PEERS_LND:
newAPIStatus = [...state.initialAPIResponseStatus, 'PEERS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
peers: action.payload
};
case LNDActions.REMOVE_PEER_LND:
@ -123,21 +127,24 @@ export function LNDReducer(state = initLNDState, action: LNDActions.LNDActions)
invoices: newInvoices
};
case LNDActions.SET_FEES_LND:
newAPIStatus = [...state.initialAPIResponseStatus, 'FEES'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
fees: action.payload
};
case LNDActions.SET_CLOSED_CHANNELS_LND:
newAPIStatus = [...state.initialAPIResponseStatus, 'CLOSEDCHANNELS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
closedChannels: action.payload,
};
case LNDActions.SET_PENDING_CHANNELS_LND:
newAPIStatus = [...state.initialAPIResponseStatus, 'PENDINGCHANNELS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
pendingChannels: action.payload.channels,
numberOfPendingChannels: action.payload.pendingChannels,
};
@ -165,9 +172,10 @@ export function LNDReducer(state = initLNDState, action: LNDActions.LNDActions)
}
});
}
newAPIStatus = [...state.initialAPIResponseStatus, 'ALLCHANNELS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
allChannels: action.payload,
numberOfActiveChannels: activeChannels,
numberOfInactiveChannels: inactiveChannels,
@ -190,9 +198,10 @@ export function LNDReducer(state = initLNDState, action: LNDActions.LNDActions)
};
case LNDActions.SET_BALANCE_LND:
if (action.payload.target === 'channels') {
newAPIStatus = [...state.initialAPIResponseStatus,'BALANCE'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
channelBalance: action.payload.balance
};
} else {
@ -204,13 +213,13 @@ export function LNDReducer(state = initLNDState, action: LNDActions.LNDActions)
case LNDActions.SET_NETWORK_LND:
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
networkInfo: action.payload
};
case LNDActions.SET_INVOICES_LND:
newAPIStatus = [...state.initialAPIResponseStatus,'INVOICES'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
invoices: action.payload
};
case LNDActions.SET_TOTAL_INVOICES_LND:
@ -224,16 +233,17 @@ export function LNDReducer(state = initLNDState, action: LNDActions.LNDActions)
transactions: action.payload
};
case LNDActions.SET_PAYMENTS_LND:
newAPIStatus = [...state.initialAPIResponseStatus, 'PAYMENTS'];
return {
...state,
initialAPIResponseCounter: state.initialAPIResponseCounter + 1,
initialAPIResponseStatus: newAPIStatus,
payments: action.payload
};
case LNDActions.SET_FORWARDING_HISTORY_LND:
if (action.payload.forwarding_events) {
const storedChannels = [...state.allChannels, ...state.closedChannels];
action.payload.forwarding_events.forEach(event => {
if (storedChannels) {
if (storedChannels && storedChannels.length > 0) {
for (let idx = 0; idx < storedChannels.length; idx++) {
if (storedChannels[idx].chan_id.toString() === event.chan_id_in) {
event.alias_in = storedChannels[idx].remote_alias ? storedChannels[idx].remote_alias : event.chan_id_in;

View file

@ -36,8 +36,8 @@ export class LightningInvoicesComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
faHistory = faHistory;
public selNode: SelNodeChild = {};
public newlyAddedInvoiceMemo = '';
public newlyAddedInvoiceValue = 0;
public newlyAddedInvoiceMemo = null;
public newlyAddedInvoiceValue = null;
public flgAnimate = true;
public memo = '';
public expiry: number;

View file

@ -158,6 +158,8 @@ export interface ForwardingEvent {
payment_hash?: string;
in_channel?: string;
out_channel?: string;
in_channel_alias?: string;
out_channel_alias?: string;
in_msatoshi?: number;
in_msat?: string;
out_msatoshi?: number;

View file

@ -1 +1 @@
export const VERSION = '0.8.2-beta';
export const VERSION = '0.8.3-beta';