Peerswap policy moved to cln store

cln-peer-swap
ShahanaFarooqui 10 months ago
parent cec34c41dc
commit f68c119f7a

File diff suppressed because one or more lines are too long

@ -5,7 +5,7 @@ import { ApiCallStatusPayload } from '../../shared/models/apiCallsPayload';
import { SelNodeChild } from '../../shared/models/RTLconfig';
import { GetInfo, Fees, Peer, Payment, QueryRoutes, Channel, FeeRates, Invoice, ListInvoices, OnChain, UTXO, SaveChannel,
GetNewAddress, DetachPeer, UpdateChannel, CloseChannel, SendPayment, GetQueryRoutes, ChannelLookup, OfferInvoice, Offer, OfferBookmark, ListForwards, FetchListForwards } from '../../shared/models/clnModels';
import { Swap, SwapRequest, SwapPeer } from '../../shared/models/peerswapModels';
import { Swap, SwapRequest, SwapPeer, PeerswapPolicy } from '../../shared/models/peerswapModels';
import { PageSettings } from '../../shared/models/pageSettings';
export const updateCLAPICallStatus = createAction(CLNActions.UPDATE_API_CALL_STATUS_CLN, props<{ payload: ApiCallStatusPayload }>());
@ -140,6 +140,10 @@ export const deleteOfferBookmark = createAction(CLNActions.DELETE_OFFER_BOOKMARK
export const removeOfferBookmark = createAction(CLNActions.REMOVE_OFFER_BOOKMARK_CLN, props<{ payload: { bolt12: string } }>());
export const fetchPSPolicy = createAction(CLNActions.FETCH_PS_POLICY_CLN);
export const setPSPolicy = createAction(CLNActions.SET_PS_POLICY_CLN, props<{ payload: PeerswapPolicy }>());
export const fetchSwaps = createAction(CLNActions.FETCH_SWAPS_CLN);
export const setSwaps = createAction(CLNActions.SET_SWAPS_CLN, props<{ payload: Swap[] }>());

@ -1002,6 +1002,25 @@ export class CLNEffects implements OnDestroy {
})
));
peerswapPolicyFetchCL = createEffect(() => this.actions.pipe(
ofType(CLNActions.FETCH_PS_POLICY_CLN),
mergeMap((action: { type: string, payload: any }) => {
this.store.dispatch(updateCLAPICallStatus({ payload: { action: 'FetchPSPolicy', status: APICallStatusEnum.INITIATED } }));
return this.httpClient.get(this.CHILD_API_URL + API_END_POINTS.PEERSWAP_API + '/reloadPolicy').
pipe(map((res: any) => {
this.logger.info(res);
this.store.dispatch(updateCLAPICallStatus({ payload: { action: 'FetchPSPolicy', status: APICallStatusEnum.COMPLETED } }));
return {
type: CLNActions.SET_PS_POLICY_CLN,
payload: res || {}
};
}), catchError((err: any) => {
this.handleErrorWithoutAlert('FetchPSPolicy', UI_MESSAGES.NO_SPINNER, 'Fetching Peerswap Policy Failed.', err);
return of({ type: RTLActions.VOID });
}));
})
));
swapPeersFetchCL = createEffect(() => this.actions.pipe(
ofType(CLNActions.FETCH_SWAP_PEERS_CLN),
mergeMap((action: { type: string, payload: any }) => {

@ -4,7 +4,7 @@ import {
addInvoice, addPeer, removeChannel, removePeer, resetCLStore, setBalance, setChannels,
setChildNodeSettingsCL, setFeeRates, setFees, setForwardingHistory,
setInfo, setInvoices, setLocalRemoteBalance, setOffers, addOffer, setPayments, setPeers, setUTXOs,
updateCLAPICallStatus, updateInvoice, updateOffer, setOfferBookmarks, addUpdateOfferBookmark, removeOfferBookmark, setPageSettings, addSwapout, addSwapin, updateSwapState, setSwapRequests, setSwapPeers, setSwaps
updateCLAPICallStatus, updateInvoice, updateOffer, setOfferBookmarks, addUpdateOfferBookmark, removeOfferBookmark, setPageSettings, addSwapout, addSwapin, updateSwapState, setSwapRequests, setSwapPeers, setSwaps, setPSPolicy
} from './cln.actions';
import { Channel, OfferBookmark } from '../../shared/models/clnModels';
import { Swap } from '../../shared/models/peerswapModels';
@ -219,6 +219,10 @@ export const CLNReducer = createReducer(initCLNState,
offersBookmarks: modifiedOfferBookmarks
};
}),
on(setPSPolicy, (state, { payload }) => ({
...state,
peerswapPolicy: payload
})),
on(setSwaps, (state, { payload }) => {
const swapOutArr: Swap[] = [];
const swapInArr: Swap[] = [];

@ -28,6 +28,7 @@ export const nodeInfoAndNodeSettingsAndAPIsStatus = createSelector(clnState, (st
export const offers = createSelector(clnState, (state: CLNState) => ({ offers: state.offers, apiCallStatus: state.apisCallStatus.FetchOffers }));
export const offerBookmarks = createSelector(clnState, (state: CLNState) => ({ offersBookmarks: state.offersBookmarks, apiCallStatus: state.apisCallStatus.FetchOfferBookmarks }));
export const getoffer = (bolt12Str) => createSelector(clnState, (state: CLNState) => (state.offers.find((offer: Offer) => offer.bolt12 === bolt12Str)));
export const psPolicy = createSelector(clnState, (state: CLNState) => ({ policy: state.peerswapPolicy, apiCallStatus: state.apisCallStatus.FetchPSPolicy }));
export const swaps = createSelector(clnState, (state: CLNState) => ({ swapOuts: state.swapOuts, swapIns: state.swapIns, swapsCanceled: state.swapsCanceled, apiCallStatus: state.apisCallStatus.FetchSwaps }));
export const swapPeers = createSelector(clnState, (state: CLNState) => ({ totalSwapPeers: state.totalSwapPeers, swapPeers: state.swapPeers, apiCallStatus: state.apisCallStatus.FetchSwapPeers }));
export const swapRequests = createSelector(clnState, (state: CLNState) => ({ swapRequests: state.swapRequests, apiCallStatus: state.apisCallStatus.FetchSwapRequests }));

@ -1,7 +1,7 @@
import { SelNodeChild } from '../../shared/models/RTLconfig';
import { APICallStatusEnum, CLN_DEFAULT_PAGE_SETTINGS, UserPersonaEnum } from '../../shared/services/consts-enums-functions';
import { GetInfo, Fees, Balance, LocalRemoteBalance, Peer, Payment, Channel, FeeRates, ListInvoices, UTXO, Offer, OfferBookmark, ListForwards } from '../../shared/models/clnModels';
import { SwapRequest, Swap, SwapPeerChannelsFlattened } from '../../shared/models/peerswapModels';
import { SwapRequest, Swap, SwapPeerChannelsFlattened, PeerswapPolicy } from '../../shared/models/peerswapModels';
import { ApiCallsListCL } from '../../shared/models/apiCallsPayload';
import { PageSettings } from '../../shared/models/pageSettings';
@ -28,6 +28,7 @@ export interface CLNState {
offers: Offer[];
offersBookmarks: OfferBookmark[];
totalSwapPeers: number;
peerswapPolicy: PeerswapPolicy;
swapPeers: SwapPeerChannelsFlattened[];
swapOuts: Swap[];
swapIns: Swap[];
@ -54,6 +55,7 @@ export const initCLNState: CLNState = {
FetchForwardingHistoryL: { status: APICallStatusEnum.UN_INITIATED },
FetchOffers: { status: APICallStatusEnum.UN_INITIATED },
FetchOfferBookmarks: { status: APICallStatusEnum.UN_INITIATED },
FetchPSPolicy: { status: APICallStatusEnum.UN_INITIATED },
FetchSwaps: { status: APICallStatusEnum.UN_INITIATED },
FetchSwapPeers: { status: APICallStatusEnum.UN_INITIATED },
FetchSwapRequests: { status: APICallStatusEnum.UN_INITIATED }
@ -79,6 +81,7 @@ export const initCLNState: CLNState = {
offers: [],
offersBookmarks: [],
totalSwapPeers: 0,
peerswapPolicy: {},
swapPeers: [],
swapOuts: [],
swapIns: [],

@ -1,9 +1,15 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ResolveEnd, Event } from '@angular/router';
import { Store } from '@ngrx/store';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { faHandshake } from '@fortawesome/free-solid-svg-icons';
import { SwapTypeEnum } from 'src/app/shared/services/consts-enums-functions';
import { RTLState } from 'src/app/store/rtl.state';
import { PeerswapPolicy } from 'src/app/shared/models/peerswapModels';
import { ApiCallStatusPayload } from 'src/app/shared/models/apiCallsPayload';
import { psPolicy } from 'src/app/cln/store/cln.selector';
import { APICallStatusEnum } from 'src/app/shared/services/consts-enums-functions';
import { fetchPSPolicy } from 'src/app/cln/store/cln.actions';
@Component({
selector: 'rtl-peerswap',
@ -17,7 +23,7 @@ export class PeerswapComponent implements OnInit, OnDestroy {
public activeTab = this.links[0];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private router: Router) { }
constructor(private router: Router, private store: Store<RTLState>) { }
ngOnInit() {
const linkFound = this.links.find((link) => this.router.url.includes(link.link));
@ -29,6 +35,11 @@ export class PeerswapComponent implements OnInit, OnDestroy {
this.activeTab = linkFound ? linkFound : this.links[0];
}
});
this.store.select(psPolicy).pipe(takeUntil(this.unSubs[1])).subscribe((policySeletor: { policy: PeerswapPolicy, apiCallStatus: ApiCallStatusPayload }) => {
if (policySeletor.apiCallStatus.status === APICallStatusEnum.UN_INITIATED) {
this.store.dispatch(fetchPSPolicy());
}
});
}
ngOnDestroy() {

@ -4,7 +4,7 @@
<div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Initiate a Swapin</span>
</div>
<button tabindex="6" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" default mat-button [mat-dialog-close]="false">X</button>
<button tabindex="6" fxFlex="5" fxLayoutAlign="center center" class="btn-close-x p-0" mat-button [mat-dialog-close]="false">X</button>
</mat-card-header>
<mat-card-content class="padding-gap-x-large">
<form #swapInForm="ngForm" fxLayout="row wrap" fxLayoutAlign="start space-between" fxFlex="100">
@ -12,12 +12,12 @@
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput placeholder="Short Channel ID" tabindex="1" name="shortChanId" disabled [value]="sPeer.short_channel_id">
</mat-form-field>
<mat-form-field *ngIf="sPeer.remote_balance >= 100000" fxFlex="100">
<mat-form-field *ngIf="sPeer.remote_balance >= (psPolicy.min_swap_amount_msat / 1000)" fxFlex="100">
<input #swapAmt="ngModel" required matInput autoFocus placeholder="Amount" tabindex="2" name="swapAmt"
type="number" [step]="1000" [min]="100000" [max]="sPeer.remote_balance" [(ngModel)]="swapAmount" (keyup)="onAmountChange()">
type="number" [step]="1000" [min]="psPolicy.min_swap_amount_msat / 1000" [max]="sPeer.remote_balance" [(ngModel)]="swapAmount" (keyup)="onAmountChange()">
<span matSuffix class="ml-1"> Sats </span>
<mat-error *ngIf="swapAmt.errors?.required">Amount is required.</mat-error>
<mat-error *ngIf="swapAmt.errors?.min">Amount must be greater than or equal to 100,000.</mat-error>
<mat-error *ngIf="swapAmt.errors?.min">Amount must be greater than or equal to {{psPolicy.min_swap_amount_msat / 1000 | number}} Sats.</mat-error>
<mat-error *ngIf="swapAmt.errors?.max">Amount must be less than or equal to {{sPeer.remote_balance | number}}.</mat-error>
<mat-hint>Amount should be between 100,000 and {{sPeer.remote_balance | number}}<br>{{swapAmountHint}}</mat-hint>
</mat-form-field>
@ -25,14 +25,14 @@
<fa-icon class="mr-1 alert-icon" [icon]="faExclamationTriangle"></fa-icon>
<span *ngIf="swapInError !== ''">{{swapInError}}</span>
</div>
<div *ngIf="sPeer.remote_balance < 100000" fxFlex="100" class="alert alert-danger mt-2">
<div *ngIf="sPeer.remote_balance < (psPolicy.min_swap_amount_msat / 1000)" fxFlex="100" class="alert alert-danger mt-2">
<fa-icon class="mr-1 alert-icon" [icon]="faExclamationTriangle"></fa-icon>
<span>Insufficient remote balance for swap in.</span>
</div>
<div fxLayout="row" fxFlex="100" class="mt-1" fxLayoutAlign="end center">
<button class="mr-1" mat-button color="primary" tabindex="3" type="button" [disabled]="sPeer.remote_balance < 100000" (click)="resetData()">Clear Field</button>
<button class="mr-1" mat-button color="primary" tabindex="3" type="button" [disabled]="sPeer.remote_balance < (psPolicy.min_swap_amount_msat / 1000)" (click)="resetData()">Clear Field</button>
<button *ngIf="flgswapCanceled" mat-button color="primary" tabindex="4" (click)="goToSwapCanceled()">Go to Swap Canceled</button>
<button *ngIf="!flgswapCanceled" mat-button color="primary" tabindex="5" [disabled]="sPeer.remote_balance < 100000" (click)="onExecuteSwapin()">{{swapInError !== '' ? 'Retry' : 'Execute'}}</button>
<button *ngIf="!flgswapCanceled" mat-button color="primary" tabindex="5" [disabled]="sPeer.remote_balance < (psPolicy.min_swap_amount_msat / 1000)" (click)="onExecuteSwapin()">{{swapInError !== '' ? 'Retry' : 'Execute'}}</button>
</div>
</form>
</mat-card-content>

@ -9,14 +9,15 @@ import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { PSSwapInformation } from '../../../../models/alertData';
import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, APICallStatusEnum, CLNActions } from '../../../../services/consts-enums-functions';
import { SwapPeerChannelsFlattened } from '../../../../models/peerswapModels';
import { PeerswapPolicy, SwapPeerChannelsFlattened } from '../../../../models/peerswapModels';
import { CommonService } from '../../../../services/common.service';
import { RTLState } from '../../../../../store/rtl.state';
import { SelNodeChild } from '../../../../../shared/models/RTLconfig';
import { clnNodeSettings } from '../../../../../cln/store/cln.selector';
import { clnNodeSettings, psPolicy } from '../../../../../cln/store/cln.selector';
import { fetchSwaps, swapIn } from '../../../../../cln/store/cln.actions';
import { Router } from '@angular/router';
import { ApiCallStatusPayload } from 'src/app/shared/models/apiCallsPayload';
@Component({
selector: 'rtl-swap-in-modal',
@ -27,6 +28,7 @@ export class PSSwapInModalComponent implements OnInit, OnDestroy {
public faExclamationTriangle = faExclamationTriangle;
public selNode: SelNodeChild | null = {};
public psPolicy: PeerswapPolicy = {};
public sPeer: SwapPeerChannelsFlattened | null = null;
public swapAmount: number | null;
public swapAmountHint = '';
@ -41,8 +43,11 @@ export class PSSwapInModalComponent implements OnInit, OnDestroy {
this.store.select(clnNodeSettings).pipe(takeUntil(this.unSubs[0])).subscribe((nodeSettings: SelNodeChild | null) => {
this.selNode = nodeSettings;
});
this.store.select(psPolicy).pipe(takeUntil(this.unSubs[1])).subscribe((policySeletor: { policy: PeerswapPolicy, apiCallStatus: ApiCallStatusPayload }) => {
this.psPolicy = policySeletor.policy;
});
this.actions.pipe(
takeUntil(this.unSubs[1]),
takeUntil(this.unSubs[2]),
filter((action) => action.type === CLNActions.UPDATE_API_CALL_STATUS_CLN)).
subscribe((action: any) => {
if (action.type === CLNActions.UPDATE_API_CALL_STATUS_CLN && action.payload.action === 'PeerswapSwapin') {

@ -4,7 +4,7 @@
<div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Initiate a Swapout</span>
</div>
<button tabindex="6" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" default mat-button [mat-dialog-close]="false">X</button>
<button tabindex="6" fxFlex="5" fxLayoutAlign="center center" class="btn-close-x p-0" mat-button [mat-dialog-close]="false">X</button>
</mat-card-header>
<mat-card-content class="padding-gap-x-large">
<form #swapOutForm="ngForm" fxLayout="row wrap" fxLayoutAlign="start space-between" fxFlex="100">
@ -12,26 +12,26 @@
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput placeholder="Short Channel ID" tabindex="1" name="shortChanId" disabled [value]="sPeer.short_channel_id" >
</mat-form-field>
<mat-form-field *ngIf="sPeer.local_balance >= 100000" fxFlex="100">
<input #swapAmt="ngModel" matInput autoFocus placeholder="Amount" type="number" tabindex="2" name="swapAmt" required [step]="1000" [min]="100000" [max]="sPeer.local_balance" [(ngModel)]="swapAmount" (keyup)="onAmountChange()">
<mat-form-field *ngIf="sPeer.local_balance >= (psPolicy.min_swap_amount_msat / 1000)" fxFlex="100">
<input #swapAmt="ngModel" matInput autoFocus placeholder="Amount" type="number" tabindex="2" name="swapAmt" required [step]="1000" [min]="psPolicy.min_swap_amount_msat / 1000" [max]="sPeer.local_balance" [(ngModel)]="swapAmount" (keyup)="onAmountChange()">
<span matSuffix class="ml-1"> Sats </span>
<mat-error *ngIf="swapAmt.errors?.required">Amount is required.</mat-error>
<mat-error *ngIf="swapAmt.errors?.min">Amount must be greater than or equal to 100,000.</mat-error>
<mat-error *ngIf="swapAmt.errors?.min">Amount must be greater than or equal to {{psPolicy.min_swap_amount_msat / 1000 | number}} Sats.</mat-error>
<mat-error *ngIf="swapAmt.errors?.max">Amount must be less than or equal to {{sPeer.local_balance | number}}.</mat-error>
<mat-hint>Amount should be between 100,000 and {{sPeer.local_balance | number}}<br>{{swapAmountHint}}</mat-hint>
<mat-hint>Amount should be between {{psPolicy.min_swap_amount_msat / 1000 | number}} and {{sPeer.local_balance | number}}<br>{{swapAmountHint}}</mat-hint>
</mat-form-field>
<div *ngIf="swapOutError !== ''" fxFlex="100" class="alert alert-danger mt-2">
<fa-icon class="mr-1 alert-icon" [icon]="faExclamationTriangle"></fa-icon>
<span *ngIf="swapOutError !== ''">{{swapOutError}}</span>
</div>
<div *ngIf="sPeer.local_balance < 100000" fxFlex="100" class="alert alert-danger mt-2">
<div *ngIf="sPeer.local_balance < (psPolicy.min_swap_amount_msat / 1000)" fxFlex="100" class="alert alert-danger mt-2">
<fa-icon class="mr-1 alert-icon" [icon]="faExclamationTriangle"></fa-icon>
<span>Insufficient local balance for swap out.</span>
</div>
<div fxLayout="row" fxFlex="100" class="mt-1" fxLayoutAlign="end center">
<button class="mr-1" mat-button color="primary" tabindex="3" type="button" [disabled]="sPeer.local_balance < 100000" (click)="resetData()">Clear Field</button>
<button class="mr-1" mat-button color="primary" tabindex="3" type="button" [disabled]="sPeer.local_balance < (psPolicy.min_swap_amount_msat / 1000)" (click)="resetData()">Clear Field</button>
<button *ngIf="flgswapCanceled" mat-button color="primary" tabindex="4" (click)="goToSwapCanceled()">Go to Swap Canceled</button>
<button *ngIf="!flgswapCanceled" mat-button color="primary" tabindex="5" [disabled]="sPeer.local_balance < 100000" (click)="onExecuteSwapout()">{{swapOutError !== '' ? 'Retry' : 'Execute'}}</button>
<button *ngIf="!flgswapCanceled" mat-button color="primary" tabindex="5" [disabled]="sPeer.local_balance < (psPolicy.min_swap_amount_msat / 1000)" (click)="onExecuteSwapout()">{{swapOutError !== '' ? 'Retry' : 'Execute'}}</button>
</div>
</form>
</mat-card-content>

@ -9,14 +9,15 @@ import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { PSSwapInformation } from '../../../../models/alertData';
import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, APICallStatusEnum, CLNActions } from '../../../../services/consts-enums-functions';
import { SwapPeerChannelsFlattened } from '../../../../models/peerswapModels';
import { PeerswapPolicy, SwapPeerChannelsFlattened } from '../../../../models/peerswapModels';
import { CommonService } from '../../../../services/common.service';
import { RTLState } from '../../../../../store/rtl.state';
import { SelNodeChild } from '../../../../../shared/models/RTLconfig';
import { clnNodeSettings } from '../../../../../cln/store/cln.selector';
import { clnNodeSettings, psPolicy } from '../../../../../cln/store/cln.selector';
import { fetchSwaps, swapOut } from '../../../../../cln/store/cln.actions';
import { Router } from '@angular/router';
import { ApiCallStatusPayload } from 'src/app/shared/models/apiCallsPayload';
@Component({
selector: 'rtl-swap-out-modal',
@ -27,6 +28,7 @@ export class PSSwapOutModalComponent implements OnInit, OnDestroy {
public faExclamationTriangle = faExclamationTriangle;
public selNode: SelNodeChild | null = {};
public psPolicy: PeerswapPolicy = {};
public sPeer: SwapPeerChannelsFlattened | null = null;
public swapAmount: number | null;
public swapAmountHint = '';
@ -41,8 +43,11 @@ export class PSSwapOutModalComponent implements OnInit, OnDestroy {
this.store.select(clnNodeSettings).pipe(takeUntil(this.unSubs[0])).subscribe((nodeSettings: SelNodeChild | null) => {
this.selNode = nodeSettings;
});
this.store.select(psPolicy).pipe(takeUntil(this.unSubs[1])).subscribe((policySeletor: { policy: PeerswapPolicy, apiCallStatus: ApiCallStatusPayload }) => {
this.psPolicy = policySeletor.policy;
});
this.actions.pipe(
takeUntil(this.unSubs[1]),
takeUntil(this.unSubs[2]),
filter((action) => action.type === CLNActions.UPDATE_API_CALL_STATUS_CLN)).
subscribe((action: any) => {
if (action.type === CLNActions.UPDATE_API_CALL_STATUS_CLN && action.payload.action === 'PeerswapSwapout') {

@ -37,7 +37,7 @@
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th *matHeaderCellDef mat-header-cell fxLayoutAlign="end center" [ngClass]="{'px-3': screenSize !== screenSizeEnum.XS}">
<th *matHeaderCellDef mat-header-cell [ngClass]="{'px-3': screenSize !== screenSizeEnum.XS}">
<div class="bordered-box table-actions-select" fxLayoutAlign="center center">
<mat-select placeholder="Actions" tabindex="1" class="mr-0">
<mat-select-trigger></mat-select-trigger>

@ -1,3 +0,0 @@
// .mat-column-actions {
// min-height: 4.8rem;
// }

@ -6,7 +6,3 @@
display: flex;
}
}
// .mat-column-actions {
// min-height: 4.8rem;
// }

@ -5,34 +5,34 @@
</div>
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" class="settings-container page-sub-title-container">
<mat-slide-toggle autoFocus class="my-1" tabindex="1" color="primary" name="peerswap" [(ngModel)]="enablePeerswap" (change)="onUpdateService()">Enable Peerswap Service</mat-slide-toggle>
<div *ngIf="enablePeerswap && reloadPolicyError !== ''" class="padding-gap-large error-border">
<div *ngIf="enablePeerswap && errorMessage !== ''" class="padding-gap-large error-border">
<div fxLayout="row">
<div fxFlex="100" class="alert alert-danger mt-1">
<fa-icon class="mr-1 alert-icon" [icon]="faExclamationTriangle"></fa-icon>
<span>{{reloadPolicyError}}</span>
<span>{{errorMessage}}</span>
</div>
</div>
</div>
<div *ngIf="enablePeerswap && reloadPolicyError === ''" class="padding-gap-large bordered-box">
<div *ngIf="enablePeerswap && errorMessage === ''" class="padding-gap-large bordered-box">
<div fxLayout="row">
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Allow New Swaps</h4>
<span class="foreground-secondary-text">{{reloadPolicy?.allow_new_swaps ? 'Yes' : 'No'}}</span>
<span class="foreground-secondary-text">{{psPolicy?.allow_new_swaps ? 'Yes' : 'No'}}</span>
</div>
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Accept All Peers</h4>
<span class="foreground-secondary-text">{{reloadPolicy?.accept_all_peers ? 'Yes' : 'No'}}</span>
<span class="foreground-secondary-text">{{psPolicy?.accept_all_peers ? 'Yes' : 'No'}}</span>
</div>
</div>
<mat-divider class="my-1" [inset]="true"></mat-divider>
<div fxLayout="row">
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Onchain Reserve (Sats)</h4>
<span class="foreground-secondary-text">{{reloadPolicy?.reserve_onchain_msat / 1000 | number}}</span>
<span class="foreground-secondary-text">{{psPolicy?.reserve_onchain_msat / 1000 | number}}</span>
</div>
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Min Swap Amount (Sats)</h4>
<span class="foreground-secondary-text">{{reloadPolicy?.min_swap_amount_msat / 1000 | number}}</span>
<span class="foreground-secondary-text">{{psPolicy?.min_swap_amount_msat / 1000 | number}}</span>
</div>
</div>
<mat-divider class="my-1" [inset]="true"></mat-divider>
@ -66,7 +66,7 @@
</div>
</div>
<div>
<mat-card *ngFor="let peer of reloadPolicy?.[listPeers.dataSource]" fxLayout="row" fxLayoutAlign="start center" class="peer-card">
<mat-card *ngFor="let peer of psPolicy?.[listPeers.dataSource]" fxLayout="row" fxLayoutAlign="start center" class="peer-card">
<div fxLayoutAlign="center center">
<button mat-icon-button color="primary" class="mr-1" matTooltipPosition="below" [matTooltip]="'Remove peer from ' + listPeers.title + ' list'" (click)="onRemovePeer(peer, listPeers.list)">
<mat-icon>remove_circle_outline</mat-icon>

@ -3,7 +3,7 @@ import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { ServicesEnum, UI_MESSAGES, PeerswapPeersLists } from '../../../../services/consts-enums-functions';
import { ServicesEnum, UI_MESSAGES, PeerswapPeersLists, APICallStatusEnum } from '../../../../services/consts-enums-functions';
import { ConfigSettingsNode } from '../../../../models/RTLconfig';
import { LoggerService } from '../../../../services/logger.service';
import { DataService } from '../../../../services/data.service';
@ -11,10 +11,12 @@ import { faInfoCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg
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 { fetchPSPolicy, setChildNodeSettingsCL } from '../../../../../cln/store/cln.actions';
import { setChildNodeSettingsECL } from '../../../../../eclair/store/ecl.actions';
import { rootSelectedNode } from '../../../../../store/rtl.selector';
import { PeerswapReloadPolicy } from '../../../../models/peerswapModels';
import { PeerswapPolicy } from '../../../../models/peerswapModels';
import { psPolicy } from 'src/app/cln/store/cln.selector';
import { ApiCallStatusPayload } from 'src/app/shared/models/apiCallsPayload';
@Component({
@ -29,32 +31,37 @@ export class PeerswapServiceSettingsComponent implements OnInit, OnDestroy {
public selNode: ConfigSettingsNode | any;
public enablePeerswap = false;
public allowSwapRequests = false;
public reloadPolicy: PeerswapReloadPolicy | null = null;
public reloadPolicyError = '';
public psPolicy: PeerswapPolicy | null = null;
public peerswapPeersLists = PeerswapPeersLists;
public errorMessage = '';
public dataForAllowedList = { icon: 'check', class: 'green', title: 'whitelisted peers', dataSource: 'allowlisted_peers', list: PeerswapPeersLists.ALLOWED, ngModelVar: '', addRemoveError: '' };
public dataForSuspiciousList = { icon: 'close', class: 'red', title: 'suspicious peers', dataSource: 'suspicious_peers', list: PeerswapPeersLists.SUSPICIOUS, ngModelVar: '', addRemoveError: '' };
public apiCallStatus: ApiCallStatusPayload | null = null;
public apiCallStatusEnum = APICallStatusEnum;
public unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private dataService: DataService) { }
ngOnInit() {
this.dataService.peerswapReloadPolicy().pipe(takeUntil(this.unSubs[0])).
subscribe({
next: (res) => {
this.reloadPolicy = res;
}, error: (err) => {
this.reloadPolicyError = 'ERROR: ' + err;
}
});
this.store.select(rootSelectedNode).
pipe(takeUntil(this.unSubs[1])).
pipe(takeUntil(this.unSubs[0])).
subscribe((selNode) => {
this.selNode = selNode;
this.enablePeerswap = !!selNode?.settings.enablePeerswap;
this.logger.info(selNode);
});
this.store.select(psPolicy).pipe(takeUntil(this.unSubs[1])).subscribe((policySeletor: { policy: PeerswapPolicy, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessage = '';
this.apiCallStatus = policySeletor.apiCallStatus;
if (this.apiCallStatus?.status === APICallStatusEnum.UN_INITIATED) {
this.store.dispatch(fetchPSPolicy());
}
if (this.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessage = 'ERROR: ' + (!this.apiCallStatus.message ? '' : (typeof (this.apiCallStatus.message) === 'object') ? JSON.stringify(this.apiCallStatus.message) : this.apiCallStatus.message);
}
this.psPolicy = policySeletor.policy;
this.logger.info(policySeletor);
});
}
onUpdateService(): boolean | void {
@ -88,7 +95,7 @@ export class PeerswapServiceSettingsComponent implements OnInit, OnDestroy {
this.dataService.addPeerToPeerswap(ngModelVar, list).pipe(takeUntil(this.unSubs[2])).
subscribe({
next: (res) => {
this.reloadPolicy = res;
this.psPolicy = res;
if (list !== PeerswapPeersLists.ALLOWED) {
this.dataForSuspiciousList.ngModelVar = '';
} else {
@ -120,7 +127,7 @@ export class PeerswapServiceSettingsComponent implements OnInit, OnDestroy {
this.dataService.removePeerFromPeerswap(peerNodeId, list).pipe(takeUntil(this.unSubs[3])).
subscribe({
next: (res) => {
this.reloadPolicy = res;
this.psPolicy = res;
}, error: (err) => {
if (list !== PeerswapPeersLists.ALLOWED) {
this.dataForSuspiciousList.addRemoveError = 'ERROR: ' + err;

@ -61,6 +61,7 @@ export interface ApiCallsListCL {
FetchForwardingHistoryL: ApiCallStatusPayload;
FetchOffers: ApiCallStatusPayload;
FetchOfferBookmarks: ApiCallStatusPayload;
FetchPSPolicy: ApiCallStatusPayload;
FetchSwaps: ApiCallStatusPayload;
FetchSwapPeers: ApiCallStatusPayload;
FetchSwapRequests: ApiCallStatusPayload;

@ -1,4 +1,4 @@
export interface PeerswapReloadPolicy {
export interface PeerswapPolicy {
accept_all_peers?: boolean;
allow_new_swaps?: boolean;
allowlisted_peers?: string[];

@ -582,6 +582,8 @@ export enum CLNActions {
ADD_UPDATE_OFFER_BOOKMARK_CLN = 'ADD_UPDATE_OFFER_BOOKMARK_CLN',
DELETE_OFFER_BOOKMARK_CLN = 'DELETE_OFFER_BOOKMARK_CLN',
REMOVE_OFFER_BOOKMARK_CLN = 'REMOVE_OFFER_BOOKMARK_CL',
FETCH_PS_POLICY_CLN = 'FETCH_PS_POLICY_CLN',
SET_PS_POLICY_CLN = 'SET_PS_POLICY_CLN',
FETCH_SWAPS_CLN = 'FETCH_SWAPS_CLN',
SET_SWAPS_CLN = 'SET_SWAPS_CLN',
FETCH_SWAP_PEERS_CLN = 'FETCH_SWAP_PEERS_CLN',

@ -333,22 +333,6 @@ export class DataService implements OnDestroy {
}));
}
peerswapReloadPolicy() {
return this.lnImplementationUpdated.pipe(first((val) => val !== null), mergeMap((updatedLnImplementation) => {
this.store.dispatch(openSpinner({ payload: UI_MESSAGES.RELOAD_POLICY_PEERSWAP }));
return this.httpClient.get(this.APIUrl + '/' + updatedLnImplementation + API_END_POINTS.PEERSWAP_API + '/reloadPolicy').pipe(
takeUntil(this.unSubs[12]),
mergeMap((res) => {
this.store.dispatch(closeSpinner({ payload: UI_MESSAGES.RELOAD_POLICY_PEERSWAP }));
return of(res);
}), catchError((err) => {
this.handleErrorWithoutAlert('Reload Peerswap Policy', UI_MESSAGES.RELOAD_POLICY_PEERSWAP, err);
return throwError(() => this.extractErrorMessage(err));
})
);
}));
}
addPeerToPeerswap(peerNodeId: string, list: PeerswapPeersLists) {
return this.lnImplementationUpdated.pipe(first((val) => val !== null), mergeMap((updatedLnImplementation) => {
this.store.dispatch(openSpinner({ payload: UI_MESSAGES.ADD_PEER_PEERSWAP }));

Loading…
Cancel
Save