Code cleanup for currency convertor

Code cleanup for currency convertor
pull/260/head
Shahana Farooqui 5 years ago
parent 5421631d12
commit 125099fe08

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -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.36940ff719dbed85b186.css"></head>
<link rel="stylesheet" href="styles.6429b7a9527a146e7054.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.cf15072f755a92e0766f.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.17677b43ba5c7b8274d4.js"></script></body>
<script src="runtime.85f0111a60b784d662a7.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.136ca1019950c55334b6.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

@ -1 +1 @@
!function(e){function r(r){for(var n,a,i=r[0],f=r[1],c=r[2],p=0,s=[];p<i.length;p++)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:"ed6f619a753cd468a3f1",7:"3b3d365a0c96df4907d8"}[e]+".js"}(e);var f=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(c);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;f.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",f.name="ChunkLoadError",f.type=n,f.request=u,t[1](f)}o[e]=void 0}};var c=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],f=i.push.bind(i);i.push=r,i=i.slice();for(var c=0;c<i.length;c++)r(i[c]);var l=f;t()}([]);
!function(e){function r(r){for(var n,a,i=r[0],f=r[1],c=r[2],p=0,s=[];p<i.length;p++)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:"6461d7eefa28dc4efa39",7:"84ad670c3bfef8117d18"}[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()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -57,7 +57,7 @@
</button>
</div>
<div fxFlex="10" fxLayoutAlign="end start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="9" type="reset"
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="9" type="reset"
(click)="resetData()">Clear</button>
</div>
</form>

@ -1 +1,2 @@
<router-outlet></router-outlet>
<mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar>
<router-outlet *ngIf="!loading"></router-outlet>

@ -1,4 +1,5 @@
import { Component } from '@angular/core';
import { Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';
@Component({
selector: 'rtl-cl-root',
@ -6,5 +7,25 @@ import { Component } from '@angular/core';
styleUrls: ['./cl-root.component.scss']
})
export class CLRootComponent {
constructor() {}
loading = false;
constructor(private router: Router) {
this.router.events.subscribe((event: Event) => {
switch (true) {
case event instanceof NavigationStart: {
this.loading = true;
break;
}
case event instanceof NavigationEnd:
case event instanceof NavigationCancel:
case event instanceof NavigationError: {
this.loading = false;
break;
}
default: {
break;
}
}
});
}
}

@ -27,7 +27,7 @@
<div fxFlex="30" fxLayoutAlign="space-between stretch">
<button fxFlex="50" fxLayoutAlign="center center" mat-raised-button color="primary"
[disabled]="fhForm.invalid" type="submit" tabindex="3">Fetch</button>
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="accent" class="ml-2" tabindex="4"
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="primary" class="ml-2" tabindex="4"
type="reset" (click)="resetData()">Clear</button>
</div>
</form>

@ -29,7 +29,7 @@
</div>
<button fxFlex="10" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit"
tabindex="5" [disabled]="!addInvoiceForm.valid">Add</button>
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="6" type="reset"
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="6" type="reset"
(click)="resetData()">Clear</button>
<button fxFlex="10" fxLayoutAlign="center center" mat-raised-button color="warn" tabindex="7" type="button"
(click)="onDeleteExpiredInvoices()">Delete Expired</button>

@ -22,7 +22,7 @@
<button fxFlex="90" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="3" type="submit" (click)="onLookup()" [disabled]="!form.valid">Lookup</button>
</div>
<div fxFlex="12" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="4" type="reset" (click)="resetData()">Clear</button>
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="4" type="reset" (click)="resetData()">Clear</button>
</div>
</form>
</mat-card-content>

@ -109,7 +109,7 @@
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="accent" tabindex="3"
<button fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="3"
(click)="resetReceiveData()" class="top-minus-15px">Clear</button>
</div>
</div>
@ -167,7 +167,7 @@
</button>
</div>
<div fxFlex="10" fxLayoutAlign="end start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="9" type="reset"
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="9" type="reset"
(click)="resetData()">Clear</button>
</div>
</form>

@ -30,7 +30,7 @@
</button>
</div>
<div fxFlex="15" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="4" type="reset"
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="4" type="reset"
(click)="resetData()">Clear</button>
</div>
</form>

@ -23,7 +23,7 @@
<p>Send Payment</p>
</ng-template>
</button>
<button fxFlex="48" mat-stroked-button color="accent" type="reset" tabindex="3" type="reset"
<button fxFlex="48" mat-stroked-button color="primary" type="reset" tabindex="3" type="reset"
(click)="resetData()">Clear</button>
</div>
</form>

@ -18,7 +18,7 @@
</button>
</div>
<div fxFlex="15" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="2" type="reset" (click)="resetData()">Clear</button>
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="2" type="reset" (click)="resetData()">Clear</button>
</div>
</form>
</mat-card-content>

@ -49,7 +49,7 @@
</button>
</div>
<div fxFlex="10" fxLayoutAlign="end start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="9" type="reset" (click)="resetData()">Clear</button>
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="9" type="reset" (click)="resetData()">Clear</button>
</div>
</form>
</mat-card-content>

@ -1 +1,2 @@
<router-outlet></router-outlet>
<mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar>
<router-outlet *ngIf="!loading"></router-outlet>

@ -1,4 +1,5 @@
import { Component } from '@angular/core';
import { Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';
@Component({
selector: 'rtl-lnd-root',
@ -6,5 +7,25 @@ import { Component } from '@angular/core';
styleUrls: ['./lnd-root.component.scss']
})
export class LNDRootComponent {
constructor() {}
loading = false;
constructor(private router: Router) {
this.router.events.subscribe((event: Event) => {
switch (true) {
case event instanceof NavigationStart: {
this.loading = true;
break;
}
case event instanceof NavigationEnd:
case event instanceof NavigationCancel:
case event instanceof NavigationError: {
this.loading = false;
break;
}
default: {
break;
}
}
});
}
}

@ -9,6 +9,9 @@ import { HomeComponent } from './home/home.component';
import { PeersComponent } from './peers/peers.component';
import { SendReceiveTransComponent } from './old-transactions/send-receive/send-receive-trans.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 { UnlockLNDComponent } from './unlock-lnd/unlock-lnd.component';
import { LightningPaymentsComponent } from './transactions/payments/lightning-payments.component';
import { ChannelManageComponent } from './channels/channel-manage/channel-manage.component';
@ -27,6 +30,7 @@ import { QueryRoutesComponent } from './payments/query-routes/query-routes.compo
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';
@NgModule({
imports: [
@ -54,7 +58,11 @@ import { LNDUnlockedGuard } from '../shared/services/auth.guard';
NodeLookupComponent,
ChannelBackupComponent,
QueryRoutesComponent,
ChannelRestoreComponent
ChannelRestoreComponent,
OnChainSendComponent,
OnChainReceiveComponent,
OnChainComponent,
OnChainTransactionHistoryComponent
],
providers: [
{ provide: LoggerService, useClass: ConsoleLoggerService },

@ -17,6 +17,7 @@ import { ForwardingHistoryComponent } from './switch/forwarding-history.componen
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 { OnChainComponent } from './on-chain/on-chain.component';
import { AuthGuard, LNDUnlockedGuard } from '../shared/services/auth.guard';
import { NotFoundComponent } from '../shared/components/not-found/not-found.component';
@ -33,13 +34,12 @@ export const LndRoutes: Routes = [
{ path: 'chnlbackup', component: ChannelBackupComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlrestore', component: ChannelRestoreComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'transactions', component: TransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'transsendreceive', component: SendReceiveTransComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'onchain', component: OnChainComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'translist', component: ListTransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'queryroutes', component: QueryRoutesComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'switch', component: ForwardingHistoryComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'routingpeers', component: RoutingPeersComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'lookups', component: LookupsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'onchain', redirectTo: 'transsendreceive' },
{ path: 'forwardinghistory', redirectTo: 'switch' },
{ path: '**', component: NotFoundComponent }
]}

@ -22,7 +22,7 @@
<button fxFlex="90" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="3" type="submit" (click)="onLookup()" [disabled]="!form.valid">Lookup</button>
</div>
<div fxFlex="12" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="4" type="reset" (click)="resetData()">Clear</button>
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="4" type="reset" (click)="resetData()">Clear</button>
</div>
</form>
</mat-card-content>

@ -95,7 +95,7 @@
<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="accent" tabindex="3" (click)="resetReceiveData()" class="top-minus-15px">Clear</button>
<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">
@ -157,7 +157,7 @@
<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="accent" tabindex="9" type="reset" (click)="resetData()">Clear</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>

@ -0,0 +1,15 @@
<div fxLayout="column">
<div fxLayout="row" fxLayoutAlign="space-between end" fxLayoutAlign.gt-sm="start end">
<mat-form-field fxFlex="48" fxFlex.gt-sm="25" fxLayoutAlign="start end">
<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 class="mt-2" fxFlex="48" fxFlex.gt-sm="25">
<button fxFlex="100" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onGenerateAddress()" [disabled]="undefined === selectedAddress.addressId" tabindex="2" class="top-minus-15px">Generate Address</button>
</div>
</div>
<rtl-on-chain-transaction-history fxLayout="row" fxFlex="100"></rtl-on-chain-transaction-history>
</div>

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

@ -0,0 +1,184 @@
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-on-chain-receive',
templateUrl: './on-chain-receive.component.html',
styleUrls: ['./on-chain-receive.component.scss']
})
export class OnChainReceiveComponent 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();
});
}
}

@ -0,0 +1,68 @@
<div fxLayout="column" fxLayout.gt-sm="row wrap">
<div fxFlex="100" class="padding-gap">
<div fxLayout="column" fxLayout.gt-sm="row wrap">
<div fxFlex="58" fxLayoutAlign="start end">
<mat-form-field fxFlex="99">
<input matInput [(ngModel)]="transaction.address" placeholder="Bitcoin Address"
tabindex="1" 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 fxFlex="30" fxLayoutAlign="start end">
<mat-form-field fxFlex="70">
<input matInput [(ngModel)]="transaction.amount" placeholder="Amount" name="amount" type="number" step="100" min="0" tabindex="2" #amount="ngModel">
<span matSuffix> {{selAmountUnit}} </span>
</mat-form-field>
</div>
<mat-form-field fxFlex="10" fxLayoutAlign="start end">
<mat-select [value]="selAmountUnit" tabindex="3" required name="amountUnit" (selectionChange)="onAmountUnitChange($event)">
<mat-option *ngFor="let amountUnit of amountUnits" [value]="amountUnit">{{amountUnit}}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div fxLayout="column" fxLayout.gt-sm="row wrap">
<div fxFlex="30" fxLayoutAlign="start start">
<mat-form-field fxFlex="99">
<mat-select [(value)]="selTransType" tabindex="4">
<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="5" #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="6" #fees="ngModel">
</mat-form-field>
</div>
<div fxFlex="40" fxLayoutAlign="space-between start">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="7"
type="reset" (click)="resetData()">Clear Fields</button>
<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 Funds</p>
</ng-template>
</button>
</div>
</div>
</div>
</div>
<ng-template #withoutData>
<h3>Sats</h3>
</ng-template>

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

@ -0,0 +1,196 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { HttpClient } from '@angular/common/http';
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 { CURRENCY_UNITS } from '../../../shared/models/enums';
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-on-chain-send',
templateUrl: './on-chain-send.component.html',
styleUrls: ['./on-chain-send.component.scss']
})
export class OnChainSendComponent 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';
public amountUnits = CURRENCY_UNITS;
public selAmountUnit = CURRENCY_UNITS[0];
public currConvertorRate = {};
public unitConversionValue = 0;
private unSubs: 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 httpClient: HttpClient) {}
ngOnInit() {
this.store.select('root')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rootStore) => {
this.appConfig = rootStore.appConfig;
this.logger.info(rootStore);
});
}
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.unSubs[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.unSubs[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 = '';
}
onAmountUnitChange(event: any) {
if(this.transaction.amount && this.selAmountUnit !== event.value) {
switch (this.selAmountUnit) {
case this.amountUnits[0]:
switch (event.value) {
case this.amountUnits[1]:
this.transaction.amount = this.transaction.amount * 0.00000001;
break;
case this.amountUnits[2]:
// this.transaction.amount = +this.currencyConvert.transform(this.transaction.amount.toString(), this.currConvertorRate[this.amountUnits[2]].last * 0.00000001);
break;
default:
break;
}
break;
case this.amountUnits[1]:
switch (event.value) {
case this.amountUnits[0]:
this.transaction.amount = this.transaction.amount * 100000000;
break;
case this.amountUnits[2]:
// this.transaction.amount = +this.currencyConvert.transform(this.transaction.amount.toString(), this.currConvertorRate[this.amountUnits[2]].last);
break;
default:
break;
}
break;
case this.amountUnits[2]:
switch (event.value) {
case this.amountUnits[0]:
// this.transaction.amount = +this.currencyConvert.transform(this.transaction.amount.toString(), this.currConvertorRate[this.amountUnits[2]].last) * 10000000;
break;
case this.amountUnits[1]:
// this.transaction.amount = +this.currencyConvert.transform(this.transaction.amount.toString(), this.currConvertorRate[this.amountUnits[2]].last);
break;
default:
break;
}
break;
default:
break;
}
}
this.selAmountUnit = event.value;
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -0,0 +1,42 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start start">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-2 w-100">
<div fxFlex="70">
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Transaction History</span>
</div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div fxLayout="row" fxLayoutAlign="start center" class="w-100">
<div perfectScrollbar class="table-container" fxFlex="100">
<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="time_stamp_str">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date/Time </th>
<td mat-cell *matCellDef="let transaction">{{transaction.time_stamp_str}}</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Amount (Sats) </th>
<td mat-cell *matCellDef="let transaction"><span fxLayoutAlign="end center">{{transaction.amount | number}}</span></td>
</ng-container>
<ng-container matColumnDef="num_confirmations">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Confirmations </th>
<td mat-cell *matCellDef="let transaction"><span fxLayoutAlign="end center">
{{transaction?.num_confirmations | number}} </span></td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="pl-3 pr-3"><span fxLayoutAlign="end center">Actions</span></th>
<td mat-cell *matCellDef="let transaction" class="pl-3">
<button mat-stroked-button color="primary" type="button" tabindex="4"
(click)="onTransactionClick(transaction, $event)">View Info</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" showFirstLastButtons class="mb-4"></mat-paginator>
</div>
</div>
</div>

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

@ -0,0 +1,115 @@
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 { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } 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-on-chain-transaction-history',
templateUrl: './on-chain-transaction-history.component.html',
styleUrls: ['./on-chain-transaction-history.component.scss']
})
export class OnChainTransactionHistoryComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
faHistory = faHistory;
public displayedColumns = [];
public listTransactions: any;
public flgLoading: Array<Boolean | 'error'> = [true];
public flgSticky = false;
public pageSize = 10;
public pageSizeOptions = [5, 10, 25, 100];
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 = ['time_stamp_str', 'amount', 'actions'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['time_stamp_str', 'amount', 'num_confirmations', 'actions'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['time_stamp_str', 'amount', 'num_confirmations', 'actions'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['time_stamp_str', 'amount', 'num_confirmations', 'actions'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['time_stamp_str', 'amount', 'num_confirmations', 'actions'];
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.listTransactions.paginator = this.paginator;
this.logger.info(this.listTransactions);
}
ngOnDestroy() {
this.unsub.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -0,0 +1,32 @@
<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]="faExchangeAlt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">On-chain Transactions</span>
</div>
<div fxLayout="column" class="padding-gap-x">
<mat-card>
<mat-card-content fxLayout="column">
<mat-tab-group>
<mat-tab label="Send">
<rtl-on-chain-send></rtl-on-chain-send>
</mat-tab>
<mat-tab label="Receive">
<rtl-on-chain-receive></rtl-on-chain-receive>
</mat-tab>
<mat-tab label="Sweep All">
<rtl-on-chain-send></rtl-on-chain-send>
</mat-tab>
</mat-tab-group>
</mat-card-content>
</mat-card>
</div>

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

@ -0,0 +1,75 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil, filter } 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',
templateUrl: './on-chain.component.html',
styleUrls: ['./on-chain.component.scss']
})
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}];
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) => {
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;
}
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;
}
});
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -28,7 +28,7 @@
</button>
</div>
<div fxFlex="15" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="4" type="reset"
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="4" type="reset"
(click)="resetData()">Clear</button>
</div>
</form>

@ -18,7 +18,7 @@
</button>
</div>
<div fxFlex="15" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="2" type="reset" (click)="resetData()">Clear</button>
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="2" type="reset" (click)="resetData()">Clear</button>
</div>
</form>
</mat-card-content>

@ -27,7 +27,7 @@
<div fxFlex="30" fxLayoutAlign="space-between stretch">
<button fxFlex="50" fxLayoutAlign="center center" mat-raised-button color="primary"
[disabled]="rpForm.invalid" type="submit" tabindex="3">Fetch</button>
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="accent" class="ml-2" tabindex="4"
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="primary" class="ml-2" tabindex="4"
type="reset" (click)="resetData()">Clear</button>
</div>
</form>

@ -6,14 +6,14 @@ import { Actions, Effect, ofType } from '@ngrx/effects';
import { of, Subject } from 'rxjs';
import { map, mergeMap, catchError, withLatestFrom } from 'rxjs/operators';
import { Location } from '@angular/common';
import { MatDialog } from '@angular/material';
import { environment, API_URL } from '../../../environments/environment';
import { InvoiceInformationComponent } from '../../shared/components/invoice-information/invoice-information.component';
import { LoggerService } from '../../shared/services/logger.service';
import { SessionService } from '../../shared/services/session.service';
import { GetInfo, GetInfoChain, Fees, Balance, NetworkInfo, Payment, GraphNode, Transaction, SwitchReq, ListInvoices } from '../../shared/models/lndModels';
import { CurrencyUnitEnum } from '../../shared/models/enums';
import { InvoiceInformationComponent } from '../../shared/components/invoice-information/invoice-information.component';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
@ -599,9 +599,9 @@ export class LNDEffects implements OnDestroy {
} else {
const confirmationMsg = { 'Destination': action.payload[1].destination, 'Timestamp': action.payload[1].timestamp_str, 'Expiry': action.payload[1].expiry };
confirmationMsg['Amount (' + ((undefined === store.nodeData.smaller_currency_unit) ?
'Sats' : store.nodeData.smaller_currency_unit) + ')'] = action.payload[1].num_satoshis;
CurrencyUnitEnum.SATS : store.nodeData.smaller_currency_unit) + ')'] = action.payload[1].num_satoshis;
const msg = {};
msg['Total Fee (' + ((undefined === store.nodeData.smaller_currency_unit) ? 'Sats' : store.nodeData.smaller_currency_unit) + ')'] =
msg['Total Fee (' + ((undefined === store.nodeData.smaller_currency_unit) ? CurrencyUnitEnum.SATS : store.nodeData.smaller_currency_unit) + ')'] =
(sendRes.payment_route.total_fees_msat / 1000);
Object.assign(msg, confirmationMsg);
this.store.dispatch(new RTLActions.OpenAlert({ config: {
@ -999,17 +999,17 @@ export class LNDEffects implements OnDestroy {
this.sessionService.setItem('lndUnlocked', 'true');
if (undefined !== info.chains) {
if (typeof info.chains[0] === 'string') {
info.smaller_currency_unit = (info.chains[0].toString().toLowerCase().indexOf('bitcoin') < 0) ? 'Litoshis' : 'Sats';
info.currency_unit = (info.chains[0].toString().toLowerCase().indexOf('bitcoin') < 0) ? 'LTC' : 'BTC';
info.smaller_currency_unit = (info.chains[0].toString().toLowerCase().indexOf('bitcoin') < 0) ? CurrencyUnitEnum.LITOSHIS : CurrencyUnitEnum.SATS;
info.currency_unit = (info.chains[0].toString().toLowerCase().indexOf('bitcoin') < 0) ? CurrencyUnitEnum.LTC : CurrencyUnitEnum.BTC;
} else if (typeof info.chains[0] === 'object' && info.chains[0].hasOwnProperty('chain')) {
const getInfoChain = <GetInfoChain>info.chains[0];
info.smaller_currency_unit = (getInfoChain.chain.toLowerCase().indexOf('bitcoin') < 0) ? 'Litoshis' : 'Sats';
info.currency_unit = (getInfoChain.chain.toLowerCase().indexOf('bitcoin') < 0) ? 'LTC' : 'BTC';
info.smaller_currency_unit = (getInfoChain.chain.toLowerCase().indexOf('bitcoin') < 0) ? CurrencyUnitEnum.LITOSHIS : CurrencyUnitEnum.SATS;
info.currency_unit = (getInfoChain.chain.toLowerCase().indexOf('bitcoin') < 0) ? CurrencyUnitEnum.LTC : CurrencyUnitEnum.BTC;
}
info.version = (undefined === info.version) ? '' : info.version.split(' ')[0];
} else {
info.smaller_currency_unit = 'Sats';
info.currency_unit = 'BTC';
info.smaller_currency_unit = CurrencyUnitEnum.SATS;
info.currency_unit = CurrencyUnitEnum.BTC;
info.version = (undefined === info.version) ? '' : info.version.split(' ')[0];
}
const node_data = {

@ -27,7 +27,7 @@
<div fxFlex="30" fxLayoutAlign="space-between stretch">
<button fxFlex="50" fxLayoutAlign="center center" mat-raised-button color="primary"
[disabled]="fhForm.invalid" type="submit" tabindex="3">Fetch</button>
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="accent" class="ml-2" tabindex="4"
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="primary" class="ml-2" tabindex="4"
type="reset" (click)="resetData()">Clear</button>
</div>
</form>

@ -4,33 +4,33 @@
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput [(ngModel)]="memo" placeholder="Memo" tabindex="1" name="memo">
</mat-form-field>
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxFlex="60" fxLayoutAlign.gt-sm="space-between center">
<mat-form-field fxFlex="50" fxLayoutAlign="start end">
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxFlex="70" fxLayoutAlign.gt-sm="space-between center">
<mat-form-field fxFlex="40" fxLayoutAlign="start end">
<input matInput [(ngModel)]="invoiceValue" (keyup)="onInvoiceValueChange()" placeholder="Amount" type="number" step="100" min="1" tabindex="2" name="invoiceValue">
<span matSuffix> {{information?.smaller_currency_unit}} </span>
<span matSuffix> {{information?.smaller_currency_unit | titlecase}} </span>
<mat-hint>{{invoiceValueHint}}</mat-hint>
</mat-form-field>
<mat-form-field fxFlex="15" fxLayoutAlign="start end">
<input matInput [(ngModel)]="expiry" placeholder="Expiry" type="number" step="{{selTimeUnit === 'Secs' ? 300 : selTimeUnit === 'Mins' ? 10 : selTimeUnit === 'Hours' ? 2 : 1}}" min="1" tabindex="3" name="expiry">
<span matSuffix> {{selTimeUnit}} </span>
<input matInput [(ngModel)]="expiry" placeholder="Expiry" type="number" step="{{selTimeUnit === timeUnitEnum.SECS ? 300 : selTimeUnit === timeUnitEnum.MINS ? 10 : selTimeUnit === timeUnitEnum.HOURS ? 2 : 1}}" min="1" tabindex="3" name="expiry">
<span matSuffix> {{selTimeUnit | titlecase}} </span>
</mat-form-field>
<mat-form-field fxFlex="15" fxLayoutAlign="start end">
<mat-select [value]="selTimeUnit" tabindex="4" required name="timeUnit" (selectionChange)="onTimeUnitChange($event)">
<mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">{{timeUnit}}</mat-option>
<mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">{{timeUnit | titlecase}}</mat-option>
</mat-select>
</mat-form-field>
<div fxFlex="15" tabindex="4" fxLayoutAlign="start center">
<mat-slide-toggle color="primary" [(ngModel)]="private" matTooltip="Include routing hints for private channels" [matTooltipPosition]="'above'" name="private">Private</mat-slide-toggle>
<div fxFlex="25" tabindex="4" fxLayoutAlign="start center">
<mat-slide-toggle color="primary" [(ngModel)]="private" matTooltip="Include routing hints for private channels" [matTooltipPosition]="'above'" name="private">Private Routing Hints</mat-slide-toggle>
</div>
</div>
</div>
<div class="mt-2">
<button fxFlex="48" fxFlex.gt-md="10" fxLayoutAlign="center center" class="mr-2" mat-raised-button color="primary" [disabled]="addInvoiceForm.form.invalid" (click)="onAddInvoice(addInvoiceForm)" tabindex="5" class="mr-2">
<p *ngIf="addInvoiceForm.form.invalid; else createText">Invalid values</p>
<ng-template #createText><p>Create Invoice</p></ng-template>
</button>
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="6" type="reset" (click)="resetData()">Clear Field</button>
</div>
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="primary" class="mr-2" tabindex="5" type="reset" (click)="resetData()">Clear Field</button>
<button fxFlex="48" fxFlex.gt-md="10" fxLayoutAlign="center center" mat-raised-button color="primary" [disabled]="addInvoiceForm.form.invalid" (click)="onAddInvoice(addInvoiceForm)" tabindex="6">
<p *ngIf="addInvoiceForm.form.invalid; else createText">Invalid values</p>
<ng-template #createText><p>Create Invoice</p></ng-template>
</button>
</div>
</form>
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-2">
<div fxFlex="70">
@ -44,16 +44,12 @@
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="invoices" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="settled">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Settled </th>
<td mat-cell *matCellDef="let invoice">
<span *ngIf="invoice.settled"><i class="material-icons primary">done_all</i></span>
<span *ngIf="!invoice.settled"><i class="material-icons primary">done</i></span>
</td>
</ng-container>
<ng-container matColumnDef="creation_date">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date Created </th>
<td mat-cell *matCellDef="let invoice">{{invoice.creation_date_str}}</td>
<td mat-cell *matCellDef="let invoice">
<span *ngIf="invoice.settled" class="green-dot"></span>
<span *ngIf="!invoice.settled" class="yellow-dot"></span>
{{invoice.creation_date_str}}</td>
</ng-container>
<ng-container matColumnDef="memo">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Memo </th>
@ -70,7 +66,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="pr-3"><span fxLayoutAlign="end center">Actions</span></th>
<td mat-cell *matCellDef="let invoice">
<button mat-stroked-button color="accent" type="button" tabindex="4" (click)="onInvoiceClick(invoice, $event)">View Info</button>
<button mat-stroked-button color="primary" type="button" tabindex="4" (click)="onInvoiceClick(invoice, $event)">View Info</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>

@ -1,19 +1,19 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { getInvoicesPaginator } from '../../../shared/services/paginator.service';
import { MatTableDataSource, MatSort, MatPaginatorIntl } from '@angular/material';
import { getInvoicesPaginator } from '../../../shared/services/paginator.service';
import { TimeUnitEnum, CurrencyUnitEnum, TIME_UNITS } from '../../../shared/models/enums';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfo, Invoice } from '../../../shared/models/lndModels';
import { CurrencyUnitConvertPipe } from '../../../shared/pipes/app.pipe';
import { LoggerService } from '../../../shared/services/logger.service';
import { InvoiceInformationComponent } from '../../../shared/components/invoice-information/invoice-information.component';
import { CommonService } from '../../../shared/services/common.service';
import { InvoiceInformationComponent } from '../../../shared/components/invoice-information/invoice-information.component';
import { newlyAddedRowAnimation } from '../../../shared/animation/row-animation';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
@ -30,8 +30,6 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
export class LightningInvoicesComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
faHistory = faHistory;
public currencyUnits = [];
public currConvertorRate = null;
public selNode: SelNodeChild = {};
public newlyAddedInvoiceMemo = '';
public newlyAddedInvoiceValue = 0;
@ -47,34 +45,35 @@ export class LightningInvoicesComponent implements OnInit, OnDestroy {
public flgLoading: Array<Boolean | 'error'> = [true];
public flgSticky = false;
public private = false;
public timeUnits = ['Secs', 'Mins', 'Hours', 'Days'];
public selTimeUnit = 'Secs';
public expiryStep = 100;
public totalInvoices = 100;
public pageSize = 10;
public pageSizeOptions = [5, 10, 25, 100];
public timeUnitEnum = TimeUnitEnum;
public timeUnits = TIME_UNITS;
public selTimeUnit = TimeUnitEnum.SECS;
private firstOffset = -1;
private lastOffset = -1;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private httpClient: HttpClient, private currencyConvert: CurrencyUnitConvertPipe, private decimalPipe: DecimalPipe) {
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private decimalPipe: DecimalPipe, private commonService: CommonService) {
switch (true) {
case (window.innerWidth <= 415):
this.displayedColumns = ['settled', 'creation_date', 'value', 'actions'];
this.displayedColumns = ['creation_date', 'value', 'actions'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['settled', 'creation_date', 'value', 'settle_date', 'actions'];
this.displayedColumns = ['creation_date', 'value', 'settle_date', 'actions'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['settled', 'creation_date', 'memo', 'value', 'settle_date', 'actions'];
this.displayedColumns = ['creation_date', 'memo', 'value', 'settle_date', 'actions'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['settled', 'creation_date', 'memo', 'value', 'settle_date', 'actions'];
this.displayedColumns = ['creation_date', 'memo', 'value', 'settle_date', 'actions'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['settled', 'creation_date', 'memo', 'value', 'settle_date', 'actions'];
this.displayedColumns = ['creation_date', 'memo', 'value', 'settle_date', 'actions'];
break;
}
}
@ -88,7 +87,6 @@ export class LightningInvoicesComponent implements OnInit, OnDestroy {
this.flgLoading[0] = 'error';
}
});
this.currencyUnits = rtlStore.nodeSettings.currencyUnits;
this.selNode = rtlStore.nodeSettings;
this.information = rtlStore.information;
this.totalInvoices = rtlStore.totalInvoices;
@ -105,21 +103,8 @@ export class LightningInvoicesComponent implements OnInit, OnDestroy {
onAddInvoice(form: any) {
let expiryInSecs = (this.expiry ? this.expiry : 3600);
if (this.selTimeUnit !== this.timeUnits[0]) {
switch (this.selTimeUnit) {
case this.timeUnits[1]:
expiryInSecs = this.expiry * 60;
break;
case this.timeUnits[2]:
expiryInSecs = this.expiry * 3600;
break;
case this.timeUnits[3]:
expiryInSecs = this.expiry * 3600 * 24;
break;
default:
expiryInSecs = this.expiry;
break;
}
if (this.selTimeUnit !== TimeUnitEnum.SECS) {
expiryInSecs = this.commonService.convertTime(this.expiry, this.selTimeUnit, TimeUnitEnum.SECS);
}
this.flgAnimate = true;
this.newlyAddedInvoiceMemo = this.memo;
@ -159,7 +144,7 @@ export class LightningInvoicesComponent implements OnInit, OnDestroy {
this.private = false;
this.expiry = undefined;
this.invoiceValueHint = '';
this.selTimeUnit = this.timeUnits[0];
this.selTimeUnit = TimeUnitEnum.SECS;
}
applyFilter(selFilter: string) {
@ -181,89 +166,19 @@ export class LightningInvoicesComponent implements OnInit, OnDestroy {
}
onInvoiceValueChange() {
let self = this;
if(this.currencyUnits[2] && this.invoiceValue && this.invoiceValue.toString().length > 2) {
if(!this.currConvertorRate) {
this.httpClient.get('https://blockchain.info/ticker')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((currConvertorData: any) => {
self.currConvertorRate = currConvertorData;
self.invoiceValueHint = '= ' + currConvertorData[self.currencyUnits[2]].symbol + self.decimalPipe.transform(self.currencyConvert.transform(self.invoiceValue.toString(), currConvertorData[self.currencyUnits[2]].last * 0.00000001), '1.2-2') + ' ' + self.currencyUnits[2];
});
} else {
self.invoiceValueHint = '= ' + this.currConvertorRate[self.currencyUnits[2]].symbol + self.decimalPipe.transform(self.currencyConvert.transform(self.invoiceValue.toString(), this.currConvertorRate[self.currencyUnits[2]].last * 0.00000001), '1.2-2') + ' ' + self.currencyUnits[2];
}
} else {
if(this.invoiceValue > 99) {
this.invoiceValueHint = '';
this.commonService.convertCurrency(this.invoiceValue, CurrencyUnitEnum.SATS, this.selNode.currencyUnits[2])
.pipe(takeUntil(this.unSubs[1]))
.subscribe(data => {
this.invoiceValueHint = '= ' + data.symbol + this.decimalPipe.transform(data.OTHER, '1.2-2') + ' ' + data.unit;
});
}
}
onTimeUnitChange(event: any) {
if(this.expiry && this.selTimeUnit !== event.value) {
switch (this.selTimeUnit) {
case this.timeUnits[0]:
switch (event.value) {
case this.timeUnits[1]:
this.expiry = this.expiry / 60;
break;
case this.timeUnits[2]:
this.expiry = this.expiry / 3600;
break;
case this.timeUnits[3]:
this.expiry = this.expiry / (3600 * 24);
break;
default:
break;
}
break;
case this.timeUnits[1]:
switch (event.value) {
case this.timeUnits[0]:
this.expiry = this.expiry * 60;
break;
case this.timeUnits[2]:
this.expiry = this.expiry / 60;
break;
case this.timeUnits[3]:
this.expiry = this.expiry / (60 * 24);
break;
default:
break;
}
break;
case this.timeUnits[2]:
switch (event.value) {
case this.timeUnits[0]:
this.expiry = this.expiry * 3600;
break;
case this.timeUnits[1]:
this.expiry = this.expiry * 60;
break;
case this.timeUnits[3]:
this.expiry = this.expiry / 24;
break;
default:
break;
}
break;
case this.timeUnits[3]:
switch (event.value) {
case this.timeUnits[0]:
this.expiry = this.expiry * 3600 * 24;
break;
case this.timeUnits[1]:
this.expiry = this.expiry * 60 * 24;
break;
case this.timeUnits[2]:
this.expiry = this.expiry * 24;
break;
default:
break;
}
break;
default:
break;
}
this.expiry = this.commonService.convertTime(this.expiry, this.selTimeUnit, event.value);
}
this.selTimeUnit = event.value;
}

@ -4,12 +4,12 @@
<input matInput placeholder="Payment Request" name="paymentRequest" [(ngModel)]="paymentRequest" tabindex="1" required #paymentReq="ngModel">
</mat-form-field>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" fxLayoutAlign.gt-md="start start">
<button fxFlex="48" fxFlex.gt-md="10" fxLayoutAlign="center center" class="mr-2" mat-raised-button color="primary" [disabled]="paymentReq.invalid" (click)="onSendPayment();" tabindex="2">
<p *ngIf="paymentReq.invalid && (paymentReq.dirty || paymentReq.touched); else sendText">Invalid Req</p>
<ng-template #sendText><p>Send Payment</p></ng-template>
</button>
<button fxFlex="48" fxFlex.gt-md="10" mat-stroked-button color="accent" type="reset" tabindex="3" type="reset" (click)="resetData()">Clear Field</button>
</div>
<button fxFlex="48" fxFlex.gt-md="10" mat-stroked-button color="primary" class="mr-2" tabindex="2" type="reset" (click)="resetData()">Clear Field</button>
<button fxFlex="48" fxFlex.gt-md="10" fxLayoutAlign="center center" mat-raised-button color="primary" [disabled]="paymentReq.invalid" (click)="onSendPayment();" tabindex="3">
<p *ngIf="paymentReq.invalid && (paymentReq.dirty || paymentReq.touched); else sendText">Invalid Req</p>
<ng-template #sendText><p>Send Payment</p></ng-template>
</button>
</div>
</form>
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-2">
<div fxFlex="70">
@ -46,7 +46,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="pl-4 pr-3"><span fxLayoutAlign="end center">Actions</span></th>
<td mat-cell *matCellDef="let payment" class="pl-4">
<button mat-stroked-button color="accent" type="button" tabindex="4" (click)="onPaymentClick(payment,$event)">View Info</button>
<button mat-stroked-button color="primary" type="button" tabindex="4" (click)="onPaymentClick(payment,$event)">View Info</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>

@ -1,11 +1,11 @@
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<div fxLayout="row wrap" 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">Lightning 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"></rtl-currency-unit-converter>
<rtl-currency-unit-converter [values]="balances" [currencyUnits]="currencyUnits"></rtl-currency-unit-converter>
</mat-card-content>
</mat-card>
</div>

@ -1,14 +0,0 @@
.tree-invisible {
display: none;
}
.lookup-tree ul,
.lookup-tree li {
margin-top: 0;
margin-bottom: 0;
list-style-type: none;
}
.pl-3 {
padding-left: 3rem;
}

@ -16,6 +16,7 @@ import * as fromRTLReducer from '../../store/rtl.reducers';
export class TransactionsComponent implements OnInit, OnDestroy {
faExchangeAlt = faExchangeAlt;
faChartPie = faChartPie;
currencyUnits = [];
balances = [{title: 'Local Capacity', dataValue: 0, tooltip: 'Amount you can send'}, {title: 'Remote Capacity', dataValue: 0, tooltip: 'Amount you can receive'}];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
@ -25,6 +26,7 @@ export class TransactionsComponent implements OnInit, OnDestroy {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
this.currencyUnits = rtlStore.nodeSettings.currencyUnits;
this.balances = [{title: 'Local Capacity', dataValue: rtlStore.totalLocalBalance, tooltip: 'Amount you can send'}, {title: 'Remote Capacity', dataValue: rtlStore.totalRemoteBalance, tooltip: 'Amount you can receive'}];
this.logger.info(rtlStore);
});

@ -21,7 +21,7 @@
<mat-hint>Enter Wallet Password</mat-hint>
</mat-form-field>
<button mat-raised-button fxFlex="15" color="primary" [disabled]="walletPassword == ''" (click)="onOperateWallet()" tabindex="4">Unlock Wallet</button>
<button fxFlex="15" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="5" type="reset" (click)="resetData()">Clear</button>
<button fxFlex="15" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="5" type="reset" (click)="resetData()">Clear</button>
</form>
</div>
<ng-template #initBlock>
@ -29,7 +29,7 @@
<form fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign="start" fxLayoutAlign.gt-sm="space-between" class="mt-2">
<div fxFlex="65" fxLayoutAlign="start" class="insecure-message">Warning: Your connection is unsecure, it's not safe to generate private keys over this connection.Are you sure you want to proceed?</div>
<button mat-raised-button fxFlex="15" color="primary" type="submit" (click)="proceed=true;warnRes=true" tabindex="4">Proceed</button>
<button fxFlex="15" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="5" type="reset" (click)="proceed=false;warnRes=true">Cancel</button>
<button fxFlex="15" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="5" type="reset" (click)="proceed=false;warnRes=true">Cancel</button>
</form>
</div>
<div *ngIf="warnRes && !proceed" fxFlex="100" fxLayoutAlign="start" class="insecure-message mt-2">Please reconfig & restart RTL after securing your LND connction. You can close this window now.</div>
@ -61,7 +61,7 @@
<mat-hint>Cipher Seed</mat-hint>
</mat-form-field>
<button mat-raised-button color="primary" fxFlex="10" [disabled]="!cipherFormGroup.valid" type="submit" matStepperNext>Next</button>
<button mat-stroked-button color="accent" fxFlex="10" type="reset" matStepperPrevious>Back</button>
<button mat-stroked-button color="primary" fxFlex="10" type="reset" matStepperPrevious>Back</button>
<div *ngIf="cipherFormGroup.errors?.invalidCipher && cipherFormGroup.controls.existingCipher.value && (cipherFormGroup.controls.cipherSeed.touched || cipherFormGroup.controls.cipherSeed.dirty)" class="validation-error-message">
<mat-icon class="validation-error-icon red">cancel</mat-icon>Invalid Cipher. Enter comma separated 24 words cipher seed.
</div>

@ -27,8 +27,8 @@ export class AlertMessageComponent implements OnInit {
setStyleOnAlertType() {
// INFO/WARN/ERROR/SUCCESS/CONFIRM
if (this.data.type === 'WARN') {
this.msgTypeBackground = 'bg-accent p-1';
this.msgTypeForeground = 'accent';
this.msgTypeBackground = 'primary p-1';
this.msgTypeForeground = 'primary';
}
if (this.data.type === 'ERROR') {
this.msgTypeBackground = 'bg-warn p-1';

@ -122,7 +122,7 @@
<div class="mt-2">
<button class="mr-2" fxFlex="10" fxLayoutAlign="center center" mat-raised-button color="primary"
(click)="onUpdateSettings()" tabindex="12">Update</button>
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="accent" (click)="onResetSettings()"
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="primary" (click)="onResetSettings()"
tabindex="13">Reset</button>
</div>
</div>

@ -31,7 +31,7 @@
</div>
<mat-divider class="pb-1"></mat-divider>
<div fxLayoutAlign="center">
<button mat-stroked-button color="accent" fxFlex="20" type="button" fxLayoutAlign="center center" class="mr-2" (click)="onClose(false)" default>{{noBtnText}}</button>
<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>
</div>

@ -1,11 +1,11 @@
<mat-tab-group>
<mat-tab *ngFor="let currencyUnit of currencyUnits" [label]="currencyUnit">
<mat-tab *ngFor="let currencyUnit of currencyUnits" label="{{ currencyUnit }}">
<div fxLayout="row" fxFlex="100">
<div fxLayout="column" *ngFor="let value of values" [matTooltip]="value.tooltip" [matTooltipPosition]="'below'" class="cc-data-block">
<div class="cc-data-title">{{value.title}}</div>
<span class="cc-data-value" *ngIf="currencyUnit === CurrencyUnitEnum.SATS">{{value.dataValue | number}}</span>
<span class="cc-data-value" *ngIf="currencyUnit === CurrencyUnitEnum.BTC">{{value.dataValue | unitconvert:0.00000001 | number:'1.6-6'}}</span>
<span class="cc-data-value" *ngIf="currencyUnit !== CurrencyUnitEnum.SATS && currencyUnit !== CurrencyUnitEnum.BTC">{{value.dataValue | unitconvert:(unitConversionValue * 0.00000001) | number:'1.2-2'}}</span>
<span class="cc-data-value" *ngIf="currencyUnit === currencyUnitEnum.SATS">{{value.dataValue | number}}</span>
<span class="cc-data-value" *ngIf="currencyUnit === currencyUnitEnum.BTC">{{value.dataValueBTC | number:'1.6-6'}}</span>
<span class="cc-data-value" *ngIf="currencyUnit !== currencyUnitEnum.SATS && currencyUnit !== currencyUnitEnum.BTC">{{value.dataValueOTHER | number:'1.2-2'}}</span>
</div>
</div>
</mat-tab>

@ -1,13 +1,9 @@
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { takeUntil } from 'rxjs/operators';
import { LoggerService } from '../../services/logger.service';
import { CurrencyUnit } from '../../models/enums';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { CurrencyUnitEnum } from '../../models/enums';
import { CommonService } from '../../services/common.service';
@Component({
selector: 'rtl-currency-unit-converter',
@ -15,26 +11,41 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
styleUrls: ['./currency-unit-converter.component.scss']
})
export class CurrencyUnitConverterComponent implements OnInit, OnDestroy {
@Input() values = [];
currencyUnits = [];
CurrencyUnitEnum = CurrencyUnit;
unitConversionValue = 0;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
public currencyUnitEnum = CurrencyUnitEnum;
private _values: Array<any>;
private _currencyUnits = [];
private unSubs = [new Subject()];
get values(): Array<any> { return this._values; }
get currencyUnits(): Array<any> { return this._currencyUnits; }
@Input() set values(data: Array<any>) {
this._values = data;
if(this._currencyUnits.length > 2 && this._values[0].dataValue >= 0) {
this.getCurrencyValues(this._values);
}
}
@Input() set currencyUnits(data: Array<any>) {
this._currencyUnits = data;
if(this._currencyUnits.length > 2 && this._values[0].dataValue >= 0) {
this.getCurrencyValues(this._values);
}
}
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private httpClient: HttpClient) {}
constructor(public commonService: CommonService) {}
ngOnInit() {
this.store.select('lnd')
.pipe(take(2))
.subscribe((rtlStore) => {
this.currencyUnits = rtlStore.nodeSettings.currencyUnits;
this.logger.info(rtlStore);
if(this.currencyUnits[2]) {
this.httpClient.get('https://blockchain.info/ticker')
ngOnInit() {}
getCurrencyValues(values) {
values.forEach(value => {
if(value.dataValue > 0) {
this.commonService.convertCurrency(value.dataValue, CurrencyUnitEnum.SATS, this.currencyUnits[2])
.pipe(takeUntil(this.unSubs[0]))
.subscribe((data: any) => {
this.unitConversionValue = data[this.currencyUnits[2]].last;
.subscribe(data => {
value.dataValueBTC = data.BTC;
value.dataValueOTHER = data.OTHER;
});
} else {
value.dataValueBTC = value.dataValue;
value.dataValueOTHER = value.dataValue;
}
});
}
@ -45,5 +56,4 @@ export class CurrencyUnitConverterComponent implements OnInit, OnDestroy {
completeSub.complete();
});
}
}

@ -8,7 +8,7 @@
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Invoice Information</span>
</div>
<mat-icon fxFlex="5" type="button" (click)="onClose()" class="cursor-pointer icon-medium">close</mat-icon>
<mat-icon tabindex="3" fxFlex="5" type="button" fxLayoutAlign="center center" (click)="onClose()" class="cursor-pointer icon-medium">close</mat-icon>
</mat-card-header>
<mat-card-content>
<div fxLayout="column">
@ -69,11 +69,11 @@
<mat-divider class="w-100 my-1"></mat-divider>
</div>
<div [ngClass]="{'mt-2': !showAdvanced, 'mt-1': showAdvanced}" fxLayout="row" fxLayoutAlign="end center">
<button fxFlex="33" fxLayoutAlign="center center" class="mr-2" mat-raised-button color="primary" tabindex="2" type="submit" rtlClipboard [payload]="invoice.payment_request" (copied)="onCopyPayment($event)">Copy Payment Request</button>
<button fxFlex="25" fxLayoutAlign="center center" mat-stroked-button color="accent" type="reset" (click)="onShowAdvanced()" tabindex="1">
<button fxFlex="25" fxLayoutAlign="center center" mat-stroked-button color="primary" type="reset" (click)="onShowAdvanced()" tabindex="2" class="mr-2">
<p *ngIf="!showAdvanced; else hideAdvancedText">Show Advanced</p>
<ng-template #hideAdvancedText><p>Hide Advanced</p></ng-template>
</button>
<button autoFocus fxFlex="33" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="1" type="submit" rtlClipboard [payload]="invoice.payment_request" (copied)="onCopyPayment($event)">Copy Payment Request</button>
</div>
</div>
</mat-card-content>

@ -15,7 +15,7 @@
</mat-radio-group>
<div fxFlex="30" fxLayoutAlign="space-between stretch">
<button fxFlex="50" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onShowConfig()" tabindex="2">Show Config</button>
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="3" type="reset" class="ml-2" (click)="resetData()">Clear</button>
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="3" type="reset" class="ml-2" (click)="resetData()">Clear</button>
</div>
</form>
<div *ngIf="configData !== '' && fileFormat === 'JSON'">

@ -14,7 +14,7 @@
</mat-form-field>
<button fxFlex="10" class="mr-2" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="2"
type="submit" [disabled]="!password">Login</button>
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="3" type="reset"
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="3" type="reset"
(click)="resetData()">Clear</button>
</form>
</mat-card-content>

@ -0,0 +1,17 @@
import { AfterContentInit, Directive, ElementRef, Input } from '@angular/core';
@Directive({
selector: '[autoFocus]'
})
export class AutoFocusDirective implements AfterContentInit {
@Input() public appAutoFocus: boolean;
public constructor(private el: ElementRef) {}
public ngAfterContentInit() {
setTimeout(() => {
this.el.nativeElement.focus();
}, 500);
}
}

@ -1,11 +1,23 @@
export const CURRENCY_UNITS = [ 'SATS', 'BTC' ];
export const TIME_UNITS = ['SECS', 'MINS', 'HOURS', 'DAYS'];
export enum AuthenticateWith {
TOKEN = 'TOKEN',
PASSWORD = 'PASSWORD'
}
export enum CurrencyUnit {
export enum TimeUnitEnum {
SECS = 'SECS',
MINS = 'MINS',
HOURS = 'HOURS',
DAYS = 'DAYS'
}
export enum CurrencyUnitEnum {
SATS = 'SATS',
BTC = 'BTC'
BTC = 'BTC',
LITOSHIS = 'LITOSHIS',
LTC = 'LTC',
OTHER = 'OTHER'
}

@ -3,7 +3,7 @@ import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faProjectDiagr
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/transsendreceive'},
{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: 32, parentId: 3, name: 'Transactions', iconType: 'FA', icon: faExchangeAlt, link: '/lnd/transactions'},

@ -10,12 +10,3 @@ export class RemoveLeadingZerosPipe implements PipeTransform {
}
}
@Pipe({ name: 'unitconvert' })
export class CurrencyUnitConvertPipe implements PipeTransform {
transform(value: string, multiplier?: number): string {
return (+value * multiplier).toString();
}
}

@ -1,9 +1,23 @@
import { Injectable, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { Injectable, OnDestroy, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject, of, Observable } from 'rxjs';
import { take, map } from 'rxjs/operators';
import { CurrencyUnitEnum, TimeUnitEnum } from '../models/enums';
@Injectable()
export class CommonService implements OnDestroy {
export class CommonService implements OnInit, OnDestroy {
currencyUnits = [];
CurrencyUnitEnum = CurrencyUnitEnum;
unitConversionValue = 0;
containerWidthChanged = new Subject<string>();
conversionData = { data: null, last_fetched: null };
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(private httpClient: HttpClient) {}
ngOnInit() {}
sortDescByKey(array, key) {
return array.sort(function (a, b) {
@ -23,8 +37,120 @@ export class CommonService implements OnDestroy {
this.containerWidthChanged.next(fieldType);
}
convertCurrency(value: number, from: string, otherCurrencyUnit: string): Observable<any> {
let latest_date = new Date().valueOf();
if(this.conversionData.data && this.conversionData.last_fetched && (latest_date < (this.conversionData.last_fetched.valueOf() + 600000))) {
return of(this.convert(value, from, otherCurrencyUnit));
} else {
return this.httpClient.get('https://blockchain.info/ticker')
.pipe(take(1),
map(data => {
this.conversionData.data = data;
this.conversionData.last_fetched = latest_date;
this.unitConversionValue = this.conversionData.data[otherCurrencyUnit].last;
return this.convert(value, from, otherCurrencyUnit);
}));
}
}
convert(value: number, from: string, otherCurrencyUnit: string) {
let returnValue = {unit: otherCurrencyUnit, symbol: this.conversionData.data[otherCurrencyUnit].symbol, SATS: 0, BTC: 0, OTHER: 0};
switch (from) {
case CurrencyUnitEnum.SATS:
returnValue.SATS = value;
returnValue.BTC = value * 0.00000001;
returnValue.OTHER = value * 0.00000001 * this.unitConversionValue;
break;
case CurrencyUnitEnum.BTC:
returnValue.SATS = value * 100000000;
returnValue.BTC = value;
returnValue.OTHER = value * this.unitConversionValue;
break;
case CurrencyUnitEnum.OTHER:
returnValue.SATS = value / this.unitConversionValue * 100000000;
returnValue.BTC = value / this.unitConversionValue;
returnValue.OTHER = value;
break;
default:
break;
}
return returnValue;
}
convertTime(value: number, from: string, to: string) {
switch (from) {
case TimeUnitEnum.SECS:
switch (to) {
case TimeUnitEnum.MINS:
value = value / 60;
break;
case TimeUnitEnum.HOURS:
value = value / 3600;
break;
case TimeUnitEnum.DAYS:
value = value / (3600 * 24);
break;
default:
break;
}
break;
case TimeUnitEnum.MINS:
switch (to) {
case TimeUnitEnum.SECS:
value = value * 60;
break;
case TimeUnitEnum.HOURS:
value = value / 60;
break;
case TimeUnitEnum.DAYS:
value = value / (60 * 24);
break;
default:
break;
}
break;
case TimeUnitEnum.HOURS:
switch (to) {
case TimeUnitEnum.SECS:
value = value * 3600;
break;
case TimeUnitEnum.MINS:
value = value * 60;
break;
case TimeUnitEnum.DAYS:
value = value / 24;
break;
default:
break;
}
break;
case TimeUnitEnum.DAYS:
switch (to) {
case TimeUnitEnum.SECS:
value = value * 3600 * 24;
break;
case TimeUnitEnum.MINS:
value = value * 60 * 24;
break;
case TimeUnitEnum.HOURS:
value = value * 24;
break;
default:
break;
}
break;
default:
break;
}
return value;
}
ngOnDestroy() {
this.containerWidthChanged.next();
this.containerWidthChanged.complete();
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -31,7 +31,8 @@ import { ServerConfigComponent } from './components/server-config/server-config.
import { ErrorComponent } from './components/error/error.component';
import { CurrencyUnitConverterComponent } from './components/currency-unit-converter/currency-unit-converter.component';
import { ClipboardDirective } from './directive/clipboard.directive';
import { RemoveLeadingZerosPipe, CurrencyUnitConvertPipe } from './pipes/app.pipe';
import { AutoFocusDirective } from './directive/auto-focus.directive';
import { RemoveLeadingZerosPipe } from './pipes/app.pipe';
import { CommonService } from './services/common.service';
@NgModule({
@ -125,10 +126,10 @@ import { CommonService } from './services/common.service';
ServerConfigComponent,
CurrencyUnitConverterComponent,
ClipboardDirective,
AutoFocusDirective,
QRCodeModule,
NgxChartsModule,
RemoveLeadingZerosPipe,
CurrencyUnitConvertPipe
RemoveLeadingZerosPipe
],
declarations: [
AppSettingsComponent,
@ -146,8 +147,8 @@ import { CommonService } from './services/common.service';
CurrencyUnitConverterComponent,
ErrorComponent,
ClipboardDirective,
RemoveLeadingZerosPipe,
CurrencyUnitConvertPipe
AutoFocusDirective,
RemoveLeadingZerosPipe
],
entryComponents: [
InvoiceInformationComponent,
@ -158,7 +159,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' } },
CommonService, CurrencyUnitConvertPipe, DecimalPipe
CommonService, DecimalPipe
]
})
export class SharedModule { }

@ -2,7 +2,7 @@
@import '~@angular/material/theming';
@include mat-core();
$purple-primary: mat-palette($purple-primary, 500, 400, 700);
$purple-primary: mat-palette($purple-primary, 500, 200, 800);
$purple-accent: mat-palette($mat-gray, 800, 600, 900);
$purple-warn: mat-palette($mat-red);

@ -228,4 +228,17 @@
font-size: $large-font-size;
}
}
.icon-medium.mat-icon:focus, .icon-medium.mat-icon:hover {
outline: none;
@include mat-elevation(1);
}
.mat-raised-button.mat-primary:focus, .mat-raised-button.mat-primary:hover {
@include mat-elevation(8);
}
.mat-raised-button.mat-primary:disabled {
cursor: not-allowed;
}
}

@ -42,6 +42,9 @@
}
}
&.day {
.mat-stroked-button.mat-primary {
border-color: $primary-color;
}
.ng-fa-icon, .mat-nested-tree-node-parent .mat-icon, .mat-form-field-suffix {
color: $foreground-secondary-text;
}
@ -186,10 +189,6 @@
color: $primary-darker;
}
.mat-stroked-button.mat-accent:hover {
color: $primary-darker;
}
.cc-data-block {
margin-right: 3.2rem;
& .cc-data-title {

@ -19,4 +19,8 @@ $icon-size: 3.6rem;
$pubkey-info-height: 15px;
$tree-node-height:48px;
$fa-icon-small-size: 2rem;
$fa-icon-regular-size: 4rem;
$fa-icon-regular-size: 4rem;
$yellow-color: #ffbd2e;
$green-color: #28ca43;
$dot-size: 1.2rem;

@ -658,7 +658,7 @@ a {
.mat-tree-node div:focus, .mat-tree-node div:active, .mat-nested-tree-node-parent div:focus, .mat-nested-tree-node-parent div:active,
.mat-tree-node .mat-icon:focus, .mat-tree-node .mat-icon:active, .mat-nested-tree-node-parent .mat-icon:focus, .mat-nested-tree-node-parent .mat-icon:active {
outline: none;
}
}
.lnd-info {
height: $sidenav-info-height;
@ -742,6 +742,24 @@ table {
width:100%;
}
.mat-button-focus-overlay {
background-color: transparent!important;
// .mat-button-focus-overlay {
// background-color: transparent!important;
// }
.green-dot {
display: inline-flex;
width: $dot-size;
height: $dot-size;
border-radius: $dot-size;
margin-right: 1rem;
background-color: $green-color;
}
.yellow-dot {
display: inline-flex;
width: $dot-size;
height: $dot-size;
border-radius: $dot-size;
margin-right: 1rem;
background-color: $yellow-color;
}
Loading…
Cancel
Save