Peers & Channels incomplete

Peers & Channels incomplete
This commit is contained in:
Shahana Farooqui 2019-11-20 19:14:37 -05:00
parent 55eb1f17b9
commit fce6528912
75 changed files with 727 additions and 867 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

View File

@ -9,8 +9,8 @@
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicon/favicon-16x16.png">
<link rel="manifest" href="assets/images/favicon/site.webmanifest">
<link rel="stylesheet" href="styles.93709d9cb38e5e717354.css"></head>
<link rel="stylesheet" href="styles.71666b4a6e6d3212bd76.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.8f0530cea64d73898b16.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.f1e6e0c51b8b63b3a908.js"></script></body>
<script src="runtime.bc5ba64463967ed50d79.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.07e5edd09acda10c8553.js"></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 +0,0 @@
!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++)o[a=i[p]]&&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:"180f16dffe826f0afab2",6:"aa83a4ccf47ad807eb8d",7:"e89ae7e15a1c87bbd30d"}[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()}([]);

View File

@ -0,0 +1 @@
!function(e){function r(r){for(var n,i,a=r[0],c=r[1],f=r[2],p=0,s=[];p<a.length;p++)o[i=a[p]]&&s.push(o[i][0]),o[i]=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,a=1;a<t.length;a++)0!==o[t[a]]&&(n=!1);n&&(u.splice(r--,1),e=i(i.s=t[0]))}return e}var n={},o={0:0},u=[];function i(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,i),t.l=!0,t.exports}i.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,a=document.createElement("script");a.charset="utf-8",a.timeout=120,i.nc&&a.setAttribute("nonce",i.nc),a.src=function(e){return i.p+""+({}[e]||e)+"."+{1:"180f16dffe826f0afab2",6:"1b0ecbae257ecf6cd485",7:"c121ddc37976e4803c74"}[e]+".js"}(e);var c=new Error;u=function(r){a.onerror=a.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:a})}),12e4);a.onerror=a.onload=u,document.head.appendChild(a)}return Promise.all(r)},i.m=e,i.c=n,i.d=function(e,r,t){i.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,r){if(1&r&&(e=i(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(i.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)i.d(t,n,(function(r){return e[r]}).bind(null,n));return t},i.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(r,"a",r),r},i.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},i.p="",i.oe=function(e){throw console.error(e),e};var a=window.webpackJsonp=window.webpackJsonp||[],c=a.push.bind(a);a.push=r,a=a.slice();for(var f=0;f<a.length;f++)r(a[f]);var l=c;t()}([]);

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,130 +0,0 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card [ngClass]="{'flip': redirectedWithPeer}">
<mat-card-header>
<mat-card-subtitle>
<h2>Open Channel</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<form fxLayout="column" fxLayout.gt-sm="row wrap" (ngSubmit)="openChannelForm.form.valid && onOpenChannel(openChannelForm)" #openChannelForm="ngForm">
<mat-form-field fxFlex="40" fxLayoutAlign="start end">
<mat-select [(ngModel)]="selectedPeer" placeholder="Alias" name="peer_alias" tabindex="1" required name="selPeer" #selPeer="ngModel">
<mat-option *ngFor="let peer of peers" [value]="peer.pub_key">
{{peer.alias}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="25" fxLayoutAlign="start end">
<input matInput [(ngModel)]="fundingAmount" placeholder="Amount ({{information?.smaller_currency_unit}})" type="number" step="1000" min="1" tabindex="2" required name="amount" #amount="ngModel">
<mat-hint>(Wallet Bal: {{totalBalance}}, Remaining Bal: {{totalBalance - ((fundingAmount) ? fundingAmount : 0)}})</mat-hint>
</mat-form-field>
<div fxFlex="15" tabindex="3" fxLayoutAlign="start center" class="chkbox-options">
<mat-checkbox [(ngModel)]="moreOptions" name="moreOptions" (change)="onMoreOptionsChange($event)">Options</mat-checkbox>
</div>
<span *ngIf="moreOptions" fxLayout="column" fxLayout.gt-sm="row wrap" fxFlex="80" fxLayoutAlign.gt-sm="space-between center">
<mat-form-field fxFlex="25" fxLayoutAlign="start end">
<mat-select tabindex="4" [(value)]="selTransType">
<mat-option *ngFor="let transType of transTypes" [value]="transType.id">
{{transType.name}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="25" *ngIf="selTransType=='0'">
<input matInput placeholder="Channel Opening Priority" disabled>
</mat-form-field>
<mat-form-field fxFlex="25" *ngIf="selTransType=='1'">
<input matInput [(ngModel)]="transTypeValue.blocks" placeholder="Target Confirmation Blocks" type="number" name="blocks" step="1" min="0" required tabindex="5" #blocks="ngModel">
</mat-form-field>
<mat-form-field fxFlex="25" *ngIf="selTransType=='2'">
<input matInput [(ngModel)]="transTypeValue.fees" placeholder="Fee ({{information?.smaller_currency_unit}}/Byte)" type="number" name="fees" step="1" min="0" required tabindex="6" #fees="ngModel">
</mat-form-field>
<mat-checkbox fxFlex="25" fxFlex.lt-lg="35" tabindex="7" [(ngModel)]="spendUnconfirmed" name="spendUnconfirmed">Spend Unconfirmed Output</mat-checkbox>
<mat-checkbox fxFlex="20" fxFlex.lt-lg="15" tabindex="8" [(ngModel)]="isPrivate" name="isPrivate">Private</mat-checkbox>
</span>
<div fxFlex="10" fxLayoutAlign="end start">
<button fxFlex="90" fxLayoutAlign="center center" mat-raised-button color="primary" [disabled]="selectedPeer === '' || fundingAmount == null || (totalBalance - ((fundingAmount) ? fundingAmount : 0) < 0)" type="submit" tabindex="8">
<p *ngIf="(selectedPeer === '' || fundingAmount == null) && (selPeer.touched || selPeer.dirty) && (amount.touched || amount.dirty); else openText">Invalid Values</p>
<ng-template #openText><p>Open</p></ng-template>
</button>
</div>
<div fxFlex="10" fxLayoutAlign="end start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="9" type="reset" (click)="resetData()">Clear</button>
</div>
</form>
</mat-card-content>
</mat-card>
</div>
<div class="padding-gap">
<mat-card>
<mat-card-content fxFlex="100" fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start start">
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="channels" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="close">
<th mat-header-cell *matHeaderCellDef> Close Channel </th>
<td mat-cell *matCellDef="let channel"><mat-icon color="accent" (click)="onChannelClose(channel)">link_off</mat-icon></td>
</ng-container>
<ng-container matColumnDef="update">
<th mat-header-cell *matHeaderCellDef><mat-icon color="accent" (click)="onChannelUpdate('all')">edit</mat-icon></th>
<td mat-cell *matCellDef="let channel"><mat-icon color="accent" (click)="onChannelUpdate(channel)">edit</mat-icon></td>
</ng-container>
<ng-container matColumnDef="active">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th>
<td mat-cell *matCellDef="let channel"> {{(channel.active) ? 'Active' : 'Inactive'}} </td>
</ng-container>
<ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
<td mat-cell *matCellDef="let channel"> {{channel.chan_id}} </td>
</ng-container>
<ng-container matColumnDef="remote_pubkey">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Pub Key </th>
<td mat-cell *matCellDef="let channel">
<div>{{channel.remote_pubkey | slice:0:10}}...</div></td>
</ng-container>
<ng-container matColumnDef="remote_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Alias </th>
<td mat-cell *matCellDef="let channel">{{channel.remote_alias}}</td>
</ng-container>
<ng-container matColumnDef="capacity">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Capacity </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.capacity | number}} </span></td>
</ng-container>
<ng-container matColumnDef="local_balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Local Bal </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.local_balance | number}} </span></td>
</ng-container>
<ng-container matColumnDef="remote_balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Remote Bal </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.remote_balance | number}} </span></td>
</ng-container>
<ng-container matColumnDef="total_satoshis_sent">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> {{information?.smaller_currency_unit}} Sent </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.total_satoshis_sent | number}} </span></td>
</ng-container>
<ng-container matColumnDef="total_satoshis_received">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> {{information?.smaller_currency_unit}} Recv </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.total_satoshis_received | number}} </span></td>
</ng-container>
<ng-container matColumnDef="commit_fee">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Fee </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.commit_fee | number}} </span></td>
</ng-container>
<ng-container matColumnDef="private">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Private </th>
<td mat-cell *matCellDef="let channel"> {{(channel.private ? 'Private' : 'Public')}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="onChannelClick(row, $event)"></tr>
</table>
</div>
</mat-card-content>
</mat-card>
</div>
</div>

View File

@ -6,31 +6,32 @@ import { SharedModule } from '../shared/shared.module';
import { LNDRootComponent } from './lnd-root.component';
import { HomeComponent } from './home/home.component';
import { PeersComponent } from './peers/peers.component';
import { SendReceiveTransComponent } from './old-transactions/send-receive/send-receive-trans.component';
import { PeersChannelsComponent } from './peers-channels/peers-channels.component';
import { ChannelsTablesComponent } from './peers-channels/channels/channels-tables/channels-tables.component';
import { PeersComponent } from './peers-channels/peers/peers.component';
import { LightningInvoicesComponent } from './transactions/invoices/lightning-invoices.component';
import { OnChainSendComponent } from './on-chain/on-chain-send/on-chain-send.component';
import { OnChainReceiveComponent } from './on-chain/on-chain-receive/on-chain-receive.component';
import { OnChainComponent } from './on-chain/on-chain.component';
import { OnChainTransactionHistoryComponent } from './on-chain/on-chain-transaction-history/on-chain-transaction-history.component';
import { UnlockLNDComponent } from './unlock-lnd/unlock-lnd.component';
import { LightningPaymentsComponent } from './transactions/payments/lightning-payments.component';
import { ChannelManageComponent } from './channels/channel-manage/channel-manage.component';
import { ChannelPendingComponent } from './channels/channel-pending/channel-pending.component';
import { ChannelClosedComponent } from './channels/channel-closed/channel-closed.component';
import { ChannelManageComponent } from './peers-channels/channels/channel-manage/channel-manage.component';
import { ChannelPendingTableComponent } from './peers-channels/channels/channels-tables/channel-pending-table/channel-pending-table.component';
import { ChannelClosedTableComponent } from './peers-channels/channels/channels-tables/channel-closed-table/channel-closed-table.component';
import { TransactionsComponent } from './transactions/transactions.component';
import { ListTransactionsComponent } from './old-transactions/list-transactions/list-transactions.component';
import { LookupsComponent } from './lookups/lookups.component';
import { ForwardingHistoryComponent } from './switch/forwarding-history.component';
import { RoutingPeersComponent } from './routing-peers/routing-peers.component';
import { ChannelLookupComponent } from './lookups/channel-lookup/channel-lookup.component';
import { NodeLookupComponent } from './lookups/node-lookup/node-lookup.component';
import { ChannelBackupComponent } from './channels/channel-backup/channel-backup.component';
import { ChannelRestoreComponent } from './channels/channel-restore/channel-restore.component';
import { ChannelBackupComponent } from './peers-channels/channels/channel-backup/channel-backup.component';
import { ChannelRestoreComponent } from './peers-channels/channels/channel-restore/channel-restore.component';
import { QueryRoutesComponent } from './payments/query-routes/query-routes.component';
import { LoggerService, ConsoleLoggerService } from '../shared/services/logger.service';
import { LNDUnlockedGuard } from '../shared/services/auth.guard';
import { OnChainTransactionHistoryComponent } from './on-chain/on-chain-transaction-history/on-chain-transaction-history.component';
import { ChannelOpenTableComponent } from './peers-channels/channels/channels-tables/channel-open-table/channel-open-table.component';
@NgModule({
imports: [
@ -42,15 +43,14 @@ import { OnChainTransactionHistoryComponent } from './on-chain/on-chain-transact
LNDRootComponent,
HomeComponent,
PeersComponent,
SendReceiveTransComponent,
PeersChannelsComponent,
LightningInvoicesComponent,
UnlockLNDComponent,
LightningPaymentsComponent,
ChannelManageComponent,
ChannelPendingComponent,
ChannelClosedComponent,
ChannelPendingTableComponent,
ChannelClosedTableComponent,
TransactionsComponent,
ListTransactionsComponent,
LookupsComponent,
ForwardingHistoryComponent,
RoutingPeersComponent,
@ -62,7 +62,9 @@ import { OnChainTransactionHistoryComponent } from './on-chain/on-chain-transact
OnChainSendComponent,
OnChainReceiveComponent,
OnChainComponent,
OnChainTransactionHistoryComponent
OnChainTransactionHistoryComponent,
ChannelsTablesComponent,
ChannelOpenTableComponent
],
providers: [
{ provide: LoggerService, useClass: ConsoleLoggerService },

View File

@ -3,20 +3,15 @@ import { ModuleWithProviders } from '@angular/core';
import { LNDRootComponent } from './lnd-root.component';
import { HomeComponent } from './home/home.component';
import { PeersChannelsComponent } from './peers-channels/peers-channels.component';
import { UnlockLNDComponent } from './unlock-lnd/unlock-lnd.component';
import { ChannelClosedComponent } from './channels/channel-closed/channel-closed.component';
import { ChannelManageComponent } from './channels/channel-manage/channel-manage.component';
import { ChannelPendingComponent } from './channels/channel-pending/channel-pending.component';
import { PeersComponent } from './peers/peers.component';
import { TransactionsComponent } from './transactions/transactions.component';
import { SendReceiveTransComponent } from './old-transactions/send-receive/send-receive-trans.component';
import { ListTransactionsComponent } from './old-transactions/list-transactions/list-transactions.component';
import { QueryRoutesComponent } from './payments/query-routes/query-routes.component';
import { LookupsComponent } from './lookups/lookups.component';
import { ForwardingHistoryComponent } from './switch/forwarding-history.component';
import { RoutingPeersComponent } from './routing-peers/routing-peers.component';
import { ChannelBackupComponent } from './channels/channel-backup/channel-backup.component';
import { ChannelRestoreComponent } from './channels/channel-restore/channel-restore.component';
import { ChannelBackupComponent } from './peers-channels/channels/channel-backup/channel-backup.component';
import { ChannelRestoreComponent } from './peers-channels/channels/channel-restore/channel-restore.component';
import { OnChainComponent } from './on-chain/on-chain.component';
import { AuthGuard, LNDUnlockedGuard } from '../shared/services/auth.guard';
@ -27,20 +22,15 @@ export const LndRoutes: Routes = [
children: [
{ path: 'unlocklnd', component: UnlockLNDComponent, canActivate: [AuthGuard] },
{ path: 'home', component: HomeComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'peers', component: PeersComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlclosed', component: ChannelClosedComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlmanage', component: ChannelManageComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlpending', component: ChannelPendingComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlbackup', component: ChannelBackupComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlrestore', component: ChannelRestoreComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'peerschannels', component: PeersChannelsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'transactions', component: TransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'onchain', component: OnChainComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'translist', component: ListTransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlbackup', component: ChannelBackupComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlrestore', component: ChannelRestoreComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'queryroutes', component: QueryRoutesComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'switch', component: ForwardingHistoryComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'forwardinghistory', component: ForwardingHistoryComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'routingpeers', component: RoutingPeersComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'lookups', component: LookupsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'forwardinghistory', redirectTo: 'switch' },
{ path: '**', component: NotFoundComponent }
]}
];

View File

@ -1,57 +0,0 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Transactions</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content class="table-card-content">
<div fxLayout="row" fxLayoutAlign="start start">
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="listTransactions" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="dest_addresses">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Destination Addresses</th>
<td mat-cell *matCellDef="let trans">{{trans?.dest_addresses?.length || 0}} Addr</td>
</ng-container>
<ng-container matColumnDef="time_stamp">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Timestamp </th>
<td mat-cell *matCellDef="let trans"> {{trans.time_stamp_str}}</td>
</ng-container>
<ng-container matColumnDef="num_confirmations">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Num Confirmations </th>
<td mat-cell *matCellDef="let trans"><span fxLayoutAlign="end center"> {{trans.num_confirmations | number}} </span></td>
</ng-container>
<ng-container matColumnDef="total_fees">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Total Fees </th>
<td mat-cell *matCellDef="let trans"><span fxLayoutAlign="end center"> {{trans.total_fees | number}} </span></td>
</ng-container>
<ng-container matColumnDef="block_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Block Hash </th>
<td mat-cell *matCellDef="let trans">{{trans.block_hash | removeleadingzeros}}</td>
</ng-container>
<ng-container matColumnDef="block_height">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Block Height </th>
<td mat-cell *matCellDef="let trans"><span fxLayoutAlign="end center"> {{trans.block_height | number}} </span></td>
</ng-container>
<ng-container matColumnDef="tx_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Txn Hash </th>
<td mat-cell *matCellDef="let trans">{{trans.tx_hash}}</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Amount </th>
<td mat-cell *matCellDef="let trans"><span fxLayoutAlign="end center"> {{trans.amount | number}} </span></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="onTransactionClick(row, $event)"></tr>
</table>
</div>
</mat-card-content>
</mat-card>
</div>
</div>

View File

@ -1,29 +0,0 @@
.ml-minus-24px {
margin-left: -24px;
}
table {
width:100%;
}
.mat-column-block_hash, .mat-column-tx_hash {
flex: 1 1 25%;
min-width: 100px;
max-width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-left: 20px;
}
.mat-column-dest_addresses, .mat-column-time_stamp {
flex: 1 1 10%;
min-width: 75px;
max-width: 75px;
}
.mat-column-num_confirmations, .mat-column-total_fees, .mat-column-block_height, .mat-column-amount {
flex: 1 1 10%;
min-width: 65px;
max-width: 65px;
}

View File

@ -1,112 +0,0 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { Transaction } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-list-transactions',
templateUrl: './list-transactions.component.html',
styleUrls: ['./list-transactions.component.scss']
})
export class ListTransactionsComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public displayedColumns = [];
public listTransactions: any;
public flgLoading: Array<Boolean | 'error'> = [true];
public flgSticky = false;
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private actions$: Actions) {
switch (true) {
case (window.innerWidth <= 415):
this.displayedColumns = ['dest_addresses', 'total_fees', 'amount'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['dest_addresses', 'time_stamp', 'total_fees', 'amount'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['dest_addresses', 'time_stamp', 'num_confirmations', 'total_fees', 'tx_hash', 'amount'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['dest_addresses', 'time_stamp', 'num_confirmations', 'total_fees', 'tx_hash', 'amount'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['dest_addresses', 'time_stamp', 'num_confirmations', 'total_fees', 'block_hash', 'block_height', 'tx_hash', 'amount'];
break;
}
}
ngOnInit() {
this.store.dispatch(new RTLActions.FetchTransactions());
this.actions$.pipe(takeUntil(this.unsub[2]), filter((action) => action.type === RTLActions.RESET_LND_STORE)).subscribe((resetLndStore: RTLActions.ResetLNDStore) => {
this.store.dispatch(new RTLActions.FetchTransactions());
});
this.store.select('lnd')
.pipe(takeUntil(this.unsub[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchTransactions') {
this.flgLoading[0] = 'error';
}
});
if (undefined !== rtlStore.transactions) {
this.loadTransactionsTable(rtlStore.transactions);
}
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== rtlStore.transactions) ? false : true;
}
this.logger.info(rtlStore);
});
}
applyFilter(selFilter: string) {
this.listTransactions.filter = selFilter;
}
onTransactionClick(selRow: Transaction, event: any) {
const flgExpansionClicked = event.target.className.includes('mat-expansion-panel-header') || event.target.className.includes('mat-expansion-indicator');
if (flgExpansionClicked) {
return;
}
const selTransaction = this.listTransactions.data.filter(transaction => {
return transaction.tx_hash === selRow.tx_hash;
})[0];
const reorderedTransactions = JSON.parse(JSON.stringify(selTransaction, [
'dest_addresses', 'time_stamp_str', 'num_confirmations', 'total_fees', 'block_hash', 'block_height', 'tx_hash', 'amount'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedTransactions)
}}}));
}
loadTransactionsTable(transactions) {
this.listTransactions = new MatTableDataSource<Transaction>([...transactions]);
this.listTransactions.sort = this.sort;
this.logger.info(this.listTransactions);
}
resetData() {
}
ngOnDestroy() {
this.unsub.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

View File

@ -1,167 +0,0 @@
<div fxLayout="column" fxLayoutAlign="center center" class="test-banner mx-1">
<h5>Don't be #reckless. #craefulgang #craefulgang #craefulgang.</h5>
</div>
<div fxLayout="column" fxLayout.gt-sm="row wrap">
<div fxFlex="34" class="padding-gap">
<mat-card [ngClass]="{'custom-card error-border': flgLoadingWallet==='error','custom-card': true}">
<mat-card-header class="bg-primary p-1" fxLayoutAlign="center center">
<mat-card-title class="m-0 pt-1">
<h5>Total Balance</h5>
<mat-progress-bar *ngIf="flgLoadingWallet===true" mode="indeterminate"></mat-progress-bar>
</mat-card-title>
</mat-card-header>
<mat-card-content fxLayout="column" fxLayoutAlign="center center">
<mat-card-content class="mt-1">
<svg style="width:70px;height:70px" viewBox="0 0 24 24">
<path fill="currentColor" d="M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V19A2,2 0 0,1 20,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" />
</svg>
</mat-card-content>
<span *ngIf="information?.currency_unit; else withoutData">
<h3 *ngIf="selNode?.satsToBTC; else smallerUnit1">{{blockchainBalance?.btc_total_balance | number}} {{information?.currency_unit}}</h3>
<ng-template #smallerUnit1><h3>{{blockchainBalance?.total_balance | number}} {{information?.smaller_currency_unit}}</h3></ng-template>
</span>
</mat-card-content>
<mat-progress-bar class="mt-minus-5" *ngIf="flgLoadingWallet===true" mode="indeterminate"></mat-progress-bar>
<mat-divider></mat-divider>
</mat-card>
</div>
<div fxFlex="33" class="padding-gap">
<mat-card [ngClass]="{'custom-card error-border': flgLoadingWallet==='error','custom-card': true}">
<mat-card-header class="bg-primary p-1" fxLayoutAlign="center center">
<mat-card-title class="m-0 pt-1">
<h5>Confirmed Balance</h5>
<mat-progress-bar *ngIf="flgLoadingWallet===true" mode="indeterminate"></mat-progress-bar>
</mat-card-title>
</mat-card-header>
<mat-card-content fxLayout="column" fxLayoutAlign="center center">
<mat-card-content class="mt-1">
<svg style="width:70px;height:70px" viewBox="0 0 24 24">
<path fill="currentColor" d="M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V19A2,2 0 0,1 20,21H4A2,2 0 0,1 2,19V8A2,2 0 0,1 4,6H8V4A2,2 0 0,1 10,2M14,6V4H10V6H14M10.5,17.5L17.09,10.91L15.68,9.5L10.5,14.67L8.41,12.59L7,14L10.5,17.5Z" />
</svg>
</mat-card-content>
<span *ngIf="information?.currency_unit; else withoutData">
<h3 *ngIf="selNode?.satsToBTC; else smallerUnit2">{{blockchainBalance?.btc_confirmed_balance | number}} {{information?.currency_unit}}</h3>
<ng-template #smallerUnit2><h3>{{blockchainBalance?.confirmed_balance | number}} {{information?.smaller_currency_unit}}</h3></ng-template>
</span>
</mat-card-content>
<mat-progress-bar class="mt-minus-5" *ngIf="flgLoadingWallet===true" mode="indeterminate"></mat-progress-bar>
<mat-divider></mat-divider>
</mat-card>
</div>
<div fxFlex="33" class="padding-gap">
<mat-card [ngClass]="{'custom-card error-border': flgLoadingWallet==='error','custom-card': true}">
<mat-card-header class="bg-primary p-1" fxLayoutAlign="center center">
<mat-card-title class="m-0 pt-1">
<h5>Unconfirmed Balance</h5>
<mat-progress-bar *ngIf="flgLoadingWallet===true" mode="indeterminate"></mat-progress-bar>
</mat-card-title>
</mat-card-header>
<mat-card-content fxLayout="column" fxLayoutAlign="center center">
<mat-card-content class="mt-1">
<svg style="width:70px;height:70px" viewBox="0 0 24 24">
<path fill="currentColor" d="M14,2A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8L10.85,19C10.85,20.1 10.85,19.5 10.85,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2H14M14,6V4H10V6H14M21.04,12.13C20.9,12.13 20.76,12.19 20.65,12.3L19.65,13.3L21.7,15.35L22.7,14.35C22.92,14.14 22.92,13.79 22.7,13.58L21.42,12.3C21.31,12.19 21.18,12.13 21.04,12.13M19.07,13.88L13,19.94V22H15.06L21.12,15.93L19.07,13.88Z" />
</svg>
</mat-card-content>
<span *ngIf="information?.currency_unit; else withoutData">
<h3 *ngIf="selNode?.satsToBTC; else smallerUnit3">{{blockchainBalance?.btc_unconfirmed_balance | number}} {{information?.currency_unit}}</h3>
<ng-template #smallerUnit3><h3>{{blockchainBalance?.unconfirmed_balance | number}} {{information?.smaller_currency_unit}}</h3></ng-template>
</span>
</mat-card-content>
<mat-progress-bar class="mt-minus-5" *ngIf="flgLoadingWallet===true" mode="indeterminate"></mat-progress-bar>
<mat-divider></mat-divider>
</mat-card>
</div>
<div fxFlex="100" class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Receive Funds</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div fxLayout="column" fxFlex="100" fxLayout.lt-md="top-minus-25px">
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" fxLayout.gt-md="row wrap">
<div fxFlex="15" fxLayoutAlign="start end">
<mat-form-field fxFlex="99">
<mat-select [(ngModel)]="selectedAddress" placeholder="Address Type" name="address_type" tabindex="1">
<mat-option *ngFor="let addressType of addressTypes" [value]="addressType">
{{addressType.addressTp}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div fxFlex="25" fxLayoutAlign="space-between end">
<div fxFlex.gt-md="65" fxFlex.lt-lg="49" fxLayoutAlign="start end">
<button fxLayoutAlign="center center" mat-raised-button color="primary" [disabled]="undefined === selectedAddress.addressId" (click)="onGenerateAddress()" tabindex="2" class="top-minus-15px">Generate Address</button>
</div>
<div fxFlex.gt-md="30" fxFlex.lt-lg="49" fxLayoutAlign="start end">
<button fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="3" (click)="resetReceiveData()" class="top-minus-15px">Clear</button>
</div>
</div>
<div fxFlex="42" fxLayoutAlign="start end">
<mat-form-field fxFlex="100">
<input matInput [value]="newAddress" placeholder="Generated Address" readonly>
</mat-form-field>
</div>
<div fxFlex.lt-lg="40" fxFlex.gt-md="14" fxLayoutAlign="center center">
<qrcode [qrdata]="newAddress" [size]="120" [level]="'L'" [allowEmptyString]="true" [ngStyle]="{'visibility': (newAddress === '') ? 'hidden' : 'visible'}" class="top-minus-5px qr-border"></qrcode>
</div>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
<div fxFlex="100" class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Send Funds</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div fxLayout="column" fxLayout.gt-sm="row wrap">
<div fxFlex="62" fxLayoutAlign="start end">
<mat-form-field fxFlex="99">
<input matInput [(ngModel)]="transaction.address" placeholder="{{information?.currency_unit}} Address" tabindex="4" name="address" #address="ngModel">
</mat-form-field>
</div>
<div fxFlex="38" fxLayoutAlign="start end">
<mat-radio-group fxFlex="100" fxLayoutAlign="space-between center" (change)="onOptionChange($event)" [(ngModel)]="flgCustomAmount">
<mat-radio-button fxFlex="35" value="0">Sweep All</mat-radio-button>
<mat-radio-button fxFlex="60" value="1">
<mat-form-field fxFlex="70"><input matInput [(ngModel)]="transaction.amount" (click)="onCustomClicked()" placeholder="Amount ({{information?.smaller_currency_unit}})" name="amount" type="number" step="100" min="0" tabindex="5" #amount="ngModel"></mat-form-field>
</mat-radio-button>
</mat-radio-group>
</div>
</div>
<div fxLayout="column" fxLayout.gt-sm="row wrap">
<div fxFlex="30" fxLayoutAlign="start start">
<mat-form-field fxFlex="99">
<mat-select [(value)]="selTransType">
<mat-option *ngFor="let transType of transTypes" [value]="transType.id">
{{transType.name}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div fxFlex="30" fxLayoutAlign="start start">
<mat-form-field fxFlex="99" *ngIf="selTransType=='1'">
<input matInput [(ngModel)]="transaction.blocks" placeholder="Target Confirmation Blocks" type="number" name="blocks" step="1" min="0" required tabindex="6" #blocks="ngModel">
</mat-form-field>
<mat-form-field fxFlex="99" *ngIf="selTransType=='2'">
<input matInput [(ngModel)]="transaction.fees" placeholder="Fee ({{information?.smaller_currency_unit}}/Byte)" type="number" name="fees" step="1" min="0" required tabindex="7" #fees="ngModel">
</mat-form-field>
</div>
<div fxFlex="40" fxLayoutAlign="space-between start">
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" [disabled]="invalidValues" type="submit" tabindex="8" (click)="onSendFunds()">
<p *ngIf="invalidValues && (address.touched || address.dirty) && (amount.touched || amount.dirty); else sendText">Invalid Values</p>
<ng-template #sendText><p>Send</p></ng-template>
</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="9" type="reset" (click)="resetData()">Clear</button>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
</div>
<ng-template #withoutData><h3>Sats</h3></ng-template>

View File

@ -1,183 +0,0 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfo, Balance, ChannelsTransaction, AddressType } from '../../../shared/models/lndModels';
import { RTLConfiguration } from '../../../shared/models/RTLconfig';
import { LoggerService } from '../../../shared/services/logger.service';
import * as sha256 from 'sha256';
import { LNDEffects } from '../../store/lnd.effects';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-send-receive-trans',
templateUrl: './send-receive-trans.component.html',
styleUrls: ['./send-receive-trans.component.scss']
})
export class SendReceiveTransComponent implements OnInit, OnDestroy {
public selNode: SelNodeChild = {};
public appConfig: RTLConfiguration;
public addressTypes = [];
public flgLoadingWallet: Boolean | 'error' = true;
public selectedAddress: AddressType = {};
public blockchainBalance: Balance = {};
public information: GetInfo = {};
public newAddress = '';
public transaction: ChannelsTransaction = {};
public transTypes = [{id: '1', name: 'Target Confirmation Blocks'}, {id: '2', name: 'Fee'}];
public selTransType = '1';
public flgCustomAmount = '1';
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private lndEffects: LNDEffects) {}
ngOnInit() {
this.store.select('root')
.pipe(takeUntil(this.unsub[0]))
.subscribe((rootStore) => {
this.appConfig = rootStore.appConfig;
this.logger.info(rootStore);
});
this.store.select('lnd')
.pipe(takeUntil(this.unsub[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchBalance/blockchain') {
this.flgLoadingWallet = 'error';
}
});
this.selNode = rtlStore.nodeSettings;
this.information = rtlStore.information;
// this.addressTypes = rtlStore.addressTypes;
this.blockchainBalance = rtlStore.blockchainBalance;
if (undefined === this.blockchainBalance.total_balance) {
this.blockchainBalance.total_balance = 0;
}
if (undefined === this.blockchainBalance.confirmed_balance) {
this.blockchainBalance.confirmed_balance = 0;
}
if (undefined === this.blockchainBalance.unconfirmed_balance) {
this.blockchainBalance.unconfirmed_balance = 0;
}
if (this.flgLoadingWallet !== 'error') {
this.flgLoadingWallet = false;
}
this.logger.info(rtlStore);
});
}
onGenerateAddress() {
this.store.dispatch(new RTLActions.OpenSpinner('Getting New Address...'));
this.store.dispatch(new RTLActions.GetNewAddress(this.selectedAddress));
this.lndEffects.setNewAddress
.pipe(takeUntil(this.unsub[1]))
.subscribe(newAddress => {
this.newAddress = newAddress;
});
}
onSendFunds() {
const confirmationMsg = {
'BTC Address': this.transaction.address,
};
if (!+this.flgCustomAmount) {
confirmationMsg['Sweep All'] = 'True';
this.transaction.sendAll = true;
} else {
confirmationMsg['Amount (' + this.information.smaller_currency_unit + ')'] = this.transaction.amount;
this.transaction.sendAll = false;
}
if (this.selTransType === '1') {
delete this.transaction.fees;
confirmationMsg['Target Confirmation Blocks'] = this.transaction.blocks;
} else {
delete this.transaction.blocks;
confirmationMsg['Fee (' + this.information.smaller_currency_unit + '/Byte)'] = this.transaction.fees;
}
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data:
{type: 'CONFIRM', message: JSON.stringify(confirmationMsg), noBtnText: 'Cancel', yesBtnText: 'Send'}
}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[2]))
.subscribe(confirmRes => {
if (confirmRes) {
if (this.transaction.sendAll && !+this.appConfig.sso.rtlSSO) {
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data:
{type: 'CONFIRM', titleMessage: 'Enter Login Password', noBtnText: 'Cancel', yesBtnText: 'Authorize', flgShowInput: true, getInputs: [
{placeholder: 'Enter Login Password', inputType: 'password', inputValue: ''}
]}
}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[3]))
.subscribe(pwdConfirmRes => {
if (pwdConfirmRes) {
const pwd = pwdConfirmRes[0].inputValue;
this.store.dispatch(new RTLActions.IsAuthorized(sha256(pwd)));
this.rtlEffects.isAuthorizedRes
.pipe(take(1))
.subscribe(authRes => {
if (authRes !== 'ERROR') {
this.dispatchToSendFunds();
}
});
}
});
} else {
this.dispatchToSendFunds();
}
}
});
}
dispatchToSendFunds() {
this.store.dispatch(new RTLActions.OpenSpinner('Sending Funds...'));
this.store.dispatch(new RTLActions.SetChannelTransaction(this.transaction));
this.transaction = {address: '', amount: 0, blocks: 0, fees: 0};
}
get invalidValues(): boolean {
return (undefined === this.transaction.address || this.transaction.address === '')
|| (+this.flgCustomAmount && (undefined === this.transaction.amount || this.transaction.amount <= 0))
|| (this.selTransType === '1' && (undefined === this.transaction.blocks || this.transaction.blocks <= 0))
|| (this.selTransType === '2' && (undefined === this.transaction.fees || this.transaction.fees <= 0));
}
onCustomClicked() {
this.flgCustomAmount = '1';
}
onOptionChange(event) {
if (!+this.flgCustomAmount) {
delete this.transaction.amount;
}
}
resetData() {
this.transaction.address = '';
this.transaction.amount = 0;
this.transaction.blocks = 0;
this.transaction.fees = 0;
}
resetReceiveData() {
this.selectedAddress = {};
this.newAddress = '';
}
ngOnDestroy() {
this.unsub.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

View File

@ -1,15 +1,12 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { faExchangeAlt, faChartPie } from '@fortawesome/free-solid-svg-icons';
import { SelNodeChild } from '../../shared/models/RTLconfig';
import { GetInfo, Balance, ChannelsTransaction, AddressType } from '../../shared/models/lndModels';
import { RTLConfiguration } from '../../shared/models/RTLconfig';
import * as fromRTLReducer from '../../store/rtl.reducers';
import * as RTLActions from '../../store/rtl.actions';
@Component({
selector: 'rtl-on-chain',
@ -18,20 +15,9 @@ import * as RTLActions from '../../store/rtl.actions';
})
export class OnChainComponent implements OnInit, OnDestroy {
public selNode: SelNodeChild = {};
public appConfig: RTLConfiguration;
public addressTypes = [];
public flgLoadingWallet: Boolean | 'error' = true;
public selectedAddress: AddressType = {};
public blockchainBalance: Balance = {};
public information: GetInfo = {};
public newAddress = '';
public transaction: ChannelsTransaction = {};
public transTypes = [{id: '1', name: 'Target Confirmation Blocks'}, {id: '2', name: 'Fee'}];
public selTransType = '1';
public flgCustomAmount = '1';
faExchangeAlt = faExchangeAlt;
faChartPie = faChartPie;
balances = [{title: 'Total Balance', dataValue: 0}, {title: 'Confirmed', dataValue: 0}, {title: 'Unconfirmed', dataValue: 0}];
public faExchangeAlt = faExchangeAlt;
public faChartPie = faChartPie;
public balances = [{title: 'Total Balance', dataValue: 0}, {title: 'Confirmed', dataValue: 0}, {title: 'Unconfirmed', dataValue: 0}];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private store: Store<fromRTLReducer.RTLState>, private actions$: Actions) {}
@ -40,27 +26,8 @@ export class OnChainComponent implements OnInit, OnDestroy {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[1]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchBalance/blockchain') {
this.flgLoadingWallet = 'error';
}
});
this.selNode = rtlStore.nodeSettings;
this.information = rtlStore.information;
this.blockchainBalance = rtlStore.blockchainBalance;
if (undefined === this.blockchainBalance.total_balance) {
this.blockchainBalance.total_balance = 0;
}
if (undefined === this.blockchainBalance.confirmed_balance) {
this.blockchainBalance.confirmed_balance = 0;
}
if (undefined === this.blockchainBalance.unconfirmed_balance) {
this.blockchainBalance.unconfirmed_balance = 0;
}
this.balances = [{title: 'Total Balance', dataValue: this.blockchainBalance.total_balance}, {title: 'Confirmed', dataValue: this.blockchainBalance.confirmed_balance}, {title: 'Unconfirmed', dataValue: this.blockchainBalance.unconfirmed_balance}];
if (this.flgLoadingWallet !== 'error') {
this.flgLoadingWallet = false;
}
this.balances = [{title: 'Total Balance', dataValue: rtlStore.blockchainBalance.total_balance || 0}, {title: 'Confirmed', dataValue: rtlStore.blockchainBalance.confirmed_balance}, {title: 'Unconfirmed', dataValue: rtlStore.blockchainBalance.unconfirmed_balance}];
});
}

View File

@ -7,13 +7,13 @@ import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { Channel } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';
import { SelNodeChild } from '../../../../shared/models/RTLconfig';
import { Channel } from '../../../../shared/models/lndModels';
import { LoggerService } from '../../../../shared/services/logger.service';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { RTLEffects } from '../../../../store/rtl.effects';
import * as RTLActions from '../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channel-backup',

View File

@ -0,0 +1,56 @@
<div fxLayout="column" fxFlex="100" fxLayout.gt-sm="row wrap" fxLayoutAlign="start start" fxLayoutAlign.gt-sm="space-between center">
<mat-form-field fxFlex="45" fxLayoutAlign="start end">
<mat-select [(ngModel)]="selectedPeer" placeholder="Alias" name="peer_alias" tabindex="1" required name="selPeer" #selPeer="ngModel">
<mat-option (click)="addNewPeer()" [value]="'new'">
ADD PEER
</mat-option>
<mat-option *ngFor="let peer of peers" [value]="peer.pub_key">
{{peer.alias}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="25" fxLayoutAlign="start end">
<input matInput [(ngModel)]="fundingAmount" placeholder="Amount" type="number" step="1000" min="1" tabindex="2" required name="amount" #amount="ngModel">
<mat-hint>(Wallet Bal: {{totalBalance}}, Remaining Bal: {{totalBalance - ((fundingAmount) ? fundingAmount : 0)}})</mat-hint>
<span matSuffix> {{information?.smaller_currency_unit | titlecase}} </span>
</mat-form-field>
<div fxFlex="15" fxLayoutAlign="start center">
<mat-slide-toggle tabindex="3" color="primary" [(ngModel)]="isPrivate" name="isPrivate">Private Channel</mat-slide-toggle>
</div>
<div fxFlex="15" fxLayoutAlign="start center">
<button fxLayoutAlign="center center" mat-stroked-button color="primary" type="reset" (click)="onShowAdvanced()" tabindex="4">
<p *ngIf="!showAdvanced; else hideAdvancedText">Show Advanced</p>
<ng-template #hideAdvancedText><p>Hide Advanced</p></ng-template>
</button>
</div>
<div *ngIf="showAdvanced" fxLayout="column" fxLayout.gt-sm="row wrap" fxFlex="75" fxLayoutAlign="start start" fxLayoutAlign.gt-sm="space-between center">
<mat-form-field fxFlex="33" fxLayoutAlign="start end">
<mat-select tabindex="5" [(value)]="selTransType">
<mat-option *ngFor="let transType of transTypes" [value]="transType.id">
{{transType.name}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="33" *ngIf="selTransType=='0'">
<input matInput placeholder="Channel Opening Priority" disabled>
</mat-form-field>
<mat-form-field fxFlex="33" *ngIf="selTransType=='1'">
<input matInput [(ngModel)]="transTypeValue.blocks" placeholder="Target Confirmation Blocks" type="number" name="blocks" step="1" min="0" required tabindex="7" #blocks="ngModel">
</mat-form-field>
<mat-form-field fxFlex="33" *ngIf="selTransType=='2'">
<input matInput [(ngModel)]="transTypeValue.fees" placeholder="Fee ({{information?.smaller_currency_unit}}/Byte)" type="number" name="fees" step="1" min="0" required tabindex="8" #fees="ngModel">
</mat-form-field>
<div fxFlex="34" fxLayoutAlign="start center">
<mat-slide-toggle tabindex="9" color="primary" [(ngModel)]="spendUnconfirmed" name="spendUnconfirmed">Spend Unconfirmed Output</mat-slide-toggle>
</div>
</div>
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxFlex="30" fxLayoutAlign="start start" fxLayoutAlign.gt-sm="space-between start">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="10" type="reset" (click)="resetData()">Clear</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onOpenChannel()" [disabled]="selectedPeer === '' || fundingAmount == null || (totalBalance - ((fundingAmount) ? fundingAmount : 0) < 0)" type="submit" tabindex="11">
<p *ngIf="(selectedPeer === '' || fundingAmount == null) && (selPeer.touched || selPeer.dirty) && (amount.touched || amount.dirty); else openText">Invalid Values</p>
<ng-template #openText><p>Open Channel</p></ng-template>
</button>
</div>
<rtl-channels-tables fxLayout="row" fxFlex="100"></rtl-channels-tables>
</div>

View File

@ -5,13 +5,13 @@ import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort } from '@angular/material';
import { Channel, Peer, GetInfo } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';
import { Channel, Peer, GetInfo } from '../../../../shared/models/lndModels';
import { LoggerService } from '../../../../shared/services/logger.service';
import { LNDEffects } from '../../store/lnd.effects';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { LNDEffects } from '../../../store/lnd.effects';
import { RTLEffects } from '../../../../store/rtl.effects';
import * as RTLActions from '../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channel-manage',
@ -36,7 +36,7 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
public transTypeValue = {blocks: '', fees: ''};
public spendUnconfirmed = false;
public isPrivate = false;
public moreOptions = false;
public showAdvanced = false;
public flgSticky = false;
public redirectedWithPeer = false;
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
@ -97,7 +97,7 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
});
}
onOpenChannel(form: any) {
onOpenChannel() {
this.store.dispatch(new RTLActions.OpenSpinner('Opening Channel...'));
let transTypeValue = '0';
if (this.selTransType === '1') {
@ -236,7 +236,7 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
resetData() {
this.selectedPeer = '';
this.fundingAmount = 0;
this.moreOptions = false;
this.showAdvanced = false;
this.spendUnconfirmed = false;
this.isPrivate = false;
this.selTransType = '0';
@ -244,14 +244,19 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
this.redirectedWithPeer = false;
}
onMoreOptionsChange(event: any) {
if (!event.checked) {
onShowAdvanced() {
this.showAdvanced = !this.showAdvanced;
if (!this.showAdvanced) {
this.spendUnconfirmed = false;
this.isPrivate = false;
this.selTransType = '0';
this.transTypeValue = {blocks: '', fees: ''};
}
}
}
addNewPeer() {
console.warn('ADD NEW PEER' + this.selectedPeer);
}
ngOnDestroy() {
this.unsub.forEach(completeSub => {

View File

@ -7,14 +7,14 @@ import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { Channel } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';
import { SelNodeChild } from '../../../../shared/models/RTLconfig';
import { Channel } from '../../../../shared/models/lndModels';
import { LoggerService } from '../../../../shared/services/logger.service';
import { LNDEffects } from '../../../lnd/store/lnd.effects';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { LNDEffects } from '../../../store/lnd.effects';
import { RTLEffects } from '../../../../store/rtl.effects';
import * as RTLActions from '../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channel-restore',

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChannelClosedTableComponent } from './channel-closed-table.component';
describe('ChannelClosedTableComponent', () => {
let component: ChannelClosedTableComponent;
let fixture: ComponentFixture<ChannelClosedTableComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChannelClosedTableComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChannelClosedTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -5,19 +5,19 @@ import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { ClosedChannel } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';
import { ClosedChannel } from '../../../../../shared/models/lndModels';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { RTLEffects } from '../../../../../store/rtl.effects';
import * as RTLActions from '../../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channel-closed',
templateUrl: './channel-closed.component.html',
styleUrls: ['./channel-closed.component.scss']
selector: 'rtl-channel-closed-table',
templateUrl: './channel-closed-table.component.html',
styleUrls: ['./channel-closed-table.component.scss']
})
export class ChannelClosedComponent implements OnInit, OnDestroy {
export class ChannelClosedTableComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public displayedColumns = [];
public closedChannels: any;

View File

@ -0,0 +1,54 @@
<div fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-2">
<div fxFlex="70"></div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="channels" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="remote_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Peer </th>
<td mat-cell *matCellDef="let channel">
<span *ngIf="channel.active" class="green-dot"></span>
<span *ngIf="!channel.active" class="yellow-dot"></span>
{{channel.remote_alias}}
</td>
</ng-container>
<ng-container matColumnDef="total_satoshis_sent">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Sent ({{information?.smaller_currency_unit}}) </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">{{channel.total_satoshis_sent | number}} </span></td>
</ng-container>
<ng-container matColumnDef="total_satoshis_received">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Received ({{information?.smaller_currency_unit}}) </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">{{channel.total_satoshis_received | number}} </span></td>
</ng-container>
<ng-container matColumnDef="capacity">
<th mat-header-cell *matHeaderCellDef>Capacity</th>
<td mat-cell *matCellDef="let channel">
<div fxLayout="row">
<mat-hint fxFlex="50" fxLayoutAlign="start center"><strong>Local: </strong>{{channel.local_balance || 0 | number}} {{information?.smaller_currency_unit}}</mat-hint>
<mat-hint fxFlex="50" fxLayoutAlign="end center"><strong>Remote: </strong>{{channel.remote_balance || 0 | number}} {{information?.smaller_currency_unit}}</mat-hint>
</div>
<mat-progress-bar mode="determinate" value="{{channel.local_balance && channel.local_balance > 0 ? ((+channel.local_balance/((+channel.local_balance)+(+channel.remote_balance)))*100) : 0}}"></mat-progress-bar>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="pr-3"><span fxLayoutAlign="end center">Actions</span></th>
<td mat-cell *matCellDef="let channel" fxLayoutAlign="end center">
<div fxFlex="100" class="bordered-box table-actions-select" fxLayoutAlign="center center">
<mat-select placeholder="Actions" tabindex="1" class="mr-0">
<mat-select-trigger></mat-select-trigger>
<mat-option (click)="onChannelClick(channel, $event)">View Info</mat-option>
<mat-option (click)="onChannelUpdate(channel)">Update Fee Policy</mat-option>
<mat-option (click)="onChannelClose(channel)">Close Channel</mat-option>
</mat-select>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</div>

View File

@ -0,0 +1,11 @@
.mat-column-capacity {
padding-left: 2rem;
padding-right: 2rem;
flex: 0 0 40%;
width: 40%;
}
.mat-column-total_satoshis_sent, .mat-column-total_satoshis_received {
flex: 0 0 10%;
width: 10%;
}

View File

@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ListTransactionsComponent } from './list-transactions.component';
import { ChannelOpenTableComponent } from './channel-open-table.component';
describe('ListTransactionsComponent', () => {
let component: ListTransactionsComponent;
let fixture: ComponentFixture<ListTransactionsComponent>;
describe('ChannelOpenTableComponent', () => {
let component: ChannelOpenTableComponent;
let fixture: ComponentFixture<ChannelOpenTableComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ListTransactionsComponent ]
declarations: [ ChannelOpenTableComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ListTransactionsComponent);
fixture = TestBed.createComponent(ChannelOpenTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -0,0 +1,206 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort } from '@angular/material';
import { Channel, GetInfo } from '../../../../../shared/models/lndModels';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { LNDEffects } from '../../../../store/lnd.effects';
import { RTLEffects } from '../../../../../store/rtl.effects';
import * as RTLActions from '../../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channel-open-table',
templateUrl: './channel-open-table.component.html',
styleUrls: ['./channel-open-table.component.scss']
})
export class ChannelOpenTableComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public totalBalance = 0;
public displayedColumns = [];
public channels: any;
public information: GetInfo = {};
public flgLoading: Array<Boolean | 'error'> = [true];
public selectedFilter = '';
public selFilter = '';
public flgSticky = false;
public myChanPolicy: any = {};
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private lndEffects: LNDEffects) {
switch (true) {
case (window.innerWidth <= 415):
this.displayedColumns = ['remote_alias', 'capacity', 'actions'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'actions'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'capacity', 'actions'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'capacity', 'actions'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'capacity', 'actions'];
break;
}
}
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unsub[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchChannels/all') {
this.flgLoading[0] = 'error';
}
});
this.information = rtlStore.information;
this.totalBalance = +rtlStore.blockchainBalance.total_balance;
if (undefined !== rtlStore.allChannels) {
this.loadChannelsTable(rtlStore.allChannels);
}
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== rtlStore.allChannels) ? false : true;
}
this.logger.info(rtlStore);
});
}
onChannelUpdate(channelToUpdate: any) {
if (channelToUpdate === 'all') {
const titleMsg = 'Updated Values for ALL Channels';
const confirmationMsg = {};
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: 'CONFIRM', titleMessage: titleMsg, noBtnText: 'Cancel', yesBtnText: 'Update', message: JSON.stringify(confirmationMsg), flgShowInput: true, getInputs: [
{placeholder: 'Base Fee msat', inputType: 'number', inputValue: 1000},
{placeholder: 'Fee Rate mili msat', inputType: 'number', inputValue: 1, min: 1},
{placeholder: 'Time Lock Delta', inputType: 'number', inputValue: 144}
]
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[2]))
.subscribe(confirmRes => {
if (confirmRes) {
const base_fee = confirmRes[0].inputValue;
const fee_rate = confirmRes[1].inputValue;
const time_lock_delta = confirmRes[2].inputValue;
this.store.dispatch(new RTLActions.OpenSpinner('Updating Channel Policy...'));
this.store.dispatch(new RTLActions.UpdateChannels({baseFeeMsat: base_fee, feeRate: fee_rate, timeLockDelta: time_lock_delta, chanPoint: 'all'}));
}
});
} else {
this.myChanPolicy = {fee_base_msat: 0, fee_rate_milli_msat: 0, time_lock_delta: 0};
this.store.dispatch(new RTLActions.OpenSpinner('Fetching Channel Policy...'));
this.store.dispatch(new RTLActions.ChannelLookup(channelToUpdate.chan_id.toString()));
this.lndEffects.setLookup
.pipe(takeUntil(this.unsub[3]))
.subscribe(resLookup => {
this.logger.info(resLookup);
if (resLookup.node1_pub === this.information.identity_pubkey) {
this.myChanPolicy = resLookup.node1_policy;
} else if (resLookup.node2_pub === this.information.identity_pubkey) {
this.myChanPolicy = resLookup.node2_policy;
} else {
this.myChanPolicy = {fee_base_msat: 0, fee_rate_milli_msat: 0, time_lock_delta: 0};
}
this.logger.info(this.myChanPolicy);
this.store.dispatch(new RTLActions.CloseSpinner());
const titleMsg = 'Updated Values for Channel Point: ' + channelToUpdate.channel_point;
const confirmationMsg = {};
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: 'CONFIRM', titleMessage: titleMsg, noBtnText: 'Cancel', yesBtnText: 'Update', message: JSON.stringify(confirmationMsg), flgShowInput: true, getInputs: [
{placeholder: 'Base Fee msat', inputType: 'number', inputValue: (this.myChanPolicy.fee_base_msat === '') ? 0 : this.myChanPolicy.fee_base_msat},
{placeholder: 'Fee Rate mili msat', inputType: 'number', inputValue: this.myChanPolicy.fee_rate_milli_msat, min: 1},
{placeholder: 'Time Lock Delta', inputType: 'number', inputValue: this.myChanPolicy.time_lock_delta}
]
}}));
});
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[2]))
.subscribe(confirmRes => {
if (confirmRes) {
const base_fee = confirmRes[0].inputValue;
const fee_rate = confirmRes[1].inputValue;
const time_lock_delta = confirmRes[2].inputValue;
this.store.dispatch(new RTLActions.OpenSpinner('Updating Channel Policy...'));
this.store.dispatch(new RTLActions.UpdateChannels({baseFeeMsat: base_fee, feeRate: fee_rate, timeLockDelta: time_lock_delta, chanPoint: channelToUpdate.channel_point}));
}
});
}
this.applyFilter();
}
onChannelClose(channelToClose: Channel) {
this.store.dispatch(new RTLActions.OpenConfirmation({
width: '70%', data: { type: 'CONFIRM', titleMessage: 'Closing channel: ' + channelToClose.chan_id, noBtnText: 'Cancel', yesBtnText: 'Close Channel'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[1]))
.subscribe(confirmRes => {
if (confirmRes) {
this.store.dispatch(new RTLActions.OpenSpinner('Closing Channel...'));
this.store.dispatch(new RTLActions.CloseChannel({channelPoint: channelToClose.channel_point, forcibly: !channelToClose.active}));
}
});
}
applyFilter() {
this.selectedFilter = this.selFilter;
this.channels.filter = this.selFilter;
}
onChannelClick(selRow: Channel, event: any) {
console.warn(selRow.local_balance && selRow.local_balance > 0 ? ((+selRow.local_balance/(selRow.local_balance+selRow.remote_balance))*100) : 0);
const flgCloseClicked =
event.target.className.includes('mat-column-close')
|| event.target.className.includes('mat-column-update')
|| event.target.className.includes('mat-icon');
if (flgCloseClicked) {
return;
}
const selChannel = this.channels.data.filter(channel => {
return channel.chan_id === selRow.chan_id;
})[0];
const reorderedChannel = JSON.parse(JSON.stringify(selChannel, [
'active', 'remote_pubkey', 'remote_alias', 'channel_point', 'chan_id', 'capacity', 'local_balance', 'remote_balance', 'commit_fee', 'commit_weight',
'fee_per_kw', 'unsettled_balance', 'total_satoshis_sent', 'total_satoshis_received', 'num_updates', 'pending_htlcs', 'csv_delay', 'private'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}}));
}
loadChannelsTable(channels) {
channels.sort(function(a, b) {
return (a.active === b.active) ? 0 : ((b.active) ? 1 : -1);
});
this.channels = new MatTableDataSource<Channel>([...channels]);
this.channels.sort = this.sort;
this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.active) ? 'active' : 'inactive') + (channel.chan_id ? channel.chan_id : '') +
(channel.remote_pubkey ? channel.remote_pubkey : '') + (channel.remote_alias ? channel.remote_alias : '') +
(channel.capacity ? channel.capacity : '') + (channel.local_balance ? channel.local_balance : '') +
(channel.remote_balance ? channel.remote_balance : '') + (channel.total_satoshis_sent ? channel.total_satoshis_sent : '') +
(channel.total_satoshis_received ? channel.total_satoshis_received : '') + (channel.commit_fee ? channel.commit_fee : '') +
(channel.private ? 'private' : 'public');
return newChannel.includes(fltr);
};
this.logger.info(this.channels);
}
ngOnDestroy() {
this.unsub.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChannelPendingTableComponent } from './channel-pending-table.component';
describe('ChannelPendingTableComponent', () => {
let component: ChannelPendingTableComponent;
let fixture: ComponentFixture<ChannelPendingTableComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChannelPendingTableComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChannelPendingTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -4,20 +4,20 @@ import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort } from '@angular/material';
import { Channel, GetInfo, PendingChannels } from '../../../shared/models/lndModels';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { LoggerService } from '../../../shared/services/logger.service';
import { Channel, GetInfo, PendingChannels } from '../../../../../shared/models/lndModels';
import { SelNodeChild } from '../../../../../shared/models/RTLconfig';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { RTLEffects } from '../../../../../store/rtl.effects';
import * as RTLActions from '../../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channel-pending',
templateUrl: './channel-pending.component.html',
styleUrls: ['./channel-pending.component.scss']
selector: 'rtl-channel-pending-table',
templateUrl: './channel-pending-table.component.html',
styleUrls: ['./channel-pending-table.component.scss']
})
export class ChannelPendingComponent implements OnInit, OnDestroy {
export class ChannelPendingTableComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public selNode: SelNodeChild = {};
public selectedFilter = 0;

View File

@ -0,0 +1,22 @@
<div fxLayout="column" fxFlex="100" class="mt-2 bordered-box">
<mat-tab-group>
<mat-tab>
<ng-template mat-tab-label>
<span matBadge="{{openChannels}}" matBadgeColor="primary" matBadgeOverlap="false" class="tab-badge">Open</span>
</ng-template>
<rtl-channel-open-table></rtl-channel-open-table>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<span matBadge="{{pendingChannels}}" matBadgeColor="primary" matBadgeOverlap="false" class="tab-badge">Pending</span>
</ng-template>
<rtl-channel-pending-table></rtl-channel-pending-table>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<span matBadge="{{closedChannels}}" matBadgeColor="primary" matBadgeOverlap="false" class="tab-badge">Closed</span>
</ng-template>
<rtl-channel-closed-table></rtl-channel-closed-table>
</mat-tab>
</mat-tab-group>
</div>

View File

@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChannelPendingComponent } from './channel-pending.component';
import { ChannelsTablesComponent } from './channels-tables.component';
describe('ChannelPendingComponent', () => {
let component: ChannelPendingComponent;
let fixture: ComponentFixture<ChannelPendingComponent>;
describe('ChannelsTablesComponent', () => {
let component: ChannelsTablesComponent;
let fixture: ComponentFixture<ChannelsTablesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChannelPendingComponent ]
declarations: [ ChannelsTablesComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChannelPendingComponent);
fixture = TestBed.createComponent(ChannelsTablesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -0,0 +1,39 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { LoggerService } from '../../../../shared/services/logger.service';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channels-tables',
templateUrl: './channels-tables.component.html',
styleUrls: ['./channels-tables.component.scss']
})
export class ChannelsTablesComponent implements OnInit, OnDestroy {
public openChannels = 0;
public pendingChannels = 0;
public closedChannels = 0;
private unSubs: Array<Subject<void>> = [new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>) {}
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
this.openChannels = (rtlStore.allChannels && rtlStore.allChannels.length) ? rtlStore.allChannels.length : 0;
this.pendingChannels = (rtlStore.numberOfPendingChannels) ? rtlStore.numberOfPendingChannels : 0;
this.closedChannels = (rtlStore.closedChannels && rtlStore.closedChannels.length) ? rtlStore.closedChannels.length : 0;
this.logger.info(rtlStore);
});
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

View File

@ -0,0 +1,35 @@
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faChartPie" class="page-title-img mr-1"></fa-icon>
<span class="page-title">On-chain Balance</span>
</div>
<div fxLayout="column" class="padding-gap-x mb-4">
<mat-card>
<mat-card-content fxLayout="column">
<rtl-currency-unit-converter [values]="balances" [currencyUnits]="selNode.currencyUnits"></rtl-currency-unit-converter>
</mat-card-content>
</mat-card>
</div>
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Connections</span>
</div>
<div fxLayout="column" class="padding-gap-x">
<mat-card>
<mat-card-content fxLayout="column">
<mat-tab-group>
<mat-tab>
<ng-template mat-tab-label>
<span matBadge="{{activeChannels}}" matBadgeColor="primary" matBadgeOverlap="false" class="tab-badge">Channels</span>
</ng-template>
<rtl-channel-manage></rtl-channel-manage>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<span matBadge="{{activePeers}}" matBadgeColor="primary" matBadgeOverlap="false" class="tab-badge">Peers</span>
</ng-template>
<rtl-peers></rtl-peers>
</mat-tab>
</mat-tab-group>
</mat-card-content>
</mat-card>
</div>

View File

@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChannelClosedComponent } from './channel-closed.component';
import { PeersChannelsComponent } from './peers-channels.component';
describe('ChannelClosedComponent', () => {
let component: ChannelClosedComponent;
let fixture: ComponentFixture<ChannelClosedComponent>;
describe('PeersChannelsComponent', () => {
let component: PeersChannelsComponent;
let fixture: ComponentFixture<PeersChannelsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChannelClosedComponent ]
declarations: [ PeersChannelsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChannelClosedComponent);
fixture = TestBed.createComponent(PeersChannelsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -0,0 +1,45 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { faUsers, faChartPie } from '@fortawesome/free-solid-svg-icons';
import { SelNodeChild } from '../../shared/models/RTLconfig';
import * as fromRTLReducer from '../../store/rtl.reducers';
@Component({
selector: 'rtl-peers-channels',
templateUrl: './peers-channels.component.html',
styleUrls: ['./peers-channels.component.scss']
})
export class PeersChannelsComponent implements OnInit, OnDestroy {
public selNode: SelNodeChild = {};
public activePeers = 0;
public activeChannels = 0;
public faUsers = faUsers;
public faChartPie = faChartPie;
public balances = [{title: 'Total Balance', dataValue: 0}, {title: 'Confirmed', dataValue: 0}, {title: 'Unconfirmed', dataValue: 0}];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private store: Store<fromRTLReducer.RTLState>, private actions$: Actions) {}
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[1]))
.subscribe((rtlStore) => {
this.selNode = rtlStore.nodeSettings;
this.activePeers = (rtlStore.peers && rtlStore.peers.length) ? rtlStore.peers.length : 0;
this.activeChannels = rtlStore.numberOfActiveChannels;
this.balances = [{title: 'Total Balance', dataValue: rtlStore.blockchainBalance.total_balance || 0}, {title: 'Confirmed', dataValue: rtlStore.blockchainBalance.confirmed_balance}, {title: 'Unconfirmed', dataValue: rtlStore.blockchainBalance.unconfirmed_balance}];
});
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

View File

@ -7,14 +7,14 @@ import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { Peer, GetInfo } from '../../shared/models/lndModels';
import { LoggerService } from '../../shared/services/logger.service';
import { Peer, GetInfo } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';
import { newlyAddedRowAnimation } from '../../shared/animation/row-animation';
import { LNDEffects } from '../store/lnd.effects';
import { RTLEffects } from '../../store/rtl.effects';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
import { newlyAddedRowAnimation } from '../../../shared/animation/row-animation';
import { LNDEffects } from '../../store/lnd.effects';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-peers',

View File

@ -173,6 +173,7 @@ export class LNDEffects implements OnDestroy {
postRes.value = action.payload.invoiceValue;
postRes.expiry = action.payload.expiry;
postRes.cltv_expiry = '144';
postRes.private = action.payload.private;
postRes.creation_date = Math.round(new Date().getTime() / 1000).toString();
postRes.creation_date_str = new Date(+postRes.creation_date * 1000).toUTCString().substring(5, 22).replace(' ', '/').replace(' ', '/').toUpperCase();
this.logger.info(postRes);

View File

@ -2,7 +2,7 @@
<div class="w-100">
<mat-card-header [ngClass]="msgTypeBackground" fxLayoutAlign="end">
<h2 fxFlex="91">{{data.type}}</h2>
<mat-icon fxFlex="7" fxLayoutAlign="end" type="button" (click)="onClose()" class="cursor-pointer">close</mat-icon>
<mat-icon autoFocus fxFlex="3" fxLayoutAlign="end" type="button" (click)="onClose()" class="cursor-pointer" tabindex="1">close</mat-icon>
</mat-card-header>
<mat-card-content>
<div class="pb-2 p-2 wrap-text new-line">
@ -30,7 +30,7 @@
</div>
<mat-divider class="pb-1"></mat-divider>
<div fxLayoutAlign="center">
<button mat-raised-button [color]="msgTypeForeground" fxFlex="30" class="mb-1" type="button" [mat-dialog-close]="false" default>OK</button>
<button mat-raised-button [color]="msgTypeForeground" fxFlex="30" class="mb-1" type="button" [mat-dialog-close]="false" tabindex="2" default>OK</button>
</div>
</mat-card-content>
</div>

View File

@ -2,8 +2,8 @@ import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { faCopy } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../../shared/services/logger.service';
import { AlertData } from '../../../shared/models/alertData';
import { LoggerService } from '../../../services/logger.service';
import { AlertData } from '../../../models/alertData';
@Component({
selector: 'rtl-alert-message',
@ -27,7 +27,7 @@ export class AlertMessageComponent implements OnInit {
setStyleOnAlertType() {
// INFO/WARN/ERROR/SUCCESS/CONFIRM
if (this.data.type === 'WARN') {
this.msgTypeBackground = 'primary p-1';
this.msgTypeBackground = 'bg-primary p-1';
this.msgTypeForeground = 'primary';
}
if (this.data.type === 'ERROR') {

View File

@ -2,7 +2,7 @@
<div class="w-100">
<mat-card-header [ngClass]="msgTypeBackground" fxLayoutAlign="end">
<h2 fxFlex="91">{{data.type}}</h2>
<mat-icon fxFlex="7" fxLayoutAlign="end" type="button" (click)="onClose(false)" class="cursor-pointer">close</mat-icon>
<mat-icon autoFocus fxFlex="3" fxLayoutAlign="end" type="button" (click)="onClose(false)" class="cursor-pointer" tabindex="1">close</mat-icon>
</mat-card-header>
<mat-card-content>
<div class="pb-2 p-2 wrap-text new-line">
@ -31,9 +31,9 @@
</div>
<mat-divider class="pb-1"></mat-divider>
<div fxLayoutAlign="center">
<button mat-stroked-button color="primary" fxFlex="20" type="button" fxLayoutAlign="center center" class="mr-2" (click)="onClose(false)" default>{{noBtnText}}</button>
<button *ngIf="flgShowInput" mat-raised-button [color]="msgTypeForeground" fxLayoutAlign="center center" fxFlex="20" type="button" (click)="onClose(getInputs)" [disabled]="!getInputs[0].inputValue">{{yesBtnText}}</button>
<button *ngIf="!flgShowInput" mat-raised-button [color]="msgTypeForeground" fxLayoutAlign="center center" fxFlex="20" type="button" (click)="onClose(true)">{{yesBtnText}}</button>
<button mat-stroked-button color="primary" fxFlex="20" type="button" fxLayoutAlign="center center" class="mr-2" (click)="onClose(false)" tabindex="2" default>{{noBtnText}}</button>
<button *ngIf="flgShowInput" mat-raised-button [color]="msgTypeForeground" fxLayoutAlign="center center" fxFlex="20" type="button" tabindex="3" (click)="onClose(getInputs)" [disabled]="!getInputs[0].inputValue">{{yesBtnText}}</button>
<button *ngIf="!flgShowInput" mat-raised-button [color]="msgTypeForeground" fxLayoutAlign="center center" fxFlex="20" type="button" tabindex="4" (click)="onClose(true)">{{yesBtnText}}</button>
</div>
</mat-card-content>
</div>

View File

@ -3,11 +3,11 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Store } from '@ngrx/store';
import { faCopy } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../../shared/services/logger.service';
import { AlertData, InputData } from '../../../shared/models/alertData';
import { LoggerService } from '../../../services/logger.service';
import { AlertData, InputData } from '../../../models/alertData';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import * as RTLActions from '../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
@Component({
selector: 'rtl-confirmation-message',
@ -36,7 +36,7 @@ export class ConfirmationMessageComponent implements OnInit {
// INFO/WARN/ERROR/SUCCESS/CONFIRM
if (this.data.type === 'WARN') {
this.msgTypeBackground = 'bg-accent p-1';
this.msgTypeBackground = 'bg-primary p-1';
}
if (this.data.type === 'ERROR') {
this.msgTypeBackground = 'bg-warn p-1';

View File

@ -8,14 +8,14 @@
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Invoice Information</span>
</div>
<mat-icon tabindex="3" fxFlex="5" type="button" fxLayoutAlign="center center" (click)="onClose()" class="cursor-pointer icon-medium">close</mat-icon>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header>
<mat-card-content>
<div fxLayout="column">
<div fxLayout="row">
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Amount Requested</h4>
<span class="foreground-secondary-text">{{(invoice.value || 0) | number}} Sats</span>
<span class="foreground-secondary-text">{{(invoice.value || 0) | number}} Sats<ng-container *ngIf="!invoice.value"> (Open Amount) </ng-container></span>
</div>
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Memo</h4>
@ -57,14 +57,18 @@
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="50">
<div fxFlex="34">
<h4 fxLayoutAlign="start" class="font-bold-500">Expiry</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.expiry}}</span>
</div>
<div fxFlex="50">
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">CLTV Expiry</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.cltv_expiry}}</span>
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">Private Routing Hints</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.private ? 'Yes' : 'No'}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
</div>

View File

@ -8,7 +8,7 @@
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Generated Address</span>
</div>
<mat-icon tabindex="3" fxFlex="5" type="button" fxLayoutAlign="center center" (click)="onClose()" class="cursor-pointer icon-medium">close</mat-icon>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header>
<mat-card-content>
<div fxLayout="column">

View File

@ -136,6 +136,11 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
onShowData(node: MenuChildNode) {
console.warn(node);
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'WARN',
titleMessage: node.name,
message: JSON.stringify(node)
}}}));
}
onNodeSelectionChange(selNodeValue: LightningNode) {

View File

@ -5,8 +5,8 @@ export const CURRENCY_UNIT_FORMATS = { Sats: '1.0-0', BTC: '1.6-6', OTHER: '1.2-
export const TIME_UNITS = ['SECS', 'MINS', 'HOURS', 'DAYS'];
export const ADDRESS_TYPES = [
{ addressId: '0', addressTp: 'p2wkh', addressDetails: 'Pay to witness key hash'},
{ addressId: '1', addressTp: 'np2wkh', addressDetails: 'Pay to nested witness key hash (default)'}
{ addressId: '0', addressTp: 'Bech32 (P2WKH)', addressDetails: 'Pay to witness key hash'},
{ addressId: '1', addressTp: 'P2SH (NP2WKH)', addressDetails: 'Pay to nested witness key hash (default)'}
];
export enum AuthenticateWith {

View File

@ -4,11 +4,11 @@ export const MENU_DATA: MenuRootNode = {
LNDChildren: [
{id: 1, parentId: 0, name: 'Dashboard', iconType: 'FA', icon: faTachometerAlt, link: '/lnd/home'},
{id: 2, parentId: 0, name: 'On-chain', iconType: 'FA', icon: faLink, link: '/lnd/onchain'},
{id: 3, parentId: 0, name: 'Lightning', iconType: 'FA', icon: faBolt, link: '/lnd/chnlmanage', children: [
{id: 31, parentId: 3, name: 'Peers/Channels', iconType: 'FA', icon: faUsers, link: '/lnd/chnlpending'},
{id: 3, parentId: 0, name: 'Lightning', iconType: 'FA', icon: faBolt, link: '/lnd/peerschannels', children: [
{id: 31, parentId: 3, name: 'Peers/Channels', iconType: 'FA', icon: faUsers, link: '/lnd/peerschannels'},
{id: 32, parentId: 3, name: 'Transactions', iconType: 'FA', icon: faExchangeAlt, link: '/lnd/transactions'},
{id: 33, parentId: 3, name: 'Lookup', iconType: 'FA', icon: faSearch, link: '/lnd/chnlclosed'},
{id: 34, parentId: 3, name: 'Routing', iconType: 'FA', icon: faProjectDiagram, link: '/lnd/chnlbackup'}
{id: 33, parentId: 3, name: 'Lookup', iconType: 'FA', icon: faSearch, link: '/lnd/lookups'},
{id: 34, parentId: 3, name: 'Routing', iconType: 'FA', icon: faProjectDiagram, link: '/lnd/routingpeers'}
]},
{id: 4, parentId: 0, name: 'Advanced', iconType: 'FA', icon: faCog, link: '/sconfig'},
{id: 5, parentId: 0, name: 'Settings', iconType: 'FA', icon: faTools, link: '/settings'},

View File

@ -19,9 +19,9 @@ import { DecimalPipe } from '@angular/common';
import { InvoiceInformationComponent } from './components/data-modal/invoice-information/invoice-information.component';
import { OnChainGeneratedAddressComponent } from './components/data-modal/on-chain-generated-address/on-chain-generated-address.component';
import { AppSettingsComponent } from './components/app-settings/app-settings.component';
import { AlertMessageComponent } from './components/alert-message/alert-message.component';
import { ConfirmationMessageComponent } from './components/confirmation-message/confirmation-message.component';
import { SpinnerDialogComponent } from './components/spinner-dialog/spinner-dialog.component';
import { AlertMessageComponent } from './components/data-modal/alert-message/alert-message.component';
import { ConfirmationMessageComponent } from './components/data-modal/confirmation-message/confirmation-message.component';
import { SpinnerDialogComponent } from './components/data-modal/spinner-dialog/spinner-dialog.component';
import { NotFoundComponent } from './components/not-found/not-found.component';
import { SigninComponent } from './components/signin/signin.component';
import { HelpComponent } from './components/help/help.component';
@ -162,7 +162,7 @@ import { CommonService } from './services/common.service';
],
providers: [
{ provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { hasBackdrop: true, autoFocus: true, disableClose: true, role: 'dialog', width: '700px' } },
{ provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: { duration: 3000, verticalPosition: 'bottom', panelClass: 'rtl-snack-bar' } },
{ provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: { duration: 2000, verticalPosition: 'bottom', panelClass: 'rtl-snack-bar' } },
CommonService, DecimalPipe
]
})

View File

@ -61,9 +61,6 @@
.icon-large {
font-size: $small-font-size * 5;
}
.icon-medium {
font-size: $small-font-size * 2 !important;
}
.icon-small {
font-size: $small-font-size * 1.5 !important;
}
@ -76,6 +73,12 @@
.mat-icon-36 {
font-size: $small-font-size;
}
.btn-close-x {
font-size: $small-font-size * 1.5;
font-weight: 600;
min-width: 3.6rem;
max-width: 3.6rem;
}
}
&.regular-font {
.mat-header-cell {
@ -139,9 +142,6 @@
.icon-large {
font-size: $regular-font-size * 5;
}
.icon-medium {
font-size: $regular-font-size * 2.2 !important;
}
.icon-small {
font-size: $regular-font-size * 1.5 !important;
}
@ -154,6 +154,12 @@
.mat-icon-36 {
font-size: $regular-font-size;
}
.btn-close-x {
font-size: $regular-font-size * 1.5;
font-weight: 600;
min-width: 3.6rem;
max-width: 3.6rem;
}
}
&.large-font {
.mat-header-cell {
@ -212,9 +218,6 @@
.icon-large {
font-size: $large-font-size * 5;
}
.icon-medium {
font-size: $large-font-size * 2.2 !important;
}
.icon-small {
font-size: $large-font-size * 1.5 !important;
}
@ -227,11 +230,16 @@
.mat-icon-36 {
font-size: $large-font-size;
}
.btn-close-x {
font-size: $large-font-size * 1.5;
font-weight: 600;
min-width: 3.6rem;
max-width: 3.6rem;
}
}
.icon-medium.mat-icon:focus, .icon-medium.mat-icon:hover {
.mat-icon.material-icons:focus {
outline: none;
@include mat-elevation(1);
}
.mat-raised-button.mat-primary:focus, .mat-raised-button.mat-primary:hover {

View File

@ -216,6 +216,12 @@
}
}
.bordered-box {
border: 1px solid $foreground-divider;
border-radius: 4px;
background: none;
}
.modal-info-header {
color: $foreground-text;
font-weight: 500;
@ -236,4 +242,24 @@
align-items: center;
}
}
.tab-badge {
& .mat-badge-content {
width: $dot-size * 1.5;
height: $dot-size * 1.5;
border-radius: $dot-size * 1.5;
line-height: $dot-size * 1.5;
margin-top: 1.2rem;
font-size: 80%;
font-weight: 500;
}
}
.table-actions-select {
padding: 0.5rem 1rem;
margin: 0.7rem 0;
& .mat-select-placeholder {
color: $foreground-text;
}
}
}

View File

@ -247,6 +247,10 @@ body {
margin-top: 2px !important;
}
.my-2px {
margin: 2px 0 !important;
}
.mt-1 {
margin-top: 1rem !important;
}
@ -259,6 +263,10 @@ body {
margin-left: 1rem !important;
}
.mr-0 {
margin-right: 0 !important;
}
.mr-1 {
margin-right: 1rem !important;
}
@ -359,6 +367,10 @@ body {
padding: 0 !important;
}
.p-5px {
padding: 0.5rem !important;
}
.pl-0 {
padding-left: 0 !important;
}
@ -762,4 +774,4 @@ table {
border-radius: $dot-size;
margin-right: 1rem;
background-color: $yellow-color;
}
}

View File

@ -14,9 +14,9 @@ import { SessionService } from '../shared/services/session.service';
import { Settings, RTLConfiguration } from '../shared/models/RTLconfig';
import { AuthenticateWith, CURRENCY_UNITS } from '../shared/models/enums';
import { SpinnerDialogComponent } from '../shared/components/spinner-dialog/spinner-dialog.component';
import { AlertMessageComponent } from '../shared/components/alert-message/alert-message.component';
import { ConfirmationMessageComponent } from '../shared/components/confirmation-message/confirmation-message.component';
import { SpinnerDialogComponent } from '../shared/components/data-modal/spinner-dialog/spinner-dialog.component';
import { AlertMessageComponent } from '../shared/components/data-modal/alert-message/alert-message.component';
import { ConfirmationMessageComponent } from '../shared/components/data-modal/confirmation-message/confirmation-message.component';
import * as RTLActions from './rtl.actions';
import * as fromRTLReducer from './rtl.reducers';