Open Liquidity Channel

Open Liquidity Channel
This commit is contained in:
Shahana Farooqui 2022-05-18 16:52:16 -04:00 committed by ShahanaFarooqui
parent 3795851acf
commit 9da3eed1b6
12 changed files with 309 additions and 50 deletions

View File

@ -56,7 +56,8 @@ import { CLNCreateOfferComponent } from './transactions/offers/create-offer-moda
import { CLNOfferInformationComponent } from './transactions/offers/offer-information-modal/offer-information.component';
import { CLNOffersTableComponent } from './transactions/offers/offers-table/offers-table.component';
import { CLNOfferBookmarksTableComponent } from './transactions/offers/offer-bookmarks-table/offer-bookmarks-table.component';
import { CLNLiquidityAdsComponent } from './liquidity-ads/liquidity-ads.component';
import { CLNLiquidityAdsListComponent } from './liquidity-ads/liquidity-ads-list/liquidity-ads-list.component';
import { CLNOpenLiquidityChannelComponent } from './liquidity-ads/open-liquidity-channel-modal/open-liquidity-channel-modal.component';
import { CLNUnlockedGuard } from '../shared/services/auth.guard';
@ -119,7 +120,8 @@ import { CLNUnlockedGuard } from '../shared/services/auth.guard';
CLNOfferInformationComponent,
CLNOffersTableComponent,
CLNOfferBookmarksTableComponent,
CLNLiquidityAdsComponent
CLNLiquidityAdsListComponent,
CLNOpenLiquidityChannelComponent
],
providers: [
CLNUnlockedGuard

View File

@ -34,7 +34,7 @@ import { CLNGraphComponent } from './graph/graph.component';
import { CLNOffersTableComponent } from './transactions/offers/offers-table/offers-table.component';
import { CLNOfferBookmarksTableComponent } from './transactions/offers/offer-bookmarks-table/offer-bookmarks-table.component';
import { CLNLocalFailedTransactionsComponent } from './routing/local-failed-transactions/local-failed-transactions.component';
import { CLNLiquidityAdsComponent } from './liquidity-ads/liquidity-ads.component';
import { CLNLiquidityAdsListComponent } from './liquidity-ads/liquidity-ads-list/liquidity-ads-list.component';
export const ClnRoutes: Routes = [
{
@ -63,7 +63,7 @@ export const ClnRoutes: Routes = [
{ path: 'peers', component: CLNPeersComponent, data: { sweepAll: false }, canActivate: [CLNUnlockedGuard] }
]
},
{ path: 'liquidityads', component: CLNLiquidityAdsComponent, canActivate: [CLNUnlockedGuard] },
{ path: 'liquidityads', component: CLNLiquidityAdsListComponent, canActivate: [CLNUnlockedGuard] },
{
path: 'transactions', component: CLNTransactionsComponent, canActivate: [CLNUnlockedGuard], children: [
{ path: '', pathMatch: 'full', redirectTo: 'payments' },

View File

@ -42,18 +42,13 @@
</span>
</div>
<mat-form-field fxFlex="34">
<input matInput placeholder="Node Capacity (Sats)" name="nodeCapacity" [(ngModel)]="nodeCapacity" tabindex="5" type="number" step="1000" required>
<input matInput placeholder="Node Capacity (Sats)" name="nodeCapacity" [(ngModel)]="nodeCapacity" (keyup)="onFilter()" tabindex="5" type="number" min="0" step="1000">
<mat-error *ngIf="!nodeCapacity">Node capacity is required.</mat-error>
</mat-form-field>
<mat-form-field fxFlex="34">
<input matInput placeholder="Channel Count" name="channelCount" [(ngModel)]="channelCount" type="number" step="1" tabindex="6" required>
<mat-error *ngIf="!channelCount">Channel count is required.</mat-error>
<input matInput placeholder="Channel Count" name="channelCount" [(ngModel)]="channelCount" (keyup)="onFilter()" type="number" step="1" min="0" tabindex="6">
</mat-form-field>
</div>
<div fxLayout="row" class="my-1">
<button class="mr-1" mat-stroked-button color="primary" tabindex="7" type="reset" (click)="onFilterReset()">Clear</button>
<button mat-flat-button color="primary" (click)="onFilter()" tabindex="8" type="submit">Filter</button>
</div>
</form>
<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>

View File

@ -1,20 +1,20 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SharedModule } from '../../shared/shared.module';
import { SharedModule } from '../../../shared/shared.module';
import { DataService } from '../../shared/services/data.service';
import { CommonService } from '../../shared/services/common.service';
import { mockDataService } from '../../shared/test-helpers/mock-services';
import { DataService } from '../../../shared/services/data.service';
import { CommonService } from '../../../shared/services/common.service';
import { mockDataService } from '../../../shared/test-helpers/mock-services';
import { CLNLiquidityAdsComponent } from './liquidity-ads.component';
import { CLNLiquidityAdsListComponent } from './liquidity-ads-list.component';
describe('CLNLiquidityAdsComponent', () => {
let component: CLNLiquidityAdsComponent;
let fixture: ComponentFixture<CLNLiquidityAdsComponent>;
describe('CLNLiquidityAdsListComponent', () => {
let component: CLNLiquidityAdsListComponent;
let fixture: ComponentFixture<CLNLiquidityAdsListComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [CLNLiquidityAdsComponent],
declarations: [CLNLiquidityAdsListComponent],
imports: [
BrowserAnimationsModule,
SharedModule
@ -28,7 +28,7 @@ describe('CLNLiquidityAdsComponent', () => {
}));
beforeEach(() => {
fixture = TestBed.createComponent(CLNLiquidityAdsComponent);
fixture = TestBed.createComponent(CLNLiquidityAdsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -7,25 +7,28 @@ import { MatSort } from '@angular/material/sort';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { faBullhorn, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { DataService } from '../../shared/services/data.service';
import { LoggerService } from '../../shared/services/logger.service';
import { CommonService } from '../../shared/services/common.service';
import { AlertTypeEnum, APICallStatusEnum, DataTypeEnum, getPaginatorLabel, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum } from '../../shared/services/consts-enums-functions';
import { LookupNode } from '../../shared/models/clnModels';
import { ApiCallStatusPayload } from '../../shared/models/apiCallsPayload';
import { openConfirmation } from '../../store/rtl.actions';
import { RTLState } from '../../store/rtl.state';
import { RTLEffects } from '../../store/rtl.effects';
import { DataService } from '../../../shared/services/data.service';
import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service';
import { AlertTypeEnum, APICallStatusEnum, DataTypeEnum, getPaginatorLabel, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
import { Balance, GetInfo, LookupNode } from '../../../shared/models/clnModels';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { openAlert, openConfirmation } from '../../../store/rtl.actions';
import { RTLState } from '../../../store/rtl.state';
import { RTLEffects } from '../../../store/rtl.effects';
import { CLNOpenLiquidityChannelComponent } from '../open-liquidity-channel-modal/open-liquidity-channel-modal.component';
import { nodeInfoAndNodeSettingsAndBalance } from '../../store/cln.selector';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
@Component({
selector: 'rtl-cln-liquidity-ads',
templateUrl: './liquidity-ads.component.html',
styleUrls: ['./liquidity-ads.component.scss'],
selector: 'rtl-cln-liquidity-ads-list',
templateUrl: './liquidity-ads-list.component.html',
styleUrls: ['./liquidity-ads-list.component.scss'],
providers: [
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Liquidity Ads') }
]
})
export class CLNLiquidityAdsComponent implements OnInit, OnDestroy {
export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
@ -34,8 +37,10 @@ export class CLNLiquidityAdsComponent implements OnInit, OnDestroy {
public displayedColumns: any[] = [];
public faBullhorn = faBullhorn;
public faExclamationTriangle = faExclamationTriangle;
public channelAmount = 0;
public channelOpeningFeeRate = 0;
public totalBalance = 0;
public information: GetInfo;
public channelAmount = 100000;
public channelOpeningFeeRate = 2;
public nodeCapacity = 500000;
public channelCount = 5;
public liquidityNodesData: LookupNode[] = [];
@ -83,6 +88,12 @@ export class CLNLiquidityAdsComponent implements OnInit, OnDestroy {
this.errorMessage = JSON.stringify(err);
}
});
this.store.select(nodeInfoAndNodeSettingsAndBalance).pipe(takeUntil(this.unSubs[1])).
subscribe((infoSettingsBalSelector: { information: GetInfo, nodeSettings: SelNodeChild, balance: Balance }) => {
this.information = infoSettingsBalSelector.information;
this.totalBalance = infoSettingsBalSelector.balance.totalBalance;
this.logger.info(infoSettingsBalSelector);
});
}
onRecalculate() {
@ -90,27 +101,35 @@ export class CLNLiquidityAdsComponent implements OnInit, OnDestroy {
}
onFilter() {
this.logger.info(this.nodeCapacity);
this.logger.info(this.channelCount);
this.liquidityNodes.filter = this.nodeCapacity + ' ' + this.channelCount;
this.liquidityNodes.filter = 'Changed';
}
loadLiqNodesTable(liqNodes: LookupNode[]) {
this.liquidityNodes = new MatTableDataSource<LookupNode>([...liqNodes]);
this.liquidityNodes.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.liquidityNodes.sort = this.sort;
this.liquidityNodes.filterPredicate = (node: LookupNode, fltr: string) => {
console.warn(node.channelCount);
console.warn(node.nodeCapacity);
console.warn(node.channelCount >= this.channelCount && node.nodeCapacity >= this.nodeCapacity);
return node.channelCount >= this.channelCount && node.nodeCapacity >= this.nodeCapacity;
}
this.liquidityNodes.filterPredicate = (node: LookupNode, fltr: string) => node.channelCount >= this.channelCount && node.nodeCapacity >= this.nodeCapacity;
this.liquidityNodes.paginator = this.paginator;
this.onFilter();
}
onOpenChannel(lqNode: LookupNode) {
const peerToAddChannelMessage = {
node: lqNode,
balance: this.totalBalance,
requestedAmount: this.channelAmount,
feeRate: this.channelOpeningFeeRate,
localAmount: 20000
};
this.store.dispatch(openAlert({
payload: {
data: {
alertTitle: 'Open Channel',
message: peerToAddChannelMessage,
component: CLNOpenLiquidityChannelComponent
}
}
}));
}
onViewLeaseInfo(lqNode: LookupNode) {
@ -141,9 +160,9 @@ export class CLNLiquidityAdsComponent implements OnInit, OnDestroy {
}
}
}));
this.rtlEffects.closeConfirm.pipe(takeUntil(this.unSubs[1])).subscribe((confirmRes) => {
this.rtlEffects.closeConfirm.pipe(takeUntil(this.unSubs[2])).subscribe((confirmRes) => {
if (confirmRes) {
console.warn('Open Channel Modal');
this.onOpenChannel(lqNode);
}
});
}

View File

@ -0,0 +1,93 @@
<div fxLayout="row">
<div fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">{{alertTitle}}</span>
</div>
<button tabindex="6" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header>
<mat-card-content class="padding-gap-x-large">
<form fxLayout="column" #form="ngForm">
<ng-container *ngTemplateOutlet="nodeDetailsExpansionBlock"></ng-container>
<div fxLayout="column" fxLayoutAlign="space-between stretch" fxLayoutAlign.gt-sm="space-between center" fxLayout.gt-sm="row wrap">
<mat-form-field fxFlex="30" fxLayoutAlign="start end">
<input autoFocus matInput [(ngModel)]="requestedAmount" placeholder="Requested Amount" type="number" [step]="1000" [min]="0" tabindex="1" required name="ramount" #ramount="ngModel">
<span matSuffix> Sats </span>
<mat-error *ngIf="ramount.errors?.required">Requested amount is required.</mat-error>
</mat-form-field>
<mat-form-field fxFlex="30" fxLayoutAlign="start end">
<input matInput [(ngModel)]="feeRate" placeholder="Fee Rate" type="number" [step]="1" [min]="0" tabindex="2" required name="feerate" #feeRt="ngModel">
<span matSuffix> Sats/vByte </span>
<mat-error *ngIf="feeRt.errors?.required">Fee rate is required.</mat-error>
</mat-form-field>
<mat-form-field fxFlex="30" fxLayoutAlign="start end">
<input matInput [(ngModel)]="localAmount" placeholder="Local Amount" type="number" [step]="1000" [min]="20000" [max]="totalBalance" tabindex="3" required name="lamount" #lamount="ngModel">
<mat-hint>Remaining Bal: {{totalBalance - ((localAmount) ? localAmount : 0) | number}}</mat-hint>
<span matSuffix> Sats </span>
<mat-error *ngIf="lamount.errors?.required">Local amount is required.</mat-error>
<mat-error *ngIf="lamount.errors?.min">Local amount must be greater than or equal to 20000.</mat-error>
<mat-error *ngIf="lamount.errors?.max">Local amount must be less than or equal to {{totalBalance}}.</mat-error>
</mat-form-field>
</div>
<div fxFlex="100" class="alert alert-info mt-2">
<span>Total cost to lease {{1250 | number}} (Sats)</span>
</div>
<div fxFlex="100" class="alert alert-danger mt-2" *ngIf="channelConnectionError !== ''">
<fa-icon [icon]="faExclamationTriangle" class="mr-1 alert-icon"></fa-icon>
<span *ngIf="channelConnectionError !== ''">{{channelConnectionError}}</span>
</div>
<div class="mt-2" fxLayout="row" fxLayoutAlign="end center">
<button mat-button color="primary" class="mr-1" tabindex="4" (click)="resetData()">Clear</button>
<button autoFocus mat-button color="primary" tabindex="5" (click)="onOpenChannel()">Execute</button>
</div>
</form>
</mat-card-content>
</div>
</div>
<ng-template #nodeDetailsExpansionBlock>
<mat-expansion-panel class="flat-expansion-panel my-1" *ngIf="node" expanded="false">
<mat-expansion-panel-header>
<mat-panel-title>
<span>Node: &nbsp;</span><strong class="font-weight-900">{{node?.alias || node?.nodeid}}</strong>
</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="column">
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">Pubkey</h4>
<span class="foreground-secondary-text">{{node.nodeid}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">Last Timestamp</h4>
<span class="overflow-wrap foreground-secondary-text">{{node.last_timestamp}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="column" fxLayoutAlign="start stretch">
<h4 fxFlex="100" class="font-bold-500 mb-1">Addresses</h4>
<div class="table-container">
<table mat-table #table [dataSource]="node.addresses" matSort class="overflow-auto">
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Type</th>
<td mat-cell *matCellDef="let address"> {{address?.type}} </td>
</ng-container>
<ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th>
<td mat-cell *matCellDef="let address"> {{address?.address }} </td>
</ng-container>
<ng-container matColumnDef="port">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Port</th>
<td mat-cell *matCellDef="let address"> {{address?.port}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</div>
</div>
</mat-expansion-panel>
</ng-template>

View File

@ -0,0 +1,3 @@
.open-inputs-box {
padding: 1.2rem 2.4rem 0.8rem 2.4rem !important;
}

View File

@ -0,0 +1,53 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { CommonService } from '../../../shared/services/common.service';
import { DataService } from '../../../shared/services/data.service';
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 { CLNOpenLiquidityChannelComponent } from './open-liquidity-channel-modal.component';
import { mockCLEffects, mockDataService, mockECLEffects, mockLNDEffects, mockMatDialogRef, mockRTLEffects } from '../../../shared/test-helpers/mock-services';
import { SharedModule } from '../../../shared/shared.module';
describe('CLNOpenLiquidityChannelComponent', () => {
let component: CLNOpenLiquidityChannelComponent;
let fixture: ComponentFixture<CLNOpenLiquidityChannelComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [CLNOpenLiquidityChannelComponent],
imports: [
BrowserAnimationsModule,
SharedModule,
StoreModule.forRoot({ root: RootReducer, lnd: LNDReducer, cln: CLNReducer, ecl: ECLReducer }),
EffectsModule.forRoot([mockRTLEffects, mockLNDEffects, mockCLEffects, mockECLEffects])
],
providers: [
CommonService,
{ provide: DataService, useClass: mockDataService },
{ provide: MatDialogRef, useClass: mockMatDialogRef },
{ provide: MAT_DIALOG_DATA, useValue: { message: {} } }
]
}).
compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CLNOpenLiquidityChannelComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
afterEach(() => {
TestBed.resetTestingModule();
});
});

View File

@ -0,0 +1,84 @@
import { Component, OnInit, Inject, OnDestroy, ViewChild } from '@angular/core';
import { Store } from '@ngrx/store';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Actions } from '@ngrx/effects';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { LookupNode } from '../../../shared/models/clnModels';
import { CLNOpenLiquidityChannelAlert } from '../../../shared/models/alertData';
import { APICallStatusEnum, CLNActions } from '../../../shared/services/consts-enums-functions';
import { RTLState } from '../../../store/rtl.state';
import { saveNewChannel } from '../../store/cln.actions';
@Component({
selector: 'rtl-cln-open-liquidity-channel',
templateUrl: './open-liquidity-channel-modal.component.html',
styleUrls: ['./open-liquidity-channel-modal.component.scss']
})
export class CLNOpenLiquidityChannelComponent implements OnInit, OnDestroy {
public faExclamationTriangle = faExclamationTriangle;
@ViewChild('form', { static: true }) form: any;
public alertTitle: string;
public totalBalance = 0;
public node: LookupNode;
public requestedAmount = 0;
public feeRate = 0;
public localAmount = 0;
public channelConnectionError = '';
public displayedColumns = ['type', 'address', 'port'];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(public dialogRef: MatDialogRef<CLNOpenLiquidityChannelComponent>, @Inject(MAT_DIALOG_DATA) public data: CLNOpenLiquidityChannelAlert, private actions: Actions, private store: Store<RTLState>) { }
ngOnInit() {
this.alertTitle = this.data.alertTitle;
this.totalBalance = this.data.message.balance;
this.node = this.data.message.node;
this.requestedAmount = this.data.message.requestedAmount;
this.feeRate = this.data.message.feeRate;
this.localAmount = this.data.message.localAmount;
this.actions.pipe(
takeUntil(this.unSubs[0]),
filter((action) => action.type === CLNActions.UPDATE_API_CALL_STATUS_CLN || action.type === CLNActions.FETCH_CHANNELS_CLN)).
subscribe((action: any) => {
if (action.type === CLNActions.UPDATE_API_CALL_STATUS_CLN && action.payload.status === APICallStatusEnum.ERROR && action.payload.action === 'SaveNewChannel') {
this.channelConnectionError = action.payload.message;
}
if (action.type === CLNActions.FETCH_CHANNELS_CLN) {
this.dialogRef.close();
}
});
}
onClose() {
this.dialogRef.close(false);
}
resetData() {
this.form.resetForm();
this.form.controls.ramount.setValue(this.data.message.requestedAmount);
this.form.controls.feerate.setValue(this.data.message.feeRate);
this.form.controls.lamount.setValue(this.data.message.localAmount);
this.channelConnectionError = '';
}
onOpenChannel(): boolean | void {
if (!this.node || !this.requestedAmount || !this.feeRate || !this.localAmount) {
return true;
}
const newChannel = { peerId: this.node.nodeid, satoshis: this.requestedAmount.toString(), announce: false, feeRate: this.feeRate + 'perkb' };
this.store.dispatch(saveNewChannel({ payload: newChannel }));
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(null);
completeSub.complete();
});
}
}

View File

@ -24,7 +24,9 @@
<h4 fxLayoutAlign="start" class="font-bold-500">{{obj.title}}</h4>
<span *ngIf="obj && obj.value; else emptyField">
<span [ngSwitch]="obj.type" class="foreground-secondary-text">
<ng-container *ngSwitchCase="dataTypeEnum.ARRAY"><span *ngFor="let arrayObj of obj.value" class="display-block">{{arrayObj}}</span></ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.ARRAY">
<span *ngFor="let arrayObj of obj.value" class="display-block w-100" [innerHTML]="arrayObj"></span>
</ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.DATE_TIME">{{(obj.value * 1000) | date:'dd/MMM/y HH:mm'}}</ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.NUMBER">{{obj.value | number:'1.0-3'}}</ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.BOOLEAN">{{obj.value === true ? 'True' : 'False'}}</ng-container>

View File

@ -1,7 +1,7 @@
import { DataTypeEnum, LoopTypeEnum, PaymentTypes, SwapTypeEnum } from '../services/consts-enums-functions';
import { GetInfoRoot, RTLConfiguration } from './RTLconfig';
import { GetInfo, Invoice, Channel, Peer, PendingOpenChannel, UTXO } from './lndModels';
import { Invoice as InvoiceCLN, GetInfo as GetInfoCLN, Peer as PeerCLN, Channel as ChannelCLN, UTXO as UTXOCLN, Offer as OfferCLN } from './clnModels';
import { Invoice as InvoiceCLN, GetInfo as GetInfoCLN, Peer as PeerCLN, Channel as ChannelCLN, UTXO as UTXOCLN, Offer as OfferCLN, LookupNode as LookupNodeCLN } from './clnModels';
import { GetInfo as GetInfoECL, Peer as PeerECL, Channel as ChannelECL, Invoice as InvoiceECL, PaymentSent as PaymentSentECL } from './eclModels';
import { LoopQuote } from './loopModels';
import { ServiceInfo } from './boltzModels';
@ -69,6 +69,14 @@ export interface CLNOpenChannelAlert {
component?: any;
}
export interface CLNOpenLiquidityChannelAlert {
alertTitle?: string;
titleMessage?: string;
message?: { node: LookupNodeCLN, balance: number, requestedAmount: number, feeRate: number, localAmount: number };
newlyAdded?: boolean;
component?: any;
}
export interface ECLOpenChannelAlert {
alertTitle?: string;
titleMessage?: string;