Swap Out, Swap In and Cancelled Swap Tables
Swap Out, Swap In and Cancelled Swap Tablespull/1089/head
parent
b37f6b8efe
commit
b23115e133
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
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
@ -1 +1 @@
|
|||||||
(()=>{"use strict";var e,v={},g={};function r(e){var n=g[e];if(void 0!==n)return n.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(n,t,f,o)=>{if(!t){var a=1/0;for(i=0;i<e.length;i++){for(var[t,f,o]=e[i],s=!0,d=0;d<t.length;d++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[d]))?t.splice(d--,1):(s=!1,o<a&&(a=o));if(s){e.splice(i--,1);var l=f();void 0!==l&&(n=l)}}return n}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,f,o]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>e+"."+{253:"256a01ccdc95a5d7",508:"06f7dec065381b97",515:"da134be35cc26574",924:"e98936d5bf0dd5da"}[e]+".js",r.miniCssF=e=>{},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="RTLApp:";r.l=(t,f,o,i)=>{if(e[t])e[t].push(f);else{var a,s;if(void 0!==o)for(var d=document.getElementsByTagName("script"),l=0;l<d.length;l++){var u=d[l];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==n+o){a=u;break}}a||(s=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+o),a.src=r.tu(t)),e[t]=[f];var c=(m,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(_=>_(b)),m)return m(b)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=c.bind(null,a.onerror),a.onload=c.bind(null,a.onload),s&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:n=>n},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(f,o)=>{var i=r.o(e,f)?e[f]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=f){var a=new Promise((u,c)=>i=e[f]=[u,c]);o.push(i[2]=a);var s=r.p+r.u(f),d=new Error;r.l(s,u=>{if(r.o(e,f)&&(0!==(i=e[f])&&(e[f]=void 0),i)){var c=u&&("load"===u.type?"missing":u.type),p=u&&u.target&&u.target.src;d.message="Loading chunk "+f+" failed.\n("+c+": "+p+")",d.name="ChunkLoadError",d.type=c,d.request=p,i[1](d)}},"chunk-"+f,f)}else e[f]=0},r.O.j=f=>0===e[f];var n=(f,o)=>{var d,l,[i,a,s]=o,u=0;if(i.some(p=>0!==e[p])){for(d in a)r.o(a,d)&&(r.m[d]=a[d]);if(s)var c=s(r)}for(f&&f(o);u<i.length;u++)r.o(e,l=i[u])&&e[l]&&e[l][0](),e[l]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();
|
(()=>{"use strict";var e,v={},g={};function r(e){var n=g[e];if(void 0!==n)return n.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(n,t,f,o)=>{if(!t){var a=1/0;for(i=0;i<e.length;i++){for(var[t,f,o]=e[i],s=!0,u=0;u<t.length;u++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[u]))?t.splice(u--,1):(s=!1,o<a&&(a=o));if(s){e.splice(i--,1);var d=f();void 0!==d&&(n=d)}}return n}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,f,o]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>e+"."+{258:"525782ba4bbc257e",508:"06f7dec065381b97",515:"73bff63b24de0558",706:"911e43a7ac305c95"}[e]+".js",r.miniCssF=e=>{},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="RTLApp:";r.l=(t,f,o,i)=>{if(e[t])e[t].push(f);else{var a,s;if(void 0!==o)for(var u=document.getElementsByTagName("script"),d=0;d<u.length;d++){var l=u[d];if(l.getAttribute("src")==t||l.getAttribute("data-webpack")==n+o){a=l;break}}a||(s=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+o),a.src=r.tu(t)),e[t]=[f];var c=(m,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(_=>_(b)),m)return m(b)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=c.bind(null,a.onerror),a.onload=c.bind(null,a.onload),s&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:n=>n},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(f,o)=>{var i=r.o(e,f)?e[f]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=f){var a=new Promise((l,c)=>i=e[f]=[l,c]);o.push(i[2]=a);var s=r.p+r.u(f),u=new Error;r.l(s,l=>{if(r.o(e,f)&&(0!==(i=e[f])&&(e[f]=void 0),i)){var c=l&&("load"===l.type?"missing":l.type),p=l&&l.target&&l.target.src;u.message="Loading chunk "+f+" failed.\n("+c+": "+p+")",u.name="ChunkLoadError",u.type=c,u.request=p,i[1](u)}},"chunk-"+f,f)}else e[f]=0},r.O.j=f=>0===e[f];var n=(f,o)=>{var u,d,[i,a,s]=o,l=0;if(i.some(p=>0!==e[p])){for(u in a)r.o(a,u)&&(r.m[u]=a[u]);if(s)var c=s(r)}for(f&&f(o);l<i.length;l++)r.o(e,d=i[l])&&e[d]&&e[d][0](),e[d]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();
|
@ -1,11 +1,3 @@
|
|||||||
.mat-column-nodeid {
|
|
||||||
flex: 0 0 20%;
|
|
||||||
width: 20%;
|
|
||||||
& .ellipsis-parent {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mat-column-actions {
|
.mat-column-actions {
|
||||||
min-height: 4.8rem;
|
min-height: 4.8rem;
|
||||||
}
|
}
|
@ -1 +0,0 @@
|
|||||||
<h1>Peerswaps Cancelled</h1>
|
|
@ -1,39 +0,0 @@
|
|||||||
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { SharedModule } from '../../../../shared/shared.module';
|
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|
||||||
import { PeerswapsCancelledComponent } from './swaps-cancelled.component';
|
|
||||||
import { mockLoggerService } from '../../../../shared/test-helpers/mock-services';
|
|
||||||
import { LoggerService } from '../../../../shared/services/logger.service';
|
|
||||||
|
|
||||||
describe('PeerswapsCancelledComponent', () => {
|
|
||||||
let component: PeerswapsCancelledComponent;
|
|
||||||
let fixture: ComponentFixture<PeerswapsCancelledComponent>;
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [PeerswapsCancelledComponent],
|
|
||||||
imports: [
|
|
||||||
BrowserAnimationsModule,
|
|
||||||
SharedModule
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
{ provide: LoggerService, useClass: mockLoggerService }
|
|
||||||
]
|
|
||||||
}).
|
|
||||||
compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(PeerswapsCancelledComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
TestBed.resetTestingModule();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,27 +0,0 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
||||||
import { Subject } from 'rxjs';
|
|
||||||
import { LoggerService } from '../../../../shared/services/logger.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'rtl-peerswap-cancelled',
|
|
||||||
templateUrl: './swaps-cancelled.component.html',
|
|
||||||
styleUrls: ['./swaps-cancelled.component.scss']
|
|
||||||
})
|
|
||||||
export class PeerswapsCancelledComponent implements OnInit, OnDestroy {
|
|
||||||
|
|
||||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
|
|
||||||
|
|
||||||
constructor(private logger: LoggerService) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.logger.info('Peerswap Out');
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.unSubs.forEach((completeSub) => {
|
|
||||||
completeSub.next(<any>null);
|
|
||||||
completeSub.complete();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
<h1>Peerswaps In</h1>
|
|
@ -1,39 +0,0 @@
|
|||||||
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { SharedModule } from '../../../../shared/shared.module';
|
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|
||||||
import { PeerswapsInComponent } from './swaps-in.component';
|
|
||||||
import { mockLoggerService } from '../../../../shared/test-helpers/mock-services';
|
|
||||||
import { LoggerService } from '../../../../shared/services/logger.service';
|
|
||||||
|
|
||||||
describe('PeerswapsInComponent', () => {
|
|
||||||
let component: PeerswapsInComponent;
|
|
||||||
let fixture: ComponentFixture<PeerswapsInComponent>;
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [PeerswapsInComponent],
|
|
||||||
imports: [
|
|
||||||
BrowserAnimationsModule,
|
|
||||||
SharedModule
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
{ provide: LoggerService, useClass: mockLoggerService }
|
|
||||||
]
|
|
||||||
}).
|
|
||||||
compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(PeerswapsInComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
TestBed.resetTestingModule();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,27 +0,0 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
||||||
import { Subject } from 'rxjs';
|
|
||||||
import { LoggerService } from '../../../../shared/services/logger.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'rtl-peer-swaps-in',
|
|
||||||
templateUrl: './swaps-in.component.html',
|
|
||||||
styleUrls: ['./swaps-in.component.scss']
|
|
||||||
})
|
|
||||||
export class PeerswapsInComponent implements OnInit, OnDestroy {
|
|
||||||
|
|
||||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
|
|
||||||
|
|
||||||
constructor(private logger: LoggerService) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.logger.info('Peerswap Out');
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.unSubs.forEach((completeSub) => {
|
|
||||||
completeSub.next(<any>null);
|
|
||||||
completeSub.complete();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,100 @@
|
|||||||
|
<div fxLayout="column" fxLayoutAlign="start stretch" class="padding-gap-x">
|
||||||
|
<div fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch"
|
||||||
|
class="page-sub-title-container">
|
||||||
|
<div fxFlex="70" class="padding-gap-x">
|
||||||
|
<fa-icon [icon]="selSwapList === swapLists[0] ? faPersonArrowUpFromLine : selSwapList === swapLists[1] ? faPersonArrowDownToLine : faPersonCircleXmark" class="mr-1"></fa-icon>
|
||||||
|
{{selSwapList === swapLists[0] ? 'Swapouts' : selSwapList === swapLists[1] ? 'Swapins' : 'Canceled Swaps'}}
|
||||||
|
</div>
|
||||||
|
<mat-form-field fxFlex="30">
|
||||||
|
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
|
||||||
|
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate">
|
||||||
|
</mat-progress-bar>
|
||||||
|
<table mat-table #table [dataSource]="swaps" fxFlex="100" matSort
|
||||||
|
[ngClass]="{'error-border': errorMessage !== ''}" class="overflow-auto">
|
||||||
|
<ng-container matColumnDef="id">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Swap Id</th>
|
||||||
|
<td mat-cell *matCellDef="let swap">
|
||||||
|
<span fxLayout="row" class="ellipsis-parent"
|
||||||
|
[ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '25rem'}">
|
||||||
|
<span class="ellipsis-child">
|
||||||
|
<fa-icon [icon]="faArrowRightFromBracket" *ngIf="swap.role === peerswapRoles.SENDER" matTooltip="Sender" matTooltipPosition="right" class="mr-1" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></fa-icon>
|
||||||
|
<fa-icon [icon]="faArrowRightToBracket" *ngIf="swap.role === peerswapRoles.RECEIVER" matTooltip="Receiver" matTooltipPosition="right" class="mr-1" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></fa-icon>
|
||||||
|
{{swap?.id}}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="alias">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Node Alias</th>
|
||||||
|
<td mat-cell *matCellDef="let swap">{{swap?.alias}}</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="short_channel_id">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header class="pl-1">Short Channel ID</th>
|
||||||
|
<td mat-cell *matCellDef="let swap" class="pl-1">{{swap?.short_channel_id}}</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="created_at">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Created At</th>
|
||||||
|
<td mat-cell *matCellDef="let swap">
|
||||||
|
{{swap?.created_at | date:'dd/MMM/y HH:mm'}}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="state">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>State</th>
|
||||||
|
<td mat-cell *matCellDef="let swap">{{swap?.state | swapState}}</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 swap"><span fxLayoutAlign="end center">{{swap?.amount | number }}</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="cancel_message">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header class="pl-2">Cancel Message</th>
|
||||||
|
<td mat-cell *matCellDef="let swap" class="pl-2">{{swap?.cancel_message}}</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="px-3">
|
||||||
|
<div class="bordered-box table-actions-select">
|
||||||
|
<mat-select placeholder="Actions" tabindex="1" class="mr-0">
|
||||||
|
<mat-select-trigger></mat-select-trigger>
|
||||||
|
<mat-option (click)="onDownloadCSV()">Download CSV</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let swap" [ngClass]="{'px-3': screenSize !== screenSizeEnum.XS}"
|
||||||
|
fxLayoutAlign="end center">
|
||||||
|
<button *ngIf="(selSwapList === swapLists[2]) || (selSwapList !== swapLists[2] && (swap.state === 'State_ClaimedPreimage' || swap.state === 'State_ClaimedCoop'))" mat-stroked-button color="primary" type="button" tabindex="4" (click)="onSwapClick(swap)">View Info</button>
|
||||||
|
<div *ngIf="selSwapList !== swapLists[2] && swap.state !== 'State_ClaimedPreimage' && swap.state !== 'State_ClaimedCoop'" class="bordered-box table-actions-select" fxLayoutAlign="center center">
|
||||||
|
<mat-select placeholder="Actions" tabindex="2" class="mr-0">
|
||||||
|
<mat-select-trigger></mat-select-trigger>
|
||||||
|
<mat-option (click)="onSwapClick(swap)">View Info</mat-option>
|
||||||
|
<mat-option (click)="onSwapRefresh(swap)">Refresh</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="no_swap">
|
||||||
|
<td mat-footer-cell *matFooterCellDef colspan="4">
|
||||||
|
<p
|
||||||
|
*ngIf="(!swaps?.data || (swaps?.data && swaps?.data.length && swaps?.data?.length<1)) && apiCallStatus?.status === apiCallStatusEnum.COMPLETED">
|
||||||
|
No swap available.</p>
|
||||||
|
<p
|
||||||
|
*ngIf="(!swaps?.data || (swaps?.data && swaps?.data.length && swaps?.data?.length<1)) && apiCallStatus?.status === apiCallStatusEnum.INITIATED">
|
||||||
|
Getting swaps...</p>
|
||||||
|
<p
|
||||||
|
*ngIf="(!swaps?.data || (swaps?.data && swaps?.data.length && swaps?.data?.length<1)) && apiCallStatus?.status === apiCallStatusEnum.ERROR">
|
||||||
|
{{errorMessage}}</p>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<tr mat-footer-row *matFooterRowDef="['no_swap']"
|
||||||
|
[ngClass]="{'display-none': swaps?.data && swaps?.data?.length>0}">
|
||||||
|
</tr>
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<mat-paginator *ngIf="errorMessage === ''" [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions"
|
||||||
|
[showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-1"></mat-paginator>
|
||||||
|
</div>
|
@ -0,0 +1,12 @@
|
|||||||
|
.mat-column-id {
|
||||||
|
flex: 0 0 20%;
|
||||||
|
width: 20%;
|
||||||
|
|
||||||
|
& .ellipsis-parent {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-column-actions {
|
||||||
|
min-height: 4.8rem;
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
|
import { StoreModule } from '@ngrx/store';
|
||||||
|
import { CommonService } from '../../../../shared/services/common.service';
|
||||||
|
import { mockCLEffects, mockLoggerService, mockECLEffects, mockLNDEffects, mockRTLEffects, mockDataService } from '../../../../shared/test-helpers/mock-services';
|
||||||
|
import { SharedModule } from '../../../../shared/shared.module';
|
||||||
|
|
||||||
|
import { RootReducer } from '../../../../store/rtl.reducers';
|
||||||
|
import { LNDReducer } from '../../../../lnd/store/lnd.reducers';
|
||||||
|
import { CLNReducer } from '../../../../cln/store/cln.reducers';
|
||||||
|
import { ECLReducer } from '../../../../eclair/store/ecl.reducers';
|
||||||
|
import { DataService } from '../../../../shared/services/data.service';
|
||||||
|
import { PeerswapsListComponent } from './swaps-list.component';
|
||||||
|
import { LoggerService } from '../../../../shared/services/logger.service';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
describe('PeerswapsListComponent', () => {
|
||||||
|
let component: PeerswapsListComponent;
|
||||||
|
let fixture: ComponentFixture<PeerswapsListComponent>;
|
||||||
|
// private commonService: CommonService, private store: Store<RTLState>, private router: Router
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [PeerswapsListComponent],
|
||||||
|
imports: [
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
SharedModule,
|
||||||
|
RouterTestingModule,
|
||||||
|
StoreModule.forRoot({ root: RootReducer, lnd: LNDReducer, cln: CLNReducer, ecl: ECLReducer }),
|
||||||
|
EffectsModule.forRoot([mockRTLEffects, mockLNDEffects, mockCLEffects, mockECLEffects])
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
CommonService,
|
||||||
|
{ provide: LoggerService, useClass: mockLoggerService },
|
||||||
|
{ provide: DataService, useClass: mockDataService }
|
||||||
|
]
|
||||||
|
}).
|
||||||
|
compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PeerswapsListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
TestBed.resetTestingModule();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,225 @@
|
|||||||
|
import { Component, OnInit, OnDestroy, ViewChild, AfterViewInit } from '@angular/core';
|
||||||
|
import { DatePipe, TitleCasePipe } from '@angular/common';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
|
||||||
|
import { MatSort } from '@angular/material/sort';
|
||||||
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
|
import { faArrowRightFromBracket, faArrowRightToBracket, faPersonArrowDownToLine, faPersonArrowUpFromLine, faPersonCircleXmark } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
import { Swap } from '../../../../shared/models/clnModels';
|
||||||
|
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, DataTypeEnum, AlertTypeEnum, PeerswapRoles, SwapTypeEnum } from '../../../../shared/services/consts-enums-functions';
|
||||||
|
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
|
||||||
|
import { LoggerService } from '../../../../shared/services/logger.service';
|
||||||
|
import { CommonService } from '../../../../shared/services/common.service';
|
||||||
|
|
||||||
|
import { RTLState } from '../../../../store/rtl.state';
|
||||||
|
import { openAlert } from '../../../../store/rtl.actions';
|
||||||
|
import { fetchSwaps, getSwap } from '../../../store/cln.actions';
|
||||||
|
import { swaps } from '../../../store/cln.selector';
|
||||||
|
import { SwapStatePipe } from '../../../../shared/pipes/app.pipe';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'rtl-peer-swaps-list',
|
||||||
|
templateUrl: './swaps-list.component.html',
|
||||||
|
styleUrls: ['./swaps-list.component.scss'],
|
||||||
|
providers: [
|
||||||
|
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Swaps') }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class PeerswapsListComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
|
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
|
||||||
|
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
|
||||||
|
public faPersonArrowDownToLine = faPersonArrowDownToLine;
|
||||||
|
public faPersonArrowUpFromLine = faPersonArrowUpFromLine;
|
||||||
|
public faPersonCircleXmark = faPersonCircleXmark;
|
||||||
|
public faArrowRightFromBracket = faArrowRightFromBracket;
|
||||||
|
public faArrowRightToBracket = faArrowRightToBracket;
|
||||||
|
public displayedColumns: any[] = [];
|
||||||
|
public allSwapsData: any = null;
|
||||||
|
public swapsData: Swap[] = [];
|
||||||
|
public swaps: any;
|
||||||
|
public flgSticky = false;
|
||||||
|
public pageSize = PAGE_SIZE;
|
||||||
|
public pageSizeOptions = PAGE_SIZE_OPTIONS;
|
||||||
|
public screenSize = '';
|
||||||
|
public screenSizeEnum = ScreenSizeEnum;
|
||||||
|
public errorMessage = '';
|
||||||
|
public selFilter = '';
|
||||||
|
public swapLists = ['psout', 'psin', 'pscanceled'];
|
||||||
|
public selSwapList = this.swapLists[0];
|
||||||
|
public peerswapRoles = PeerswapRoles;
|
||||||
|
public apiCallStatus: ApiCallStatusPayload | null = null;
|
||||||
|
public apiCallStatusEnum = APICallStatusEnum;
|
||||||
|
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
|
||||||
|
|
||||||
|
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private router: Router, private swapStatePipe: SwapStatePipe, private titleCasePipe: TitleCasePipe) {
|
||||||
|
this.screenSize = this.commonService.getScreenSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||||
|
this.router.onSameUrlNavigation = 'reload';
|
||||||
|
this.selSwapList = this.router.url.substring(this.router.url.lastIndexOf('/') + 1);
|
||||||
|
this.store.select(swaps).pipe(takeUntil(this.unSubs[0])).
|
||||||
|
subscribe((swapsSeletor: { swapOuts: Swap[], swapIns: Swap[], swapsCanceled: Swap[], apiCallStatus: ApiCallStatusPayload }) => {
|
||||||
|
this.errorMessage = '';
|
||||||
|
this.apiCallStatus = swapsSeletor.apiCallStatus;
|
||||||
|
if (this.apiCallStatus?.status === APICallStatusEnum.UN_INITIATED) {
|
||||||
|
this.store.dispatch(fetchSwaps());
|
||||||
|
}
|
||||||
|
if (this.apiCallStatus.status === APICallStatusEnum.ERROR) {
|
||||||
|
this.errorMessage = !this.apiCallStatus.message ? '' : (typeof (this.apiCallStatus.message) === 'object') ? JSON.stringify(this.apiCallStatus.message) : this.apiCallStatus.message;
|
||||||
|
}
|
||||||
|
if (this.apiCallStatus?.status === APICallStatusEnum.COMPLETED) {
|
||||||
|
this.allSwapsData = { swapOuts: swapsSeletor.swapOuts, swapIns: swapsSeletor.swapIns, swapsCanceled: swapsSeletor.swapsCanceled };
|
||||||
|
if (this.sort && this.paginator) {
|
||||||
|
this.loadTableWithSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.logger.info(swapsSeletor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (this.allSwapsData) {
|
||||||
|
this.loadTableWithSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTableWithSelection() {
|
||||||
|
switch (this.selSwapList) {
|
||||||
|
case this.swapLists[0]:
|
||||||
|
if (this.screenSize === ScreenSizeEnum.XS) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'state', 'amount', 'actions'];
|
||||||
|
} else if (this.screenSize === ScreenSizeEnum.SM) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'state', 'amount', 'actions'];
|
||||||
|
} else if (this.screenSize === ScreenSizeEnum.MD) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'created_at', 'state', 'amount', 'actions'];
|
||||||
|
} else {
|
||||||
|
this.flgSticky = true;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'created_at', 'state', 'amount', 'actions'];
|
||||||
|
}
|
||||||
|
this.swapsData = this.allSwapsData?.swapOuts || [];
|
||||||
|
break;
|
||||||
|
case this.swapLists[1]:
|
||||||
|
if (this.screenSize === ScreenSizeEnum.XS) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'state', 'amount', 'actions'];
|
||||||
|
} else if (this.screenSize === ScreenSizeEnum.SM) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'state', 'amount', 'actions'];
|
||||||
|
} else if (this.screenSize === ScreenSizeEnum.MD) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'created_at', 'state', 'amount', 'actions'];
|
||||||
|
} else {
|
||||||
|
this.flgSticky = true;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'created_at', 'state', 'amount', 'actions'];
|
||||||
|
}
|
||||||
|
this.swapsData = this.allSwapsData?.swapIns || [];
|
||||||
|
break;
|
||||||
|
case this.swapLists[2]:
|
||||||
|
if (this.screenSize === ScreenSizeEnum.XS) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'amount', 'cancel_message', 'actions'];
|
||||||
|
} else if (this.screenSize === ScreenSizeEnum.SM) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'amount', 'cancel_message', 'actions'];
|
||||||
|
} else if (this.screenSize === ScreenSizeEnum.MD) {
|
||||||
|
this.flgSticky = false;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'created_at', 'amount', 'cancel_message', 'actions'];
|
||||||
|
} else {
|
||||||
|
this.flgSticky = true;
|
||||||
|
this.displayedColumns = ['id', 'alias', 'short_channel_id', 'created_at', 'amount', 'cancel_message', 'actions'];
|
||||||
|
}
|
||||||
|
this.swapsData = this.allSwapsData?.swapsCanceled || [];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (this.swapsData && this.swapsData.length > 0 && this.sort && this.paginator) {
|
||||||
|
this.loadswapsTable(this.swapsData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSwapClick(selSwap: Swap) {
|
||||||
|
const reorderedSwap = [
|
||||||
|
[{ key: 'id', value: selSwap.id, title: 'Swap Id', width: 100, type: DataTypeEnum.STRING }],
|
||||||
|
[{ key: 'state', value: this.swapStatePipe.transform(selSwap.state || ''), title: 'State', width: 50, type: DataTypeEnum.STRING },
|
||||||
|
{ key: 'role', value: this.titleCasePipe.transform(selSwap.role), title: 'Role', width: 50, type: DataTypeEnum.STRING }],
|
||||||
|
[{ key: 'alias', value: selSwap.alias, title: 'Alias', width: 50, type: DataTypeEnum.STRING },
|
||||||
|
{ key: 'short_channel_id', value: selSwap.short_channel_id, title: 'Short Channel ID', width: 50, type: DataTypeEnum.STRING }],
|
||||||
|
[{ key: 'amount', value: selSwap.amount, title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER },
|
||||||
|
{ key: 'created_at', value: this.datePipe.transform(new Date(selSwap.created_at || ''), 'dd/MMM/YYYY HH:mm'), title: 'Created At', width: 50, type: DataTypeEnum.STRING }],
|
||||||
|
[{ key: 'peer_node_id', value: selSwap.peer_node_id, title: 'Peer Node Id', width: 100, type: DataTypeEnum.STRING }],
|
||||||
|
[{ key: 'initiator_node_id', value: selSwap.initiator_node_id, title: 'Initiator Node Id', width: 100, type: DataTypeEnum.STRING }]
|
||||||
|
];
|
||||||
|
if (selSwap.opening_tx_id) {
|
||||||
|
reorderedSwap.push([{ key: 'opening_tx_id', value: selSwap.opening_tx_id, title: 'Opening Transaction Id', width: 100, type: DataTypeEnum.STRING }]);
|
||||||
|
}
|
||||||
|
if (selSwap.claim_tx_id) {
|
||||||
|
reorderedSwap.push([{ key: 'claim_tx_id', value: selSwap.claim_tx_id, title: 'Claim Transaction Id', width: 100, type: DataTypeEnum.STRING }]);
|
||||||
|
}
|
||||||
|
if (selSwap.cancel_message) {
|
||||||
|
reorderedSwap.push([{ key: 'cancel_message', value: selSwap.cancel_message, title: 'Cancel Message', width: 100, type: DataTypeEnum.STRING }]);
|
||||||
|
}
|
||||||
|
this.store.dispatch(openAlert({
|
||||||
|
payload: {
|
||||||
|
data: {
|
||||||
|
type: AlertTypeEnum.INFORMATION,
|
||||||
|
alertTitle: this.selSwapList === this.swapLists[0] ? 'Swapout Information' : this.selSwapList === this.swapLists[1] ? 'Swapin Information' : 'Swap Canceled Information',
|
||||||
|
message: reorderedSwap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
loadswapsTable(swaps: Swap[]) {
|
||||||
|
this.swaps = new MatTableDataSource<Swap>([...swaps]);
|
||||||
|
this.swaps.sort = this.sort;
|
||||||
|
this.swaps.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
|
||||||
|
this.swaps.filterPredicate = (swap: Swap, fltr: string) => {
|
||||||
|
const newSwap =
|
||||||
|
(swap.id ? swap.id : '') +
|
||||||
|
(swap.alias ? swap.alias.toLowerCase() : '') +
|
||||||
|
(swap.role ? swap.role : '') +
|
||||||
|
(swap.short_channel_id ? swap.short_channel_id : '') +
|
||||||
|
(swap.amount ? swap.amount : '') +
|
||||||
|
(swap.state ? swap.state : '') +
|
||||||
|
((swap.created_at) ? this.datePipe.transform(new Date(swap.created_at), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') +
|
||||||
|
(swap.cancel_message ? swap.cancel_message.toLowerCase : '');
|
||||||
|
return newSwap?.includes(fltr) || false;
|
||||||
|
};
|
||||||
|
this.swaps.paginator = this.paginator;
|
||||||
|
this.applyFilter();
|
||||||
|
this.logger.info(this.swaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSwapRefresh(selSwap: Swap) {
|
||||||
|
this.store.dispatch(getSwap({ payload: selSwap.id || '' }));
|
||||||
|
}
|
||||||
|
|
||||||
|
onDownloadCSV() {
|
||||||
|
if (this.swaps && this.swaps.data && this.swaps.data.length > 0) {
|
||||||
|
this.commonService.downloadFile(this.swaps.data, 'Peerswap-' + this.selSwapList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applyFilter() {
|
||||||
|
this.swaps.filter = this.selFilter.trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.unSubs.forEach((completeSub) => {
|
||||||
|
completeSub.next(<any>null);
|
||||||
|
completeSub.complete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
<h1>Peerswaps Out</h1>
|
|
@ -1,39 +0,0 @@
|
|||||||
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { SharedModule } from '../../../../shared/shared.module';
|
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|
||||||
import { PeerswapsOutComponent } from './swaps-out.component';
|
|
||||||
import { mockLoggerService } from '../../../../shared/test-helpers/mock-services';
|
|
||||||
import { LoggerService } from '../../../../shared/services/logger.service';
|
|
||||||
|
|
||||||
describe('PeerswapsOutComponent', () => {
|
|
||||||
let component: PeerswapsOutComponent;
|
|
||||||
let fixture: ComponentFixture<PeerswapsOutComponent>;
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [PeerswapsOutComponent],
|
|
||||||
imports: [
|
|
||||||
BrowserAnimationsModule,
|
|
||||||
SharedModule
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
{ provide: LoggerService, useClass: mockLoggerService }
|
|
||||||
]
|
|
||||||
}).
|
|
||||||
compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(PeerswapsOutComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
TestBed.resetTestingModule();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,27 +0,0 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
||||||
import { Subject } from 'rxjs';
|
|
||||||
import { LoggerService } from '../../../../shared/services/logger.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'rtl-peer-swaps-out',
|
|
||||||
templateUrl: './swaps-out.component.html',
|
|
||||||
styleUrls: ['./swaps-out.component.scss']
|
|
||||||
})
|
|
||||||
export class PeerswapsOutComponent implements OnInit, OnDestroy {
|
|
||||||
|
|
||||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
|
|
||||||
|
|
||||||
constructor(private logger: LoggerService) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.logger.info('Peerswap Out');
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.unSubs.forEach((completeSub) => {
|
|
||||||
completeSub.next(<any>null);
|
|
||||||
completeSub.complete();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue