Configure Peerswap Service #1071

Configure Peerswap Service #1071
This commit is contained in:
ShahanaFarooqui 2022-08-24 00:58:18 -07:00
parent 9bfa04a712
commit 7f00e3de9c
45 changed files with 593 additions and 67 deletions

View File

@ -66,4 +66,5 @@ RTL_CONFIG_PATH (Path for the folder containing 'RTL-Config.json' file, Required
BITCOIND_CONFIG_PATH (Full path of the bitcoind.conf file including the file name, Optional)<br />
CHANNEL_BACKUP_PATH (Folder location for saving the channel backup files, valid for LND implementation only, Required if ln implementation=LND else Optional)<br />
ENABLE_OFFERS (Boolean flag to enable the offers feature on core lighning, default false, optional)<br />
ENABLE_PEERSWAP (Boolean flag to enable the peerswap feature on core lighning, default false, optional)<br />
LN_API_PASSWORD (Password for Eclair implementation if the eclair.conf path is not available, Required if ln implementation=ECL && config path is undefined)<br />

View File

@ -108,6 +108,7 @@ export const getRTLConfig = (req, res, next) => {
settings.swapServerUrl = node.swap_server_url;
settings.boltzServerUrl = node.boltz_server_url;
settings.enableOffers = node.enable_offers;
settings.enablePeerswap = node.enable_peerswap;
settings.channelBackupPath = node.channel_backup_path;
settings.currencyUnit = node.currency_unit;
nodesArr.push({
@ -311,7 +312,7 @@ export const updateServiceSettings = (req, res, next) => {
const RTLConfFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
const config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
const selectedNode = common.findNode(req.session.selectedNode.index);
config.nodes.find((node) => {
config.nodes.forEach((node) => {
if (node.index === req.session.selectedNode.index) {
switch (req.body.service) {
case 'LOOP':
@ -346,6 +347,10 @@ export const updateServiceSettings = (req, res, next) => {
node.Settings.enableOffers = req.body.settings.enableOffers;
selectedNode.enable_offers = req.body.settings.enableOffers;
break;
case 'PEERSWAP':
node.Settings.enablePeerswap = req.body.settings.enablePeerswap;
selectedNode.enable_peerswap = req.body.settings.enablePeerswap;
break;
default:
break;
}

View File

@ -1,5 +1,5 @@
export class CommonSelectedNode {
constructor(options, ln_server_url, macaroon_path, ln_api_password, swap_server_url, boltz_server_url, config_path, rtl_conf_file_path, swap_macaroon_path, boltz_macaroon_path, bitcoind_config_path, channel_backup_path, log_level, log_file, index, ln_node, ln_implementation, user_persona, theme_mode, theme_color, fiat_conversion, currency_unit, ln_version, api_version, enable_offers) {
constructor(options, ln_server_url, macaroon_path, ln_api_password, swap_server_url, boltz_server_url, config_path, rtl_conf_file_path, swap_macaroon_path, boltz_macaroon_path, bitcoind_config_path, channel_backup_path, log_level, log_file, index, ln_node, ln_implementation, user_persona, theme_mode, theme_color, fiat_conversion, currency_unit, ln_version, api_version, enable_offers, enable_peerswap) {
this.options = options;
this.ln_server_url = ln_server_url;
this.macaroon_path = macaroon_path;
@ -25,6 +25,7 @@ export class CommonSelectedNode {
this.ln_version = ln_version;
this.api_version = api_version;
this.enable_offers = enable_offers;
this.enable_peerswap = enable_peerswap;
}
}
export class AuthenticationConfiguration {
@ -35,7 +36,7 @@ export class AuthenticationConfiguration {
}
}
export class NodeSettingsConfiguration {
constructor(userPersona, themeMode, themeColor, fiatConversion, currencyUnit, bitcoindConfigPath, logLevel, lnServerUrl, swapServerUrl, boltzServerUrl, channelBackupPath, enableOffers) {
constructor(userPersona, themeMode, themeColor, fiatConversion, currencyUnit, bitcoindConfigPath, logLevel, lnServerUrl, swapServerUrl, boltzServerUrl, channelBackupPath, enableOffers, enablePeerswap) {
this.userPersona = userPersona;
this.themeMode = themeMode;
this.themeColor = themeColor;
@ -48,6 +49,7 @@ export class NodeSettingsConfiguration {
this.boltzServerUrl = boltzServerUrl;
this.channelBackupPath = channelBackupPath;
this.enableOffers = enableOffers;
this.enablePeerswap = enablePeerswap;
}
}
export class LogJSONObj {

View File

@ -241,6 +241,7 @@ export class ConfigService {
this.common.nodes[idx].boltz_macaroon_path = '';
}
this.common.nodes[idx].enable_offers = process.env.ENABLE_OFFERS ? process.env.ENABLE_OFFERS : (node.Settings.enableOffers) ? node.Settings.enableOffers : false;
this.common.nodes[idx].enable_peerswap = process.env.ENABLE_PEERSWAP ? process.env.ENABLE_PEERSWAP : (node.Settings.enablePeerswap) ? node.Settings.enablePeerswap : false;
this.common.nodes[idx].bitcoind_config_path = process.env.BITCOIND_CONFIG_PATH ? process.env.BITCOIND_CONFIG_PATH : (node.Settings.bitcoindConfigPath) ? node.Settings.bitcoindConfigPath : '';
this.common.nodes[idx].channel_backup_path = process.env.CHANNEL_BACKUP_PATH ? process.env.CHANNEL_BACKUP_PATH : (node.Settings.channelBackupPath) ? node.Settings.channelBackupPath : this.common.rtl_conf_file_path + sep + 'channels-backup' + sep + 'node-' + node.index;
try {

View File

@ -109,6 +109,7 @@ export const getRTLConfig = (req, res, next) => {
settings.swapServerUrl = node.swap_server_url;
settings.boltzServerUrl = node.boltz_server_url;
settings.enableOffers = node.enable_offers;
settings.enablePeerswap = node.enable_peerswap;
settings.channelBackupPath = node.channel_backup_path;
settings.currencyUnit = node.currency_unit;
nodesArr.push({
@ -306,7 +307,7 @@ export const updateServiceSettings = (req, res, next) => {
const RTLConfFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
const config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
const selectedNode = common.findNode(req.session.selectedNode.index);
config.nodes.find((node) => {
config.nodes.forEach((node) => {
if (node.index === req.session.selectedNode.index) {
switch (req.body.service) {
case 'LOOP':
@ -342,6 +343,11 @@ export const updateServiceSettings = (req, res, next) => {
selectedNode.enable_offers = req.body.settings.enableOffers;
break;
case 'PEERSWAP':
node.Settings.enablePeerswap = req.body.settings.enablePeerswap;
selectedNode.enable_peerswap = req.body.settings.enablePeerswap;
break;
default:
break;
}

View File

@ -25,7 +25,8 @@ export class CommonSelectedNode {
public currency_unit?: string,
public ln_version?: string,
public api_version?: string,
public enable_offers?: boolean
public enable_offers?: boolean,
public enable_peerswap?: boolean
) { }
}
@ -54,7 +55,8 @@ export class NodeSettingsConfiguration {
public swapServerUrl?: string,
public boltzServerUrl?: string,
public channelBackupPath?: string,
public enableOffers?: boolean
public enableOffers?: boolean,
public enablePeerswap?: boolean
) { }
}

View File

@ -226,6 +226,7 @@ export class ConfigService {
this.common.nodes[idx].boltz_macaroon_path = '';
}
this.common.nodes[idx].enable_offers = process.env.ENABLE_OFFERS ? process.env.ENABLE_OFFERS : (node.Settings.enableOffers) ? node.Settings.enableOffers : false;
this.common.nodes[idx].enable_peerswap = process.env.ENABLE_PEERSWAP ? process.env.ENABLE_PEERSWAP : (node.Settings.enablePeerswap) ? node.Settings.enablePeerswap : false;
this.common.nodes[idx].bitcoind_config_path = process.env.BITCOIND_CONFIG_PATH ? process.env.BITCOIND_CONFIG_PATH : (node.Settings.bitcoindConfigPath) ? node.Settings.bitcoindConfigPath : '';
this.common.nodes[idx].channel_backup_path = process.env.CHANNEL_BACKUP_PATH ? process.env.CHANNEL_BACKUP_PATH : (node.Settings.channelBackupPath) ? node.Settings.channelBackupPath : this.common.rtl_conf_file_path + sep + 'channels-backup' + sep + 'node-' + node.index;
try {

View File

@ -11,15 +11,21 @@ import { NodeSettingsComponent } from './shared/components/node-config/node-sett
import { ServicesSettingsComponent } from './shared/components/node-config/services-settings/services-settings.component';
import { LoopServiceSettingsComponent } from './shared/components/node-config/services-settings/loop-service-settings/loop-service-settings.component';
import { BoltzServiceSettingsComponent } from './shared/components/node-config/services-settings/boltz-service-settings/boltz-service-settings.component';
import { ServicesComponent } from './shared/components/services/services.component';
import { LoopComponent } from './shared/components/services/loop/loop.component';
import { BoltzRootComponent } from './shared/components/services/boltz/boltz-root.component';
import { LNServicesComponent } from './shared/components/ln-services/ln-services.component';
import { LoopComponent } from './shared/components/ln-services/loop/loop.component';
import { BoltzRootComponent } from './shared/components/ln-services/boltz/boltz-root.component';
import { HelpComponent } from './shared/components/help/help.component';
import { LoginComponent } from './shared/components/login/login.component';
import { NotFoundComponent } from './shared/components/not-found/not-found.component';
import { ErrorComponent } from './shared/components/error/error.component';
import { AuthGuard } from './shared/services/auth.guard';
import { ExperimentalSettingsComponent } from './shared/components/node-config/experimental-settings/experimental-settings.component';
import { PeerswapComponent } from './shared/components/ln-services/peerswap/peerswap.component';
import { PeerswapServiceSettingsComponent } from './shared/components/node-config/services-settings/peerswap-service-settings/peerswap-service-settings.component';
import { SwapPeersComponent } from './shared/components/ln-services/peerswap/swap-peers/swap-peers.component';
import { PeerswapsOutComponent } from './shared/components/ln-services/peerswap/swaps-out/swaps-out.component';
import { PeerswapsInComponent } from './shared/components/ln-services/peerswap/swaps-in/swaps-in.component';
import { PeerswapsCancelledComponent } from './shared/components/ln-services/peerswap/swaps-cancelled/swaps-cancelled.component';
export const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'login' },
@ -42,7 +48,8 @@ export const routes: Routes = [
path: 'services', component: ServicesSettingsComponent, canActivate: [AuthGuard], children: [
{ path: '', pathMatch: 'full', redirectTo: 'loop' },
{ path: 'loop', component: LoopServiceSettingsComponent, canActivate: [AuthGuard] },
{ path: 'boltz', component: BoltzServiceSettingsComponent, canActivate: [AuthGuard] }
{ path: 'boltz', component: BoltzServiceSettingsComponent, canActivate: [AuthGuard] },
{ path: 'peerswap', component: PeerswapServiceSettingsComponent, canActivate: [AuthGuard] }
]
},
{ path: 'experimental', component: ExperimentalSettingsComponent, canActivate: [AuthGuard] },
@ -50,12 +57,21 @@ export const routes: Routes = [
]
},
{
path: 'services', component: ServicesComponent, canActivate: [AuthGuard], children: [
path: 'services', component: LNServicesComponent, canActivate: [AuthGuard], children: [
{ path: '', pathMatch: 'full', redirectTo: 'loop' },
{ path: 'loop', pathMatch: 'full', redirectTo: 'loop/loopout' },
{ path: 'loop/:selTab', component: LoopComponent },
{ path: 'boltz', pathMatch: 'full', redirectTo: 'boltz/swapout' },
{ path: 'boltz/:selTab', component: BoltzRootComponent }
{ path: 'boltz/:selTab', component: BoltzRootComponent },
{
path: 'peerswap', component: PeerswapComponent, canActivate: [AuthGuard], children: [
{ path: '', pathMatch: 'full', redirectTo: 'peers' },
{ path: 'peers', component: SwapPeersComponent, canActivate: [AuthGuard] },
{ path: 'psout', component: PeerswapsOutComponent, canActivate: [AuthGuard] },
{ path: 'psin', component: PeerswapsInComponent, canActivate: [AuthGuard] },
{ path: 'pscancelled', component: PeerswapsCancelledComponent, canActivate: [AuthGuard] }
]
},
]
},
{ path: 'help', component: HelpComponent },

View File

@ -45,7 +45,7 @@ export const initCLNState: CLNState = {
FetchOffers: { status: APICallStatusEnum.UN_INITIATED },
FetchOfferBookmarks: { status: APICallStatusEnum.UN_INITIATED }
},
nodeSettings: { userPersona: UserPersonaEnum.OPERATOR, selCurrencyUnit: 'USD', fiatConversion: false, channelBackupPath: '', currencyUnits: [], enableOffers: false },
nodeSettings: { userPersona: UserPersonaEnum.OPERATOR, selCurrencyUnit: 'USD', fiatConversion: false, channelBackupPath: '', currencyUnits: [], enableOffers: false, enablePeerswap: false },
information: {},
fees: {},
feeRatesPerKB: {},

View File

@ -0,0 +1,16 @@
<div fxLayout="row" fxLayoutAlign="start center" class="page-title-container">
<fa-icon [icon]="faHandshake" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Peerswap</span>
</div>
<div fxLayout="column" class="padding-gap-x">
<mat-card>
<mat-card-content fxLayout="column">
<nav mat-tab-nav-bar>
<div role="tab" mat-tab-link *ngFor="let link of links" class="mat-tab-label" [active]="activeTab.link === link.link" (click)="activeTab = link" routerLink="{{link.link}}">{{link.name}}</div>
</nav>
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="mat-tab-body-wrapper mb-2">
<router-outlet></router-outlet>
</div>
</mat-card-content>
</mat-card>
</div>

View File

@ -0,0 +1,52 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { StoreModule } from '@ngrx/store';
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 { LoopService } from '../../../services/loop.service';
import { PeerswapComponent } from './peerswap.component';
import { SharedModule } from '../../../shared.module';
import { mockDataService } from '../../../test-helpers/mock-services';
import { CommonService } from '../../../services/common.service';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { DataService } from '../../../services/data.service';
describe('PeerswapComponent', () => {
let component: PeerswapComponent;
let fixture: ComponentFixture<PeerswapComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [PeerswapComponent],
imports: [
BrowserAnimationsModule,
SharedModule,
RouterTestingModule,
StoreModule.forRoot({ root: RootReducer, lnd: LNDReducer, cln: CLNReducer, ecl: ECLReducer })
],
providers: [
CommonService,
{ provide: DataService, useClass: mockDataService }
]
}).
compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PeerswapComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
afterEach(() => {
TestBed.resetTestingModule();
});
});

View File

@ -0,0 +1,41 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ResolveEnd, Event } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { faHandshake } from '@fortawesome/free-solid-svg-icons';
@Component({
selector: 'rtl-peerswap',
templateUrl: './peerswap.component.html',
styleUrls: ['./peerswap.component.scss']
})
export class PeerswapComponent implements OnInit, OnDestroy {
public faHandshake = faHandshake;
public links = [{ link: 'peers', name: 'Peers' }, { link: 'psout', name: 'Peerswap Out' }, { link: 'psin', name: 'Peerswap In' }, { link: 'pscancelled', name: 'Cancelled Peerswaps' }];
public activeTab = this.links[0];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private router: Router) { }
ngOnInit() {
const linkFound = this.links.find((link) => this.router.url.includes(link.link));
this.activeTab = linkFound ? linkFound : this.links[0];
this.router.events.pipe(takeUntil(this.unSubs[0]), filter((e) => e instanceof ResolveEnd)).
subscribe({
next: (value: ResolveEnd | Event) => {
const linkFound = this.links.find((link) => (<ResolveEnd>value).urlAfterRedirects.includes(link.link));
this.activeTab = linkFound ? linkFound : this.links[0];
}
});
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null);
completeSub.complete();
});
}
}

View File

@ -0,0 +1 @@
<h1>Swap Peers</h1>

View File

@ -0,0 +1,35 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { SharedModule } from '../../../../shared.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SwapPeersComponent } from './swap-peers.component';
describe('SwapPeersComponent', () => {
let component: SwapPeersComponent;
let fixture: ComponentFixture<SwapPeersComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [SwapPeersComponent],
imports: [
BrowserAnimationsModule,
SharedModule
],
providers: []
}).
compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SwapPeersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
afterEach(() => {
TestBed.resetTestingModule();
});
});

View File

@ -0,0 +1,25 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
@Component({
selector: 'rtl-peerswap-peers',
templateUrl: './swap-peers.component.html',
styleUrls: ['./swap-peers.component.scss']
})
export class SwapPeersComponent implements OnInit, OnDestroy {
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor() {}
ngOnInit() {
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null);
completeSub.complete();
});
}
}

View File

@ -0,0 +1 @@
<h1>Peerswaps Cancelled</h1>

View File

@ -0,0 +1,35 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { SharedModule } from '../../../../shared.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { PeerswapsCancelledComponent } from './swaps-cancelled.component';
describe('PeerswapsCancelledComponent', () => {
let component: PeerswapsCancelledComponent;
let fixture: ComponentFixture<PeerswapsCancelledComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [PeerswapsCancelledComponent],
imports: [
BrowserAnimationsModule,
SharedModule
],
providers: []
}).
compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PeerswapsCancelledComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
afterEach(() => {
TestBed.resetTestingModule();
});
});

View File

@ -0,0 +1,25 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
@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() {}
ngOnInit() {
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null);
completeSub.complete();
});
}
}

View File

@ -0,0 +1 @@
<h1>Peerswaps In</h1>

View File

@ -0,0 +1,35 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { SharedModule } from '../../../../shared.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { PeerswapsInComponent } from './swaps-in.component';
describe('PeerswapsInComponent', () => {
let component: PeerswapsInComponent;
let fixture: ComponentFixture<PeerswapsInComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [PeerswapsInComponent],
imports: [
BrowserAnimationsModule,
SharedModule
],
providers: []
}).
compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PeerswapsInComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
afterEach(() => {
TestBed.resetTestingModule();
});
});

View File

@ -0,0 +1,25 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
@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() {}
ngOnInit() {
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null);
completeSub.complete();
});
}
}

View File

@ -0,0 +1 @@
<h1>Peerswaps Out</h1>

View File

@ -0,0 +1,35 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { SharedModule } from '../../../../shared.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { PeerswapsOutComponent } from './swaps-out.component';
describe('PeerswapsOutComponent', () => {
let component: PeerswapsOutComponent;
let fixture: ComponentFixture<PeerswapsOutComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [PeerswapsOutComponent],
imports: [
BrowserAnimationsModule,
SharedModule
],
providers: []
}).
compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PeerswapsOutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
afterEach(() => {
TestBed.resetTestingModule();
});
});

View File

@ -0,0 +1,25 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
@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() {}
ngOnInit() {
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null);
completeSub.complete();
});
}
}

View File

@ -35,8 +35,8 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
faEye = faEye;
public appConfig: RTLConfiguration;
public selConfigNodeIndex: Number;
public selNode: ConfigSettingsNode;
public settings: Settings;
public selNode: ConfigSettingsNode | any;
public settings: Settings | null;
public version = '';
public information: GetInfoRoot = {};
public informationChain: GetInfoChain = {};
@ -74,7 +74,7 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
this.appConfig = appConfig;
});
this.store.select(rootSelNodeAndNodeData).pipe(takeUntil(this.unSubs[1])).
subscribe((rootData: { nodeDate: GetInfoRoot, selNode: ConfigSettingsNode }) => {
subscribe((rootData: { nodeDate: GetInfoRoot, selNode: ConfigSettingsNode | null }) => {
this.information = rootData.nodeDate;
if (this.information.identity_pubkey) {
if (this.information.chains && typeof this.information.chains[0] === 'string') {
@ -94,8 +94,8 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
this.smallScreen = true;
}
this.selNode = rootData.selNode;
this.settings = this.selNode.settings;
this.selConfigNodeIndex = +(rootData.selNode.index || 0);
this.settings = this.selNode?.settings || null;
this.selConfigNodeIndex = +(rootData.selNode?.index || 0);
if (this.selNode && this.selNode.lnImplementation) {
this.filterSideMenuNodes();
}
@ -143,7 +143,7 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
}
filterSideMenuNodes() {
switch (this.selNode.lnImplementation?.toUpperCase()) {
switch (this.selNode?.lnImplementation?.toUpperCase()) {
case 'CLN':
this.loadCLNMenu();
break;
@ -163,12 +163,12 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
clonedMenu = JSON.parse(JSON.stringify(MENU_DATA.LNDChildren));
this.navMenus.data = clonedMenu?.filter((navMenuData: any) => {
if (navMenuData.children && navMenuData.children.length) {
navMenuData.children = navMenuData.children?.filter((navMenuChild) => ((navMenuChild.userPersona === UserPersonaEnum.ALL || navMenuChild.userPersona === this.settings.userPersona) && navMenuChild.link !== '/services/loop' && navMenuChild.link !== '/services/boltz') ||
(navMenuChild.link === '/services/loop' && this.settings.swapServerUrl && this.settings.swapServerUrl.trim() !== '') ||
(navMenuChild.link === '/services/boltz' && this.settings.boltzServerUrl && this.settings.boltzServerUrl.trim() !== ''));
navMenuData.children = navMenuData.children?.filter((navMenuChild) => ((navMenuChild.userPersona === UserPersonaEnum.ALL || navMenuChild.userPersona === this.settings?.userPersona) && navMenuChild.link !== '/services/loop' && navMenuChild.link !== '/services/boltz') ||
(navMenuChild.link === '/services/loop' && this.settings?.swapServerUrl && this.settings.swapServerUrl.trim() !== '') ||
(navMenuChild.link === '/services/boltz' && this.settings?.boltzServerUrl && this.settings.boltzServerUrl.trim() !== ''));
return navMenuData.children.length > 0;
}
return navMenuData.userPersona === UserPersonaEnum.ALL || navMenuData.userPersona === this.settings.userPersona;
return navMenuData.userPersona === UserPersonaEnum.ALL || navMenuData.userPersona === this.settings?.userPersona;
});
}
@ -177,10 +177,11 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
clonedMenu = JSON.parse(JSON.stringify(MENU_DATA.CLNChildren));
this.navMenus.data = clonedMenu?.filter((navMenuData: any) => {
if (navMenuData.children && navMenuData.children.length) {
navMenuData.children = navMenuData.children?.filter((navMenuChild) => ((navMenuChild.userPersona === UserPersonaEnum.ALL || navMenuChild.userPersona === this.settings.userPersona) && navMenuChild.link !== '/cln/messages') ||
(navMenuChild.link === '/cln/messages' && this.information.api_version && this.commonService.isVersionCompatible(this.information.api_version, '0.2.2')));
navMenuData.children = navMenuData.children?.filter((navMenuChild) => ((navMenuChild.userPersona === UserPersonaEnum.ALL || navMenuChild.userPersona === this.settings?.userPersona) && navMenuChild.link !== '/services/peerswap') ||
(navMenuChild.link === '/services/peerswap' && this.settings?.enablePeerswap));
return navMenuData.children.length > 0;
}
return navMenuData.userPersona === UserPersonaEnum.ALL || navMenuData.userPersona === this.settings.userPersona;
return navMenuData.userPersona === UserPersonaEnum.ALL || navMenuData.userPersona === this.settings?.userPersona;
});
}

View File

@ -7,7 +7,7 @@
<mat-card-content fxLayout="column">
<nav mat-tab-nav-bar>
<div role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[0].link" (click)="activeLink = links[0].link" routerLink="{{links[0].link}}">{{links[0].name}}</div>
<div role="tab" mat-tab-link *ngIf="selNode?.lnImplementation?.toUpperCase() === 'LND'" class="mat-tab-label" [active]="activeLink === links[1].link" (click)="activeLink = links[1].link" routerLink="{{links[1].link}}" [state]="{ initial: false }">{{links[1].name}}</div>
<div role="tab" mat-tab-link *ngIf="selNode?.lnImplementation?.toUpperCase() === 'LND' || selNode?.lnImplementation?.toUpperCase() === 'CLN'" class="mat-tab-label" [active]="activeLink === links[1].link" (click)="activeLink = links[1].link" routerLink="{{links[1].link}}" [state]="{ initial: false }">{{links[1].name}}</div>
<div role="tab" mat-tab-link *ngIf="selNode?.lnImplementation?.toUpperCase() === 'CLN'" class="mat-tab-label" [active]="activeLink === links[2].link" (click)="activeLink = links[2].link" routerLink="{{links[2].link}}">{{links[2].name}}</div>
<div role="tab" mat-tab-link *ngIf="showLnConfig" class="mat-tab-label" [active]="activeLink === links[3].link" (click)="activeLink = links[3].link" routerLink="{{links[3].link}}">{{links[3].name}}</div>
</nav>

View File

@ -18,7 +18,7 @@ export class NodeConfigComponent implements OnInit, OnDestroy {
public faTools = faTools;
public showLnConfig = false;
public selNode: ConfigSettingsNode;
public selNode: ConfigSettingsNode | any;
public lnImplementationStr = '';
public links = [{ link: 'layout', name: 'Layout' }, { link: 'services', name: 'Services' }, { link: 'experimental', name: 'Experimental' }, { link: 'lnconfig', name: this.lnImplementationStr }];
public activeLink = '';

View File

@ -0,0 +1,15 @@
<div [perfectScrollbar] fxLayout="column" fxFlex="100">
<div fxFlex="100" class="alert alert-info mt-1">
<fa-icon [icon]="faInfoCircle" class="mr-1 alert-icon"></fa-icon>
<span>Please ensure that <strong>peerswapd</strong> is running and accessible to RTL before enabling this service. Click <strong><a href="https://github.com/ElementsProject/peerswap" target="_blank">here</a></strong> to learn more about Core Lightning peerswap.</span>
</div>
<form fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" class="settings-container page-sub-title-container mt-1" #form="ngForm">
<div fxLayout="column" fxFlex="50" fxLayoutAlign="start stretch">
<mat-slide-toggle autoFocus class="mb-1" tabindex="1" color="primary" [(ngModel)]="enablePeerswap" name="peerswap">Enable Peerswap Service</mat-slide-toggle>
</div>
</form>
<div fxLayout="row" class="mt-2">
<!-- <button class="mr-1" mat-stroked-button color="primary" type="reset" (click)="onReset()" tabindex="4">Reset</button> -->
<button mat-flat-button color="primary" type="submit" (click)="onUpdateService()" tabindex="5">Update</button>
</div>
</div>

View File

@ -0,0 +1,70 @@
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { ServicesEnum, UI_MESSAGES } from '../../../../services/consts-enums-functions';
import { ConfigSettingsNode } from '../../../../models/RTLconfig';
import { LoggerService } from '../../../../services/logger.service';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
import { updateServiceSettings } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state';
import { setChildNodeSettingsLND } from '../../../../../lnd/store/lnd.actions';
import { setChildNodeSettingsCL } from '../../../../../cln/store/cln.actions';
import { setChildNodeSettingsECL } from '../../../../../eclair/store/ecl.actions';
import { rootSelectedNode } from '../../../../../store/rtl.selector';
@Component({
selector: 'rtl-peerswap-service-settings',
templateUrl: './peerswap-service-settings.component.html',
styleUrls: ['./peerswap-service-settings.component.scss']
})
export class PeerswapServiceSettingsComponent implements OnInit, OnDestroy {
public faInfoCircle = faInfoCircle;
public selNode: ConfigSettingsNode | any;
public enablePeerswap = false;
unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>) { }
ngOnInit() {
this.store.select(rootSelectedNode).
pipe(takeUntil(this.unSubs[0])).
subscribe((selNode) => {
this.selNode = selNode;
this.enablePeerswap = !!selNode?.settings.enablePeerswap;
this.logger.info(selNode);
});
}
onUpdateService(): boolean | void {
this.store.dispatch(updateServiceSettings({ payload: { uiMessage: UI_MESSAGES.UPDATE_PEERSWAP_SETTINGS, service: ServicesEnum.PEERSWAP, settings: { enablePeerswap: this.enablePeerswap } } }));
this.store.dispatch(setChildNodeSettingsLND({
payload: {
userPersona: this.selNode.settings.userPersona, channelBackupPath: this.selNode.settings.channelBackupPath, selCurrencyUnit: this.selNode.settings.currencyUnit, currencyUnits: this.selNode.settings.currencyUnits, fiatConversion: this.selNode.settings.fiatConversion,
lnImplementation: this.selNode.lnImplementation, swapServerUrl: this.selNode.settings.swapServerUrl, boltzServerUrl: this.selNode.settings.boltzServerUrl, enableOffers: this.selNode.settings.enableOffers, enablePeerswap: this.selNode.settings.enablePeerswap
}
}));
this.store.dispatch(setChildNodeSettingsCL({
payload: {
userPersona: this.selNode.settings.userPersona, channelBackupPath: this.selNode.settings.channelBackupPath, selCurrencyUnit: this.selNode.settings.currencyUnit, currencyUnits: this.selNode.settings.currencyUnits, fiatConversion: this.selNode.settings.fiatConversion,
lnImplementation: this.selNode.lnImplementation, swapServerUrl: this.selNode.settings.swapServerUrl, boltzServerUrl: this.selNode.settings.boltzServerUrl, enableOffers: this.selNode.settings.enableOffers, enablePeerswap: this.selNode.settings.enablePeerswap
}
}));
this.store.dispatch(setChildNodeSettingsECL({
payload: {
userPersona: this.selNode.settings.userPersona, channelBackupPath: this.selNode.settings.channelBackupPath, selCurrencyUnit: this.selNode.settings.currencyUnit, currencyUnits: this.selNode.settings.currencyUnits, fiatConversion: this.selNode.settings.fiatConversion,
lnImplementation: this.selNode.lnImplementation, swapServerUrl: this.selNode.settings.swapServerUrl, boltzServerUrl: this.selNode.settings.boltzServerUrl, enableOffers: this.selNode.settings.enableOffers, enablePeerswap: this.selNode.settings.enablePeerswap
}
}));
}
ngOnDestroy() {
this.unSubs.forEach((unsub) => {
unsub.next();
unsub.complete();
});
}
}

View File

@ -6,8 +6,9 @@
<mat-card>
<mat-card-content fxLayout="column">
<nav mat-tab-nav-bar>
<div role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[0].link" (click)="activeLink = links[0].link" routerLink="{{links[0].link}}">{{links[0].name}}</div>
<div role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[1].link" (click)="activeLink = links[1].link" routerLink="{{links[1].link}}" [state]="{ initial: false }">{{links[1].name}}</div>
<div *ngIf="selNode?.lnImplementation?.toUpperCase() === 'LND'" role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[0].link" (click)="activeLink = links[0].link" routerLink="{{links[0].link}}">{{links[0].name}}</div>
<div *ngIf="selNode?.lnImplementation?.toUpperCase() === 'LND'" role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[1].link" (click)="activeLink = links[1].link" routerLink="{{links[1].link}}" [state]="{ initial: false }">{{links[1].name}}</div>
<div *ngIf="selNode?.lnImplementation?.toUpperCase() === 'CLN'" role="tab" mat-tab-link class="mat-tab-label" [active]="activeLink === links[2].link" (click)="activeLink = links[2].link" routerLink="{{links[2].link}}">{{links[2].name}}</div>
</nav>
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch" class="mat-tab-body-wrapper">
<router-outlet></router-outlet>

View File

@ -1,8 +1,12 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ResolveEnd, Event } from '@angular/router';
import { Router, ResolveEnd, Event, ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { faLayerGroup } from '@fortawesome/free-solid-svg-icons';
import { ConfigSettingsNode } from '../../../models/RTLconfig';
import { Store } from '@ngrx/store';
import { RTLState } from '../../../../store/rtl.state';
import { rootSelectedNode } from '../../../../store/rtl.selector';
@Component({
selector: 'rtl-services-settings',
@ -12,11 +16,12 @@ import { faLayerGroup } from '@fortawesome/free-solid-svg-icons';
export class ServicesSettingsComponent implements OnInit, OnDestroy {
public faLayerGroup = faLayerGroup;
public links = [{ link: 'loop', name: 'Loop' }, { link: 'boltz', name: 'Boltz' }];
public links = [{ link: 'loop', name: 'Loop' }, { link: 'boltz', name: 'Boltz' }, { link: 'peerswap', name: 'Peerswap' }];
public activeLink = '';
public selNode: ConfigSettingsNode | any;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private router: Router) { }
constructor(private store: Store<RTLState>, private router: Router, private activatedRoute: ActivatedRoute) { }
ngOnInit() {
const linkFound = this.links.find((link) => this.router.url.includes(link.link));
@ -25,9 +30,20 @@ export class ServicesSettingsComponent implements OnInit, OnDestroy {
subscribe({
next: (value: ResolveEnd | Event) => {
const linkFound = this.links.find((link) => (<ResolveEnd>value).urlAfterRedirects.includes(link.link));
this.activeLink = linkFound ? linkFound.link : this.links[0].link;
if(this.selNode.lnImplementation.toUpperCase() === 'CLN') {
this.activeLink = this.links[2].link;
} else {
this.activeLink = linkFound ? linkFound.link : this.links[0].link;
}
}
});
this.store.select(rootSelectedNode).pipe(takeUntil(this.unSubs[1])).subscribe((selNode) => {
this.selNode = selNode;
if (this.selNode.lnImplementation.toUpperCase() === 'CLN') {
this.activeLink = this.links[2].link;
this.router.navigate(['./' + this.activeLink], { relativeTo: this.activatedRoute });
}
});
}
ngOnDestroy() {

View File

@ -24,7 +24,8 @@ export class Settings {
public boltzServerUrl?: string,
public channelBackupPath?: string,
public currencyUnit?: string,
public enableOffers?: boolean
public enableOffers?: boolean,
public enablePeerswap?: boolean
) { }
}
@ -84,6 +85,7 @@ export interface SelNodeChild {
swapServerUrl?: string;
boltzServerUrl?: string;
enableOffers?: boolean;
enablePeerswap?: boolean;
}
export class HelpTopic {

View File

@ -1,4 +1,4 @@
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faMapSigns, faQuestion, faSearch, faChartBar, faTools, faProjectDiagram, faDownload, faServer, faPercentage, faInfinity, faUserCheck, faLayerGroup, faBullhorn } from '@fortawesome/free-solid-svg-icons';
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faMapSigns, faQuestion, faSearch, faChartBar, faTools, faProjectDiagram, faDownload, faServer, faPercentage, faInfinity, faUserCheck, faLayerGroup, faBullhorn, faHandshake } from '@fortawesome/free-solid-svg-icons';
import { UserPersonaEnum } from '../services/consts-enums-functions';
export class MenuChildNode {
@ -64,8 +64,13 @@ export const MENU_DATA: MenuRootNode = {
{ id: 39, parentId: 3, name: 'Node/Fee Rates', iconType: 'FA', icon: faServer, link: '/cln/rates', userPersona: UserPersonaEnum.MERCHANT }
]
},
{ id: 4, parentId: 0, name: 'Node Config', iconType: 'FA', icon: faTools, link: '/config', userPersona: UserPersonaEnum.ALL },
{ id: 5, parentId: 0, name: 'Help', iconType: 'FA', icon: faQuestion, link: '/help', userPersona: UserPersonaEnum.ALL }
{
id: 4, parentId: 0, name: 'Services', iconType: 'FA', icon: faLayerGroup, link: '/services/peerswap', userPersona: UserPersonaEnum.ALL, children: [
{ id: 41, parentId: 4, name: 'Peerswap', iconType: 'FA', icon: faHandshake, link: '/services/peerswap', userPersona: UserPersonaEnum.ALL },
]
},
{ id: 5, parentId: 0, name: 'Node Config', iconType: 'FA', icon: faTools, link: '/config', userPersona: UserPersonaEnum.ALL },
{ id: 6, parentId: 0, name: 'Help', iconType: 'FA', icon: faQuestion, link: '/help', userPersona: UserPersonaEnum.ALL }
],
ECLChildren: [
{ id: 1, parentId: 0, name: 'Dashboard', iconType: 'FA', icon: faTachometerAlt, link: '/ecl/home', userPersona: UserPersonaEnum.ALL },

View File

@ -243,7 +243,8 @@ export const SCROLL_RANGES = ['MONTHLY', 'YEARLY'];
export enum ServicesEnum {
LOOP = 'LOOP',
BOLTZ = 'BOLTZ',
OFFERS = 'OFFERS'
OFFERS = 'OFFERS',
PEERSWAP = 'PEERSWAP'
}
export const PASSWORD_BLACKLIST = ['password', 'changeme', 'moneyprintergobrrr'];
@ -296,6 +297,7 @@ export const UI_MESSAGES = {
WAIT_SYNC_NODE: 'Waiting for Node Sync...',
UPDATE_BOLTZ_SETTINGS: 'Updating Boltz Service Settings...',
UPDATE_LOOP_SETTINGS: 'Updating Loop Service Settings...',
UPDATE_PEERSWAP_SETTINGS: 'Updating Peerswap Service Settings...',
UPDATE_SETTING: 'Updating Setting...',
UPDATE_UI_SETTINGS: 'Updating Settings...',
UPDATE_NODE_SETTINGS: 'Updating Node Settings...',

View File

@ -65,6 +65,7 @@ import { NodeSettingsComponent } from './components/node-config/node-settings/no
import { ServicesSettingsComponent } from './components/node-config/services-settings/services-settings.component';
import { LoopServiceSettingsComponent } from './components/node-config/services-settings/loop-service-settings/loop-service-settings.component';
import { BoltzServiceSettingsComponent } from './components/node-config/services-settings/boltz-service-settings/boltz-service-settings.component';
import { PeerswapServiceSettingsComponent } from './components/node-config/services-settings/peerswap-service-settings/peerswap-service-settings.component';
import { ExperimentalSettingsComponent } from './components/node-config/experimental-settings/experimental-settings.component';
import { ErrorComponent } from './components/error/error.component';
import { CurrencyUnitConverterComponent } from './components/currency-unit-converter/currency-unit-converter.component';
@ -79,21 +80,26 @@ import { ErrorMessageComponent } from './components/data-modal/error-message/err
import { TwoFactorAuthComponent } from './components/data-modal/two-factor-auth/two-factor-auth.component';
import { LoginTokenComponent } from './components/data-modal/login-2fa-token/login-2fa-token.component';
import { ServicesComponent } from './components/services/services.component';
import { LoopComponent } from '../shared/components/services/loop/loop.component';
import { SwapsComponent } from '../shared/components/services/loop/swaps/swaps.component';
import { LoopModalComponent } from '../shared/components/services/loop/loop-modal/loop-modal.component';
import { LoopQuoteComponent } from '../shared/components/services/loop/loop-quote/loop-quote.component';
import { LoopStatusComponent } from '../shared/components/services/loop/loop-status/loop-status.component';
import { LoopOutInfoGraphicsComponent } from '../shared/components/services/loop/loop-out-info-graphics/info-graphics.component';
import { LoopInInfoGraphicsComponent } from '../shared/components/services/loop/loop-in-info-graphics/info-graphics.component';
import { BoltzRootComponent } from './components/services/boltz/boltz-root.component';
import { BoltzSwapsComponent } from './components/services/boltz/swaps/swaps.component';
import { SwapStatusComponent } from './components/services/boltz/swap-status/swap-status.component';
import { SwapServiceInfoComponent } from './components/services/boltz/swap-service-info/swap-service-info.component';
import { SwapModalComponent } from './components/services/boltz/swap-modal/swap-modal.component';
import { SwapInInfoGraphicsComponent } from './components/services/boltz/swap-in-info-graphics/info-graphics.component';
import { SwapOutInfoGraphicsComponent } from './components/services/boltz/swap-out-info-graphics/info-graphics.component';
import { LNServicesComponent } from './components/ln-services/ln-services.component';
import { LoopComponent } from '../shared/components/ln-services/loop/loop.component';
import { SwapsComponent } from '../shared/components/ln-services/loop/swaps/swaps.component';
import { LoopModalComponent } from '../shared/components/ln-services/loop/loop-modal/loop-modal.component';
import { LoopQuoteComponent } from '../shared/components/ln-services/loop/loop-quote/loop-quote.component';
import { LoopStatusComponent } from '../shared/components/ln-services/loop/loop-status/loop-status.component';
import { LoopOutInfoGraphicsComponent } from '../shared/components/ln-services/loop/loop-out-info-graphics/info-graphics.component';
import { LoopInInfoGraphicsComponent } from '../shared/components/ln-services/loop/loop-in-info-graphics/info-graphics.component';
import { BoltzRootComponent } from './components/ln-services/boltz/boltz-root.component';
import { BoltzSwapsComponent } from './components/ln-services/boltz/swaps/swaps.component';
import { SwapStatusComponent } from './components/ln-services/boltz/swap-status/swap-status.component';
import { SwapServiceInfoComponent } from './components/ln-services/boltz/swap-service-info/swap-service-info.component';
import { SwapModalComponent } from './components/ln-services/boltz/swap-modal/swap-modal.component';
import { SwapInInfoGraphicsComponent } from './components/ln-services/boltz/swap-in-info-graphics/info-graphics.component';
import { SwapOutInfoGraphicsComponent } from './components/ln-services/boltz/swap-out-info-graphics/info-graphics.component';
import { PeerswapComponent } from './components/ln-services/peerswap/peerswap.component';
import { SwapPeersComponent } from './components/ln-services/peerswap/swap-peers/swap-peers.component';
import { PeerswapsCancelledComponent } from './components/ln-services/peerswap/swaps-cancelled/swaps-cancelled.component';
import { PeerswapsInComponent } from './components/ln-services/peerswap/swaps-in/swaps-in.component';
import { PeerswapsOutComponent } from './components/ln-services/peerswap/swaps-out/swaps-out.component';
import { ClipboardDirective } from './directive/clipboard.directive';
import { AutoFocusDirective } from './directive/auto-focus.directive';
@ -244,11 +250,12 @@ export const DEFAULT_DATE_FORMAT: MatDateFormats = {
ServicesSettingsComponent,
LoopServiceSettingsComponent,
BoltzServiceSettingsComponent,
PeerswapServiceSettingsComponent,
ExperimentalSettingsComponent,
CurrencyUnitConverterComponent,
HorizontalScrollerComponent,
TransactionsReportTableComponent,
ServicesComponent,
LNServicesComponent,
LoopComponent,
SwapsComponent,
LoopModalComponent,
@ -262,7 +269,12 @@ export const DEFAULT_DATE_FORMAT: MatDateFormats = {
SwapServiceInfoComponent,
SwapModalComponent,
SwapInInfoGraphicsComponent,
SwapOutInfoGraphicsComponent
SwapOutInfoGraphicsComponent,
PeerswapComponent,
SwapPeersComponent,
PeerswapsCancelledComponent,
PeerswapsInComponent,
PeerswapsOutComponent
],
declarations: [
AppSettingsComponent,
@ -282,6 +294,7 @@ export const DEFAULT_DATE_FORMAT: MatDateFormats = {
ServicesSettingsComponent,
LoopServiceSettingsComponent,
BoltzServiceSettingsComponent,
PeerswapServiceSettingsComponent,
ExperimentalSettingsComponent,
CurrencyUnitConverterComponent,
HorizontalScrollerComponent,
@ -305,7 +318,7 @@ export const DEFAULT_DATE_FORMAT: MatDateFormats = {
TwoFactorAuthComponent,
LoginTokenComponent,
TransactionsReportTableComponent,
ServicesComponent,
LNServicesComponent,
LoopComponent,
SwapsComponent,
LoopModalComponent,
@ -319,7 +332,12 @@ export const DEFAULT_DATE_FORMAT: MatDateFormats = {
SwapServiceInfoComponent,
SwapModalComponent,
SwapInInfoGraphicsComponent,
SwapOutInfoGraphicsComponent
SwapOutInfoGraphicsComponent,
PeerswapComponent,
SwapPeersComponent,
PeerswapsCancelledComponent,
PeerswapsInComponent,
PeerswapsOutComponent
],
providers: [
{ provide: LoggerService, useClass: ConsoleLoggerService },

View File

@ -759,7 +759,8 @@ export const mockActionsData = {
boltzServerUrl: '',
channelBackupPath: '',
currencyUnit: '',
enableOffers: false
enableOffers: false,
enablePeerswap: false
},
authentication: {
swapMacaroonPath: '',
@ -782,7 +783,8 @@ export const mockActionsData = {
lnImplementation: 'LND',
swapServerUrl: '',
boltzServerUrl: '',
enableOffers: false
enableOffers: false,
enablePeerswap: false
},
setSelectedNode: {
settings: {
@ -802,7 +804,8 @@ export const mockActionsData = {
boltzServerUrl: '',
channelBackupPath: '',
currencyUnit: '',
enableOffers: false
enableOffers: false,
enablePeerswap: false
},
authentication: {
swapMacaroonPath: '',

View File

@ -499,12 +499,12 @@ export class RTLEffects implements OnDestroy {
mergeMap((action: { type: string, payload: SetSelectedNode }) => {
this.store.dispatch(openSpinner({ payload: action.payload.uiMessage }));
this.store.dispatch(updateRootAPICallStatus({ payload: { action: 'UpdateSelNode', status: APICallStatusEnum.INITIATED } }));
return this.httpClient.get(environment.CONF_API + '/updateSelNode/' + action.payload.currentLnNode.index + '/' + action.payload.prevLnNodeIndex).pipe(
return this.httpClient.get(environment.CONF_API + '/updateSelNode/' + action.payload.currentLnNode?.index + '/' + action.payload.prevLnNodeIndex).pipe(
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(updateRootAPICallStatus({ payload: { action: 'UpdateSelNode', status: APICallStatusEnum.COMPLETED } }));
this.store.dispatch(closeSpinner({ payload: action.payload.uiMessage }));
this.initializeNode(action.payload.currentLnNode, action.payload.isInitialSetup);
this.initializeNode(action.payload.currentLnNode!, action.payload.isInitialSetup);
return { type: RTLActions.VOID };
}),
catchError((err: any) => {
@ -551,9 +551,9 @@ export class RTLEffects implements OnDestroy {
const landingPage = isInitialSetup ? '' : 'HOME';
let selNode = {};
if (node.settings.fiatConversion && node.settings.currencyUnit) {
selNode = { userPersona: node.settings.userPersona, channelBackupPath: node.settings.channelBackupPath, selCurrencyUnit: node.settings.currencyUnit, currencyUnits: [...CURRENCY_UNITS, node.settings.currencyUnit], fiatConversion: node.settings.fiatConversion, lnImplementation: node.lnImplementation, swapServerUrl: node.settings.swapServerUrl, boltzServerUrl: node.settings.boltzServerUrl, enableOffers: node.settings.enableOffers };
selNode = { userPersona: node.settings.userPersona, channelBackupPath: node.settings.channelBackupPath, selCurrencyUnit: node.settings.currencyUnit, currencyUnits: [...CURRENCY_UNITS, node.settings.currencyUnit], fiatConversion: node.settings.fiatConversion, lnImplementation: node.lnImplementation, swapServerUrl: node.settings.swapServerUrl, boltzServerUrl: node.settings.boltzServerUrl, enableOffers: node.settings.enableOffers, enablePeerswap: node.settings.enablePeerswap };
} else {
selNode = { userPersona: node.settings.userPersona, channelBackupPath: node.settings.channelBackupPath, selCurrencyUnit: node.settings.currencyUnit, currencyUnits: CURRENCY_UNITS, fiatConversion: node.settings.fiatConversion, lnImplementation: node.lnImplementation, swapServerUrl: node.settings.swapServerUrl, boltzServerUrl: node.settings.boltzServerUrl, enableOffers: node.settings.enableOffers };
selNode = { userPersona: node.settings.userPersona, channelBackupPath: node.settings.channelBackupPath, selCurrencyUnit: node.settings.currencyUnit, currencyUnits: CURRENCY_UNITS, fiatConversion: node.settings.fiatConversion, lnImplementation: node.lnImplementation, swapServerUrl: node.settings.swapServerUrl, boltzServerUrl: node.settings.boltzServerUrl, enableOffers: node.settings.enableOffers, enablePeerswap: node.settings.enablePeerswap };
}
this.sessionService.removeItem('lndUnlocked');
this.sessionService.removeItem('clUnlocked');

View File

@ -44,6 +44,9 @@ export const RootReducer = createReducer(initRootState,
case ServicesEnum.OFFERS:
updatedSelNode.settings.enableOffers = payload.settings.enableOffers;
break;
case ServicesEnum.PEERSWAP:
updatedSelNode.settings.enablePeerswap = payload.settings.enablePeerswap;
break;
default:
break;

View File

@ -9,12 +9,12 @@ import { ECLState } from '../eclair/store/ecl.state';
export interface RootState {
apiURL: string;
apisCallStatus: ApiCallsListRoot;
selNode: ConfigSettingsNode | null;
selNode: ConfigSettingsNode | any;
appConfig: RTLConfiguration;
nodeData: GetInfoRoot;
}
const initNodeSettings = { userPersona: 'OPERATOR', themeMode: 'DAY', themeColor: 'PURPLE', channelBackupPath: '', selCurrencyUnit: 'USD', fiatConversion: false, currencyUnits: ['Sats', 'BTC', 'USD'], bitcoindConfigPath: '', enableOffers: false };
const initNodeSettings = { userPersona: 'OPERATOR', themeMode: 'DAY', themeColor: 'PURPLE', channelBackupPath: '', selCurrencyUnit: 'USD', fiatConversion: false, currencyUnits: ['Sats', 'BTC', 'USD'], bitcoindConfigPath: '', enableOffers: false, enablePeerswap: false };
const initNodeAuthentication = { configPath: '', swapMacaroonPath: '', boltzMacaroonPath: '' };
export const initRootState: RootState = {