Sign/Verify Message #240

Sign/Verify Message #240
pull/266/head
Shahana Farooqui 4 years ago
parent d8835d2fcc
commit d41e6d4a46

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.dc87b0a5f469f6ecc1b4.css"></head>
<link rel="stylesheet" href="styles.e6b93e564e6b46dc016e.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.987de13467a4c3a263de.js" defer></script><script src="polyfills-es5.37b2eeccc22c1df73ce7.js" nomodule defer></script><script src="polyfills.f1c3d2a0bcdfc4e93ca8.js" defer></script><script src="main.d1d565730bda0bc69787.js" defer></script></body>
<script src="runtime.fd7f598087c4a68228d3.js" defer></script><script src="polyfills-es5.37b2eeccc22c1df73ce7.js" nomodule defer></script><script src="polyfills.f1c3d2a0bcdfc4e93ca8.js" defer></script><script src="main.ffc3e23c9362bb3a7234.js" defer></script></body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -26,6 +26,7 @@ const payReqRoutes = require("./routes/lnd/payReq");
const paymentsRoutes = require("./routes/lnd/payments");
const invoiceRoutes = require("./routes/lnd/invoices");
const switchRoutes = require("./routes/lnd/switch");
const messageRoutes = require("./routes/lnd/message");
const infoCLRoutes = require("./routes/c-lightning/getInfo");
const feesCLRoutes = require("./routes/c-lightning/fees");
@ -73,6 +74,7 @@ app.use(apiLNDRoot + "payreq", payReqRoutes);
app.use(apiLNDRoot + "payments", paymentsRoutes);
app.use(apiLNDRoot + "invoices", invoiceRoutes);
app.use(apiLNDRoot + "switch", switchRoutes);
app.use(apiLNDRoot + "message", messageRoutes);
app.use(apiCLRoot + "getinfo", infoCLRoutes);
app.use(apiCLRoot + "fees", feesCLRoutes);

@ -0,0 +1,57 @@
var request = require('request-promise');
var common = require('../../common');
var logger = require('../logger');
var options = {};
exports.signMessage = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/signmessage';
options.form = JSON.stringify({
msg: Buffer.from(req.body.message).toString('base64')
});
request.post(options, (error, response, body) => {
logger.info({fileName: 'Messages', msg: 'Message Signed: ' + JSON.stringify(body)});
if(!body || body.error) {
res.status(500).json({
message: "Sign message failed!",
error: (!body) ? 'Error From Server!' : body.error
});
} else {
res.status(201).json(body);
}
})
.catch(function (err) {
logger.error({fileName: 'Messages', lineNum: 24, msg: 'Sign Message Failed: ' + JSON.stringify(err)});
return res.status(500).json({
message: 'Sign Message Failed!',
error: err.error
});
});
};
exports.verifyMessage = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/verifymessage';
options.form = JSON.stringify({
msg: Buffer.from(req.body.message).toString('base64'),
signature: req.body.signature
});
request.post(options, (error, response, body) => {
logger.info({fileName: 'Messages', msg: 'Message Verified: ' + JSON.stringify(body)});
if(!body || body.error) {
res.status(500).json({
message: "Verify message failed!",
error: (!body) ? 'Error From Server!' : body.error
});
} else {
res.status(201).json(body);
}
})
.catch(function (err) {
logger.error({fileName: 'Messages', lineNum: 24, msg: 'Message Verification Failed: ' + JSON.stringify(err)});
return res.status(500).json({
message: 'Verify Message Failed!',
error: err.error
});
});
};

@ -0,0 +1,9 @@
const MessagesController = require("../../controllers/lnd/message");
const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
router.post("/sign", authCheck, MessagesController.signMessage);
router.post("/verify", authCheck, MessagesController.verifyMessage);
module.exports = router;

@ -29,6 +29,9 @@ import { NodeLookupComponent } from './lookups/node-lookup/node-lookup.component
import { BackupComponent } from './backup/backup.component';
import { ChannelBackupTableComponent } from './backup/channel-backup-table/channel-backup-table.component';
import { ChannelRestoreTableComponent } from './backup/channel-restore-table/channel-restore-table.component';
import { SignVerifyMessageComponent } from './sign-verify-message/sign-verify-message.component';
import { SignComponent } from './sign-verify-message/sign/sign.component';
import { VerifyComponent } from './sign-verify-message/verify/verify.component';
import { QueryRoutesComponent } from './transactions/query-routes/query-routes.component';
import { ChannelOpenTableComponent } from './peers-channels/channels/channels-tables/channel-open-table/channel-open-table.component';
import { UnlockWalletComponent } from './wallet/unlock/unlock.component';
@ -69,8 +72,11 @@ import { LNDUnlockedGuard } from '../shared/services/auth.guard';
NodeLookupComponent,
BackupComponent,
ChannelBackupTableComponent,
QueryRoutesComponent,
ChannelRestoreTableComponent,
SignVerifyMessageComponent,
SignComponent,
VerifyComponent,
QueryRoutesComponent,
OnChainSendComponent,
OnChainReceiveComponent,
OnChainComponent,

@ -10,10 +10,11 @@ import { LookupsComponent } from './lookups/lookups.component';
import { RoutingComponent } from './routing/routing.component';
import { OnChainComponent } from './on-chain/on-chain.component';
import { NetworkInfoComponent } from './network-info/network-info.component';
import { BackupComponent } from './backup/backup.component';
import { SignVerifyMessageComponent } from './sign-verify-message/sign-verify-message.component';
import { NotFoundComponent } from '../shared/components/not-found/not-found.component';
import { AuthGuard, LNDUnlockedGuard } from '../shared/services/auth.guard';
import { NotFoundComponent } from '../shared/components/not-found/not-found.component';
import { BackupComponent } from './backup/backup.component';
export const LndRoutes: Routes = [
{ path: '', component: LNDRootComponent,
@ -23,6 +24,7 @@ export const LndRoutes: Routes = [
{ path: 'onchain', component: OnChainComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'peerschannels', component: PeersChannelsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'transactions', component: TransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'signverify', component: SignVerifyMessageComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'backup', component: BackupComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'routing', component: RoutingComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'lookups', component: LookupsComponent, canActivate: [LNDUnlockedGuard] },

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil, filter, take } from 'rxjs/operators';
import { Store } from '@ngrx/store';

@ -0,0 +1,15 @@
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faUserCheck" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Sign/Verify Message</span>
</div>
<div fxLayout="column" class="padding-gap-x">
<mat-card>
<mat-card-content fxLayout="column">
<mat-tab-group>
<mat-tab label="Sign"><rtl-sign></rtl-sign></mat-tab>
<mat-tab label="Verify"><rtl-verify></rtl-verify></mat-tab>
</mat-tab-group>
</mat-card-content>
</mat-card>
</div>

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

@ -0,0 +1,14 @@
import { Component } from '@angular/core';
import { faUserCheck } from '@fortawesome/free-solid-svg-icons';
@Component({
selector: 'rtl-sign-verify-message',
templateUrl: './sign-verify-message.component.html',
styleUrls: ['./sign-verify-message.component.scss']
})
export class SignVerifyMessageComponent {
public faUserCheck = faUserCheck;
constructor() {}
}

@ -0,0 +1,16 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" #form="ngForm">
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<textarea autoFocus matInput [(ngModel)]="message" rows="5" (focus)="signature=''" placeholder="Message" required tabindex="1" name="message"></textarea>
<mat-error *ngIf="!message">Message is required.</mat-error>
</mat-form-field>
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start start" class="mt-1 bordered-box padding-gap-large">
<p>{{signature}}</p>
</div>
<div fxLayout="row" fxFlex="100" fxFlex.gt-sm="30" fxLayoutAlign="space-between stretch" class="mt-2">
<button fxFlex="30" mat-stroked-button color="primary" tabindex="2" type="reset" (click)="resetData()" type="reset">Clear Field</button>
<button fxFlex="30" mat-flat-button color="primary" (click)="onSign()" tabindex="3" type="submit">Sign</button>
<button fxFlex="35" mat-flat-button color="primary" tabindex="4" rtlClipboard [payload]="signature" (copied)="onCopyField($event)" type="button">Copy Signature</button>
</div>
</form>
</div>

@ -0,0 +1,6 @@
.mat-column-channel_point {
flex: 1 1 25%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

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

@ -0,0 +1,44 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { MatSnackBar } from '@angular/material';
import { DataService } from '../../../shared/services/data.service';
import { LoggerService } from '../../../shared/services/logger.service';
@Component({
selector: 'rtl-sign',
templateUrl: './sign.component.html',
styleUrls: ['./sign.component.scss']
})
export class SignComponent implements OnInit, OnDestroy {
public message = '';
public signature = '';
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(private dataService: DataService, private snackBar: MatSnackBar, private logger: LoggerService) {}
ngOnInit() {}
onSign() {
if (!this.message || this.message === '') { return true; }
this.dataService.signMessage(this.message).pipe(takeUntil(this.unSubs[0])).subscribe(res => { this.signature = res; });
}
onCopyField(payload: string) {
this.snackBar.open('Signature copied.');
this.logger.info('Copied Text: ' + payload);
}
resetData() {
this.message = '';
this.signature = '';
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -0,0 +1,19 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-sm="row wrap" #form="ngForm">
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<textarea autoFocus matInput [(ngModel)]="message" rows="5" (focus)="verifyRes=null" placeholder="Message" required tabindex="1" name="message"></textarea>
<mat-error *ngIf="!message">Message is required.</mat-error>
</mat-form-field>
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput placeholder="Signature" name="signature" [(ngModel)]="signature" tabindex="2" required #sign="ngModel">
<mat-error *ngIf="!signature">Signature is required.</mat-error>
</mat-form-field>
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start start" class="mt-1 bordered-box padding-gap-large" [ngClass]="{'border-valid': verifyRes?.valid, 'border-invalid': verifyRes?.pubkey && !verifyRes?.valid}">
<p>{{!verifyRes?.pubkey ? '' : (verifyRes?.pubkey && verifyRes?.valid) ? 'Valid: ' : 'Invalid: '}}{{verifyRes?.pubkey}}</p>
</div>
<div fxLayout="row" fxFlex="100" fxFlex.gt-sm="30" fxLayoutAlign="space-between stretch" class="mt-2">
<button fxFlex="48" mat-stroked-button color="primary" tabindex="3" type="reset" (click)="resetData()" type="reset">Clear Field</button>
<button fxFlex="48" mat-flat-button color="primary" (click)="onVerify()" tabindex="4" type="submit">Verify</button>
</div>
</form>
</div>

@ -0,0 +1,6 @@
.mat-column-channel_point {
flex: 1 1 25%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

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

@ -0,0 +1,39 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { DataService } from '../../../shared/services/data.service';
@Component({
selector: 'rtl-verify',
templateUrl: './verify.component.html',
styleUrls: ['./verify.component.scss']
})
export class VerifyComponent implements OnInit, OnDestroy {
public message = '';
public signature = '';
public verifyRes = {pubkey: '', valid: null};
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(private dataService: DataService) {}
ngOnInit() {}
onVerify() {
if ((!this.message || this.message === '') || (!this.signature || this.signature === '')) { return true; }
this.dataService.verifyMessage(this.message, this.signature).pipe(takeUntil(this.unSubs[0])).subscribe(res => { this.verifyRes = res; });
}
resetData() {
this.message = '';
this.signature = '';
this.verifyRes = null;
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -9,7 +9,7 @@
<mat-card-content class="mt-5px">
<form fxLayout="column">
<div fxLayout="column" class="bordered-box my-2 p-2">
<p fxLayoutAlign="start center" class="pb-1">Closing channel: {{channelToClose.channel_point}}</p>
<p fxLayoutAlign="start center" class="pb-1 word-break">Closing channel: {{channelToClose.channel_point}}</p>
<div fxLayoutAlign="space-between center">
<mat-form-field fxFlex.gt-sm="48">
<mat-select [(value)]="selTransType" tabindex="1">

@ -1,4 +1,4 @@
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faMapSigns, faQuestion, faSearch, faTools, faProjectDiagram, faDownload, faServer, faPercentage } from '@fortawesome/free-solid-svg-icons';
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faMapSigns, faQuestion, faSearch, faTools, faProjectDiagram, faDownload, faServer, faPercentage, faUserCheck } from '@fortawesome/free-solid-svg-icons';
import { UserPersonaEnum } from '../services/consts-enums-functions';
export const MENU_DATA: MenuRootNode = {
@ -10,7 +10,8 @@ export const MENU_DATA: MenuRootNode = {
{id: 32, parentId: 3, name: 'Transactions', iconType: 'FA', icon: faExchangeAlt, link: '/lnd/transactions', userPersona: UserPersonaEnum.ALL},
{id: 33, parentId: 3, name: 'Routing', iconType: 'FA', icon: faMapSigns, link: '/lnd/routing', userPersona: UserPersonaEnum.ALL},
{id: 34, parentId: 3, name: 'Graph Lookup', iconType: 'FA', icon: faSearch, link: '/lnd/lookups', userPersona: UserPersonaEnum.ALL},
{id: 35, parentId: 3, name: 'Backup', iconType: 'FA', icon: faDownload, link: '/lnd/backup', userPersona: UserPersonaEnum.ALL}
{id: 35, parentId: 3, name: 'Sign/Verify', iconType: 'FA', icon: faUserCheck, link: '/lnd/signverify', userPersona: UserPersonaEnum.ALL},
{id: 36, parentId: 3, name: 'Backup', iconType: 'FA', icon: faDownload, link: '/lnd/backup', userPersona: UserPersonaEnum.ALL}
]},
{id: 5, parentId: 0, name: 'Network', iconType: 'FA', icon: faProjectDiagram, link: '/lnd/network', userPersona: UserPersonaEnum.OPERATOR},
{id: 6, parentId: 0, name: 'Node/Network', iconType: 'FA', icon: faServer, link: '/lnd/network', userPersona: UserPersonaEnum.MERCHANT},

@ -2,14 +2,21 @@ import { Injectable, OnInit, OnDestroy } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject, of, Observable } from 'rxjs';
import { take, map, takeUntil, catchError } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { LoggerService } from '../../shared/services/logger.service';
import { environment, API_URL } from '../../../environments/environment';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
import { ErrorMessageComponent } from '../components/data-modal/error-message/error-message.component';
@Injectable()
export class DataService implements OnInit, OnDestroy {
private CHILD_API_URL = API_URL + '/lnd';
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private httpClient: HttpClient) {}
constructor(private httpClient: HttpClient, private store: Store<fromRTLReducer.RTLState>, private logger: LoggerService,) {}
ngOnInit() {}
@ -29,6 +36,62 @@ export class DataService implements OnInit, OnDestroy {
return nodes$;
}
signMessage(msg: string) {
this.store.dispatch(new RTLActions.OpenSpinner('Signing Message...'));
return this.httpClient.post(this.CHILD_API_URL + environment.MESSAGE_API + '/sign', {message: msg})
.pipe(takeUntil(this.unSubs[1]),
map((res: any) => {
this.store.dispatch(new RTLActions.CloseSpinner());
return res.signature;
}),
catchError(err => {
this.handleErrorWithAlert('ERROR', 'Sign Message Failed', this.CHILD_API_URL + environment.MESSAGE_API + '/sign', err);
throw err;
}));
}
verifyMessage(msg: string, sign: string) {
this.store.dispatch(new RTLActions.OpenSpinner('Verifying Message...'));
return this.httpClient.post(this.CHILD_API_URL + environment.MESSAGE_API + '/verify', {message: msg, signature: sign})
.pipe(takeUntil(this.unSubs[2]),
map((res: any) => {
this.store.dispatch(new RTLActions.CloseSpinner());
return res;
}),
catchError(err => {
this.handleErrorWithAlert('ERROR', 'Verify Message Failed', this.CHILD_API_URL + environment.MESSAGE_API + '/verify', err);
throw err;
}));
}
handleErrorWithoutAlert(actionName: string, err: { status: number, error: any }) {
this.logger.error('ERROR IN: ' + actionName + '\n' + JSON.stringify(err));
if (err.status === 401) {
this.logger.info('Redirecting to Login');
this.store.dispatch(new RTLActions.Logout());
} else {
this.store.dispatch(new RTLActions.EffectErrorLnd({ action: actionName, code: err.status.toString(), message: err.error.error }));
}
}
handleErrorWithAlert(alertType: string, alertTitle: string, errURL: string, err: { status: number, error: any }) {
this.logger.error(err);
if (err.status === 401) {
this.logger.info('Redirecting to Login');
this.store.dispatch(new RTLActions.Logout());
} else {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
data: {
type: alertType,
alertTitle: alertTitle,
message: { code: err.status, message: err.error.error, URL: errURL },
component: ErrorMessageComponent
}
}));
}
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();

@ -391,6 +391,7 @@
border: 1px solid $foreground-divider;
border-radius: 4px;
background: none;
min-height: 5.5rem;
}
.mat-expansion-panel {

@ -961,3 +961,11 @@ table {
overflow-y: scroll;
max-height: 600px;
}
.border-valid {
border: 1px solid $green-color !important;
}
.border-invalid {
border: 1px solid $red-color !important;
}

@ -22,5 +22,6 @@ export const environment = {
INVOICES_API: '/invoices',
SWITCH_API: '/switch',
ON_CHAIN_API: '/onchain',
MESSAGE_API: '/message',
VERSION: VERSION
};

@ -22,5 +22,6 @@ export const environment = {
INVOICES_API: '/invoices',
SWITCH_API: '/switch',
ON_CHAIN_API: '/onchain',
MESSAGE_API: '/message',
VERSION: VERSION
};

Loading…
Cancel
Save