mirror of
https://github.com/Ride-The-Lightning/RTL.git
synced 2025-02-22 14:22:48 +01:00
Channel closing with pending htlc & inactive without priority #393 & #410
This commit is contained in:
parent
18ec1b70fe
commit
4da3b66bc7
12 changed files with 111 additions and 40 deletions
File diff suppressed because one or more lines are too long
|
@ -12,8 +12,8 @@
|
|||
<link rel="mask-icon" href="assets/images/favicon-light/safari-pinned-tab.svg" color="#5bbad5">
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="stylesheet" href="styles.63dd7929168e9fd14a1a.css"></head>
|
||||
<link rel="stylesheet" href="styles.1268069d095d5cf8e257.css"></head>
|
||||
<body>
|
||||
<rtl-app></rtl-app>
|
||||
<script src="runtime.2641b91157c23d9a9741.js" defer></script><script src="polyfills-es5.2ac0d98b22574ae745b1.js" nomodule defer></script><script src="polyfills.5ae721a6ae5ab597a53d.js" defer></script><script src="main.bac9de7c65f61812af23.js" defer></script></body>
|
||||
<script src="runtime.1cfb7a3d5c7630696d04.js" defer></script><script src="polyfills-es5.2ac0d98b22574ae745b1.js" nomodule defer></script><script src="polyfills.5ae721a6ae5ab597a53d.js" defer></script><script src="main.bac9de7c65f61812af23.js" defer></script></body>
|
||||
</html>
|
||||
|
|
|
@ -1 +1 @@
|
|||
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],f=r[2],p=0,d=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&d.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);d.length;)d.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"9bb271dd8dffd2d994a5",6:"02d8d1e879c0be336222",7:"4a00e92294df28ac9ca1",8:"98795e7ab86361a07d2b"}[e]+".js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([]);
|
||||
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],f=r[2],p=0,d=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&d.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);d.length;)d.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"9bb271dd8dffd2d994a5",6:"02d8d1e879c0be336222",7:"4a00e92294df28ac9ca1",8:"cbebc1d46c4bfbda8693"}[e]+".js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([]);
|
5
angular/styles.1268069d095d5cf8e257.css
Normal file
5
angular/styles.1268069d095d5cf8e257.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -204,6 +204,9 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
onChannelClose(channelToClose: Channel) {
|
||||
if (channelToClose.active) {
|
||||
this.store.dispatch(new LNDActions.FetchAllChannels()); //To get latest pending htlc status
|
||||
}
|
||||
this.store.dispatch(new RTLActions.OpenAlert({width: '70%', data: {
|
||||
channel: channelToClose,
|
||||
component: CloseChannelComponent
|
||||
|
|
|
@ -10,32 +10,42 @@
|
|||
<form fxLayout="column">
|
||||
<div fxLayout="column" class="bordered-box my-2 p-2">
|
||||
<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" [disabled]="!channelToClose.active">
|
||||
<mat-option *ngFor="let transType of transTypes" [value]="transType.id">
|
||||
{{transType.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="48" *ngIf="selTransType=='0'">
|
||||
<input matInput placeholder="Default" disabled>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex.gt-sm="48" fxLayoutAlign="start end" *ngIf="selTransType=='1'">
|
||||
<input matInput [(ngModel)]="blocks" placeholder="Number of Blocks" type="number" name="blocks" step="1"
|
||||
min="0" required tabindex="2" #blcks="ngModel">
|
||||
<mat-error *ngIf="!blocks">Number of blocks is required.</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex.gt-sm="48" fxLayoutAlign="start end" *ngIf="selTransType=='2'">
|
||||
<input matInput [(ngModel)]="fees" placeholder="Fees (Sats/Byte)"
|
||||
type="number" name="fees" step="1" min="0" required tabindex="3" #fee="ngModel">
|
||||
<mat-error *ngIf="!fees">Fees is required.</mat-error>
|
||||
</mat-form-field>
|
||||
<div *ngIf="flgPendingHtlcs" fxLayoutAlign="start center">
|
||||
<p fxFlex="100" fxLayoutAlign="start center" class="color-warn"><mat-icon class="mr-1 icon-small">close</mat-icon>{{errorMsg}}</p>
|
||||
</div>
|
||||
<div *ngIf="!flgPendingHtlcs" fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
|
||||
<div *ngIf="!channelToClose.active" fxFlex="100" class="alert alert-info">
|
||||
<fa-icon [icon]="faInfoCircle" class="mr-1 alert-icon"></fa-icon>
|
||||
<span>Force closing an inactive channel uses a pre-defined fee.</span>
|
||||
</div>
|
||||
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between center">
|
||||
<mat-form-field fxFlex.gt-sm="48">
|
||||
<mat-select [(value)]="selTransType" tabindex="1" [disabled]="!channelToClose.active">
|
||||
<mat-option *ngFor="let transType of transTypes" [value]="transType.id">
|
||||
{{transType.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="48" *ngIf="selTransType=='0'">
|
||||
<input matInput placeholder="Default" disabled>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex.gt-sm="48" fxLayoutAlign="start end" *ngIf="selTransType=='1'">
|
||||
<input matInput [(ngModel)]="blocks" placeholder="Number of Blocks" type="number" name="blocks" step="1"
|
||||
min="0" required tabindex="2" #blcks="ngModel">
|
||||
<mat-error *ngIf="!blocks">Number of blocks is required.</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex.gt-sm="48" fxLayoutAlign="start end" *ngIf="selTransType=='2'">
|
||||
<input matInput [(ngModel)]="fees" placeholder="Fees (Sats/Byte)"
|
||||
type="number" name="fees" step="1" min="0" required tabindex="3" #fee="ngModel">
|
||||
<mat-error *ngIf="!fees">Fees is required.</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayoutAlign="end center">
|
||||
<button mat-stroked-button color="primary" type="reset" class="mr-1" (click)="resetData()" tabindex="2" default>Clear</button>
|
||||
<button mat-flat-button color="primary" type="submit" tabindex="4" (click)="onCloseChannel()">Close Channel</button>
|
||||
<button *ngIf="channelToClose.active && !flgPendingHtlcs" mat-stroked-button color="primary" type="reset" class="mr-1" (click)="resetData()" tabindex="3" default>Clear</button>
|
||||
<button *ngIf="!flgPendingHtlcs" mat-flat-button color="primary" type="submit" tabindex="4" (click)="onCloseChannel()">Close Channel</button>
|
||||
<button *ngIf="flgPendingHtlcs" mat-flat-button color="primary" type="submit" tabindex="5" (click)="onClose()">Ok</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-card-content>
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import { Component, OnInit, Inject } from '@angular/core';
|
||||
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { Subject } from 'rxjs';
|
||||
import { filter, takeUntil } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Actions } from '@ngrx/effects';
|
||||
import { faExclamationTriangle, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import { LoggerService } from '../../../../shared/services/logger.service';
|
||||
import { Channel } from '../../../../shared/models/lndModels';
|
||||
import { ChannelInformation } from '../../../../shared/models/alertData';
|
||||
import { TRANS_TYPES } from '../../../../shared/services/consts-enums-functions';
|
||||
|
@ -15,17 +20,35 @@ import * as fromRTLReducer from '../../../../store/rtl.reducers';
|
|||
templateUrl: './close-channel.component.html',
|
||||
styleUrls: ['./close-channel.component.scss']
|
||||
})
|
||||
export class CloseChannelComponent implements OnInit {
|
||||
export class CloseChannelComponent implements OnInit, OnDestroy {
|
||||
public channelToClose: Channel;
|
||||
public transTypes = TRANS_TYPES;
|
||||
public selTransType = '0';
|
||||
public blocks = null;
|
||||
public fees = null;
|
||||
public faExclamationTriangle = faExclamationTriangle;
|
||||
public faInfoCircle = faInfoCircle;
|
||||
public flgPendingHtlcs = false;
|
||||
public errorMsg = 'Please wait for pending HTLCs to settle before attempting channel closure.';
|
||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
|
||||
|
||||
constructor(public dialogRef: MatDialogRef<CloseChannelComponent>, @Inject(MAT_DIALOG_DATA) public data: ChannelInformation, private store: Store<fromRTLReducer.RTLState>) {}
|
||||
constructor(public dialogRef: MatDialogRef<CloseChannelComponent>, @Inject(MAT_DIALOG_DATA) public data: ChannelInformation, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions, private logger: LoggerService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.channelToClose = this.data.channel;
|
||||
this.actions$.pipe(takeUntil(this.unSubs[0]),
|
||||
filter(action => action.type === LNDActions.EFFECT_ERROR_LND || action.type === LNDActions.SET_ALL_CHANNELS_LND))
|
||||
.subscribe((action: LNDActions.EffectError | LNDActions.SetAllChannels) => {
|
||||
if (action.type === LNDActions.SET_ALL_CHANNELS_LND) {
|
||||
let filteredChannel = action.payload.find(channel => channel.chan_id === this.data.channel.chan_id);
|
||||
if (filteredChannel.pending_htlcs && filteredChannel.pending_htlcs.length && filteredChannel.pending_htlcs.length > 0) {
|
||||
this.flgPendingHtlcs = true;
|
||||
}
|
||||
}
|
||||
if (action.type === LNDActions.EFFECT_ERROR_LND && action.payload.action === 'FetchChannels/all') {
|
||||
this.logger.error('Fetching latest channel information failed!\n' + action.payload.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onCloseChannel() {
|
||||
|
@ -48,4 +71,10 @@ export class CloseChannelComponent implements OnInit {
|
|||
this.dialogRef.close(false);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unSubs.forEach(completeSub => {
|
||||
completeSub.next();
|
||||
completeSub.complete();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1038,4 +1038,10 @@ table {
|
|||
30% {transform: translateY(-20%)}
|
||||
40% {transform: translateY(20%)}
|
||||
50% {transform: translateY(0)}
|
||||
}
|
||||
}
|
||||
|
||||
.mat-form-field-appearance-legacy.mat-form-field-disabled {
|
||||
& input, mat-select, .mat-select-trigger, .mat-select-value, .mat-select-arro-wrapper, textarea, .mat-form-field-infix {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
$background: map-get($theme, background);
|
||||
$background-color: mat-color($background, card);
|
||||
$hover-background: rgba(0, 0, 0, 0.04);
|
||||
$hover-background-white: rgba(255, 255, 255, 0.06);
|
||||
$hover-background-dark: rgba(255, 255, 255, 0.06);
|
||||
|
||||
.bg-primary {
|
||||
@include _mat-toolbar-color($primary);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
$background: map-get($theme, background);
|
||||
$background-color: mat-color($background, card);
|
||||
$hover-background: rgba(0, 0, 0, 0.04);
|
||||
$hover-background-white: rgba(255, 255, 255, 0.06);
|
||||
$hover-background-dark: rgba(255, 255, 255, 0.06);
|
||||
|
||||
&.night {
|
||||
.mat-primary {
|
||||
|
@ -68,7 +68,7 @@
|
|||
.mat-tree-node:hover, .mat-nested-tree-node-parent:hover, .mat-select-panel .mat-option:hover, .mat-menu-panel .mat-menu-content .mat-menu-item:hover {
|
||||
color: $primary-darker;
|
||||
cursor: pointer;
|
||||
background: $hover-background-white;
|
||||
background: $hover-background-dark;
|
||||
& .ng-fa-icon, & .mat-icon {
|
||||
color: $primary-darker;
|
||||
}
|
||||
|
@ -170,4 +170,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
& .mat-form-field-disabled {
|
||||
& .mat-form-field-underline{
|
||||
background-color: transparent;
|
||||
background-image: linear-gradient(90deg,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);
|
||||
background-size: 5px 100%;
|
||||
height: 1.4px;
|
||||
}
|
||||
& .mat-form-field-flex {
|
||||
background-color: $hover-background-dark;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
$background: map-get($theme, background);
|
||||
$background-color: mat-color($background, card);
|
||||
$hover-background: rgba(0, 0, 0, 0.04);
|
||||
$hover-background-white: rgba(255, 255, 255, 0.06);
|
||||
$hover-background-dark: rgba(255, 255, 255, 0.06);
|
||||
|
||||
&.day {
|
||||
.mat-progress-bar.this-channel-bar .mat-progress-bar-fill::after {
|
||||
|
@ -165,4 +165,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
& .mat-form-field-disabled {
|
||||
& .mat-form-field-underline{
|
||||
background-color: transparent;
|
||||
background-image: linear-gradient(90deg,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);
|
||||
background-size: 5px 100%;
|
||||
height: 1.4px;
|
||||
}
|
||||
& .mat-form-field-flex {
|
||||
background-color: $hover-background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue