list invoice htlcs (#448)

list invoice htlcs
This commit is contained in:
ShahanaFarooqui 2020-08-25 22:27:33 -04:00 committed by GitHub
parent 25bdec8a70
commit 5aac044a13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 155 additions and 75 deletions

File diff suppressed because one or more lines are too long

View File

@ -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.1268069d095d5cf8e257.css"></head>
<link rel="stylesheet" href="styles.359ebcd013ec97f69532.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.9e7465a615254b205f19.js" defer></script><script src="polyfills-es5.2ac0d98b22574ae745b1.js" nomodule defer></script><script src="polyfills.5ae721a6ae5ab597a53d.js" defer></script><script src="main.3d79a2643378c8aeda8b.js" defer></script></body>
<script src="runtime.9286733a532e58a6bba7.js" defer></script><script src="polyfills-es5.2ac0d98b22574ae745b1.js" nomodule defer></script><script src="polyfills.5ae721a6ae5ab597a53d.js" defer></script><script src="main.f38d9b0b63f350c3adfc.js" defer></script></body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],f=r[2],p=0,s=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"9bb271dd8dffd2d994a5",6:"02d8d1e879c0be336222",7:"4a00e92294df28ac9ca1",8:"57420fc1ef9c4c3b9030"}[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:"957aa486ae91d97f8075"}[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()}([]);

File diff suppressed because one or more lines are too long

View File

@ -50,10 +50,17 @@ exports.listInvoices = (req, res, next) => {
} else {
if (body.invoices && body.invoices.length > 0) {
body.invoices.forEach(invoice => {
invoice.r_preimage = invoice.r_preimage ? Buffer.from(invoice.r_preimage, 'base64').toString('hex') : '';
invoice.r_hash = invoice.r_hash ? Buffer.from(invoice.r_hash, 'base64').toString('hex') : '';
invoice.description_hash = invoice.description_hash ? Buffer.from(invoice.description_hash, 'base64').toString('hex') : null;
invoice.creation_date_str = (!invoice.creation_date) ? '' : common.convertTimestampToDate(invoice.creation_date);
invoice.settle_date_str = (!invoice.settle_date || invoice.settle_date === '0') ? '' : common.convertTimestampToDate(invoice.settle_date);
invoice.btc_value = (!invoice.value) ? 0 : common.convertToBTC(invoice.value);
invoice.btc_amt_paid_sat = (!invoice.amt_paid_sat) ? 0 : common.convertToBTC(invoice.amt_paid_sat);
invoice.htlcs.forEach(htlc => {
htlc.accept_time_str = (!htlc.accept_time) ? '' : common.convertTimestampToDate(htlc.accept_time);
htlc.resolve_time_str = (!htlc.resolve_time) ? '' : common.convertTimestampToDate(htlc.resolve_time);
});
});
body.invoices = common.sortDescByKey(body.invoices, 'creation_date');
}

View File

@ -16,7 +16,7 @@
<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>
<span>Force closing an inactive channel costs a pre-defined fee.</span>
</div>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between center">
<mat-form-field fxFlex.gt-sm="48">

View File

@ -2,7 +2,7 @@
<div fxFlex="35" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap-large" [ngClass]="{'display-none': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}">
<qrcode [qrdata]="invoice.payment_request" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode>
</div>
<div fxFlex="65" class="padding-gap-large">
<div fxLayout="column" fxFlex="65" class="padding-gap-large">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header mb-2">
<div fxFlex="95" fxLayoutAlign="start start">
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
@ -15,6 +15,7 @@
<div fxFlex="30" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap" [ngClass]="{'display-none': screenSize !== screenSizeEnum.XS && screenSize !== screenSizeEnum.SM}">
<qrcode [qrdata]="invoice.payment_request" [margin]="2" [width]="qrWidth" [errorCorrectionLevel]="'L'" [allowEmptyString]="true"></qrcode>
</div>
<div perfectScrollbar [ngClass]="{'h-46': invoice.htlcs && invoice.htlcs.length > 0 && showAdvanced}" #scrollContainer>
<div fxLayout="row">
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">{{screenSize === screenSizeEnum.XS ? 'Amount' : 'Amount Requested'}}</h4>
@ -25,7 +26,7 @@
<span class="foreground-secondary-text">{{invoice.memo}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Date Created</h4>
@ -36,7 +37,7 @@
<span class="foreground-secondary-text">{{invoice.settle_date_str || '-'}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">Payment Request</h4>
@ -44,21 +45,14 @@
</div>
</div>
<div *ngIf="showAdvanced">
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">R Hash</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.r_hash}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">R Preimage</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.r_preimage || '-'}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="34">
<h4 fxLayoutAlign="start" class="font-bold-500">State</h4>
@ -73,9 +67,46 @@
<span class="overflow-wrap foreground-secondary-text">{{invoice.private ? 'Yes' : 'No'}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="row" *ngIf="invoice.htlcs && invoice.htlcs.length > 0">
<mat-expansion-panel (opened)="flgOpened = true" (closed)="onExpansionClosed()" class="flat-expansion-panel" fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100">
<mat-expansion-panel-header>
<mat-panel-title>
<h4 fxLayoutAlign="start center" fxFlex="100" class="font-bold-500">HTLCs</h4>
</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100">
<div fxLayout="row" fxLayoutAlign="start start" fxFlex="100" class="mt-minus-1">
<span fxFlex="60" class="foreground-secondary-text font-bold-500">Channel ID</span>
<span fxFlex="40" class="foreground-secondary-text font-bold-500">Amount (Sats)</span>
</div>
<div [ngClass]="{'mt-2': !showAdvanced, 'mt-1': showAdvanced}" fxLayout="row" fxLayoutAlign="end center" fxFlex="100">
<mat-divider [inset]="true" class="my-1"></mat-divider>
<div fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" *ngFor="let htlc of invoice.htlcs">
<div fxLayout="row" fxLayoutAlign="start start" fxFlex="100">
<span fxFlex="60" class="foreground-secondary-text">
<span *ngIf="htlc.state === 'SETTLED'" class="dot green" matTooltip="Settled" matTooltipPosition="right" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></span>
<span *ngIf="htlc.state === 'ACCEPTED'" class="dot yellow" matTooltip="Accepted" matTooltipPosition="right" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></span>
<span *ngIf="htlc.state === 'CANCELED'" class="dot red" matTooltip="Cancelled" matTooltipPosition="right" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></span>
{{htlc.chan_id}}
</span>
<span fxFlex="40" class="foreground-secondary-text">{{htlc.amt_msat/1000 | number:htlc?.amt_msat < 1000 ? '1.0-4' : '1.0-0'}}</span>
</div>
<mat-divider [inset]="true" class="my-1"></mat-divider>
</div>
</div>
</mat-expansion-panel>
</div>
<mat-divider [inset]="true" class="my-1" *ngIf="invoice.htlcs && invoice.htlcs.length > 0"></mat-divider>
</div>
</div>
</div>
</mat-card-content>
<div *ngIf="invoice.htlcs && invoice.htlcs.length > 0 && showAdvanced && flgOpened" fxLayout="row" fxLayoutAlign="start end" class="btn-sticky-container">
<button mat-mini-fab aria-label="Scroll Down" fxLayoutAlign="center center" (click)="onScrollDown()">
<mat-icon fxLayoutAlign="center center">arrow_downward</mat-icon>
</button>
</div>
<div fxLayout="row" fxLayoutAlign="end center" fxFlex="100">
<button mat-stroked-button color="primary" type="reset" (click)="onShowAdvanced()" tabindex="1" class="mr-1">
<p *ngIf="!showAdvanced; else hideAdvancedText">Show Advanced</p>
<ng-template #hideAdvancedText><p>Hide Advanced</p></ng-template>
@ -83,6 +114,4 @@
<button autoFocus mat-flat-button color="primary" tabindex="2" type="submit" rtlClipboard [payload]="invoice.payment_request" (copied)="onCopyPayment($event)">{{screenSize === screenSizeEnum.XS ? 'Copy Payment' : 'Copy Payment Request'}}</button>
</div>
</div>
</mat-card-content>
</div>
</div>

View File

@ -1,4 +1,4 @@
import { Component, OnInit, Inject } from '@angular/core';
import { Component, OnInit, Inject, ElementRef, ViewChild } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { faReceipt } from '@fortawesome/free-solid-svg-icons';
import { MatSnackBar } from '@angular/material/snack-bar';
@ -15,6 +15,10 @@ import { ScreenSizeEnum } from '../../../shared/services/consts-enums-functions'
styleUrls: ['./invoice-information.component.scss']
})
export class InvoiceInformationComponent implements OnInit {
private scrollContainer: ElementRef;
@ViewChild('scrollContainer') set container(containerContent: ElementRef) {
if(containerContent) { this.scrollContainer = containerContent; }
}
public faReceipt = faReceipt;
public showAdvanced = false;
public newlyAdded = false;
@ -22,6 +26,7 @@ export class InvoiceInformationComponent implements OnInit {
public qrWidth = 240;
public screenSize = '';
public screenSizeEnum = ScreenSizeEnum;
public flgOpened = false;
constructor(public dialogRef: MatDialogRef<InvoiceInformationComponent>, @Inject(MAT_DIALOG_DATA) public data: InvoiceInformation, private logger: LoggerService, private commonService: CommonService, private snackBar: MatSnackBar) { }
@ -40,6 +45,16 @@ export class InvoiceInformationComponent implements OnInit {
onShowAdvanced() {
this.showAdvanced = !this.showAdvanced;
this.flgOpened = false;
}
onScrollDown() {
this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollTop + 60;
}
onExpansionClosed() {
this.flgOpened = false
this.scrollContainer.nativeElement.scrollTop = 0;
}
onCopyPayment(payload: string) {

View File

@ -8,7 +8,7 @@ import { MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfo, Invoice } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';

View File

@ -9,7 +9,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { GetInfo, Payment, PayRequest, Channel, HTLC, Peer, Hop } from '../../../shared/models/lndModels';
import { GetInfo, Payment, PayRequest, Channel, PaymentHTLC, Peer, Hop } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, FEE_LIMIT_TYPES } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service';
@ -279,7 +279,7 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
}, []);
}
onHTLCClick(selHtlc: HTLC, selPayment: Payment) {
onHTLCClick(selHtlc: PaymentHTLC, selPayment: Payment) {
const reorderedHTLC = [
[{key: 'payment_hash', value: selPayment.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING}],
[{key: 'payment_request', value: selPayment.payment_request, title: 'Payment Request', width: 100, type: DataTypeEnum.STRING}],

View File

@ -38,6 +38,13 @@ export interface ChannelFeeReport {
fee_rate?: number;
}
export interface ChannelHTLC {
incoming?: boolean;
amount?: string;
hash_lock?: string;
expiration_height?: number;
}
export interface Channel {
active?: boolean;
remote_pubkey?: string;
@ -55,7 +62,7 @@ export interface Channel {
total_satoshis_received?: number;
num_updates?: number;
private?: boolean;
pending_htlcs?: HTLC[];
pending_htlcs?: ChannelHTLC[];
csv_delay?: number;
initiator?: boolean;
chan_status_flags?: string;
@ -245,7 +252,7 @@ export interface HopHint {
fee_base_msat?: number;
}
export interface HTLC {
export interface PaymentHTLC {
status?: string;
route?: Route;
attempt_time_ns?: string;
@ -256,13 +263,28 @@ export interface HTLC {
resolve_time_str?: string;
}
export interface InvoiceHTLC {
chan_id?: string;
htlc_index?: string;
amt_msat?: string;
accept_height?: number;
accept_time?: string;
accept_time_str?: string;
resolve_time?: string;
resolve_time_str?: string;
expiry_height?: number;
state?: string;
custom_records?: any;
mpp_total_amt_msat?: string;
}
export interface Invoice {
memo?: string;
receipt?: string;
r_preimage?: string;
r_hash?: string;
value?: string;
btc_value?: string;
value_msat?: string;
settled?: boolean;
creation_date?: string;
creation_date_str?: string;
@ -273,7 +295,6 @@ export interface Invoice {
expiry?: string;
fallback_addr?: string;
cltv_expiry?: string;
state?: string;
route_hints?: RouteHint[];
private?: boolean;
add_index?: string;
@ -282,6 +303,10 @@ export interface Invoice {
amt_paid_sat?: string;
btc_amt_paid_sat?: string;
amt_paid_msat?: string;
state?: string;
htlcs?: InvoiceHTLC[];
features?: any;
is_keysend?: boolean;
}
export interface ListInvoices {
@ -337,7 +362,7 @@ export interface Payment {
creation_time_ns?: string;
payment_index?: string;
failure_reason?: string;
htlcs: HTLC[];
htlcs: PaymentHTLC[];
is_expanded?: boolean;
}

View File

@ -776,6 +776,10 @@ body {
height: 40rem !important;
}
.h-46 {
height: 46rem !important;
}
.h-10 {
height: 10rem !important;
}