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
pull/397/head^2
ShahanaFarooqui 4 years ago committed by GitHub
parent 2f5dbd9ae2
commit da24d3fcc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

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

@ -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

@ -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

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

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

@ -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>

@ -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>

@ -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">

@ -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>

@ -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},

@ -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>

@ -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},

@ -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() {

@ -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/');

@ -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:

@ -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>

@ -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>

@ -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>

@ -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">

@ -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());
}
});

@ -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:

@ -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>

@ -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>

@ -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">

@ -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>

@ -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>

@ -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;

@ -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>

@ -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());
}
});

@ -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;

@ -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;

@ -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;

@ -1 +1 @@
export const VERSION = '0.8.2-beta';
export const VERSION = '0.8.3-beta';
Loading…
Cancel
Save