ecl: Open channel model block if min fee is higher

pull/1388/head
ShahanaFarooqui 3 weeks ago
parent 93434d92c2
commit 3fdd0b6d36

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(()=>{"use strict";var e,v={},m={};function r(e){var f=m[e];if(void 0!==f)return f.exports;var t=m[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(f,t,i,o)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,o]=e[n],c=!0,l=0;l<t.length;l++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[l]))?t.splice(l--,1):(c=!1,o<a&&(a=o));if(c){e.splice(n--,1);var d=i();void 0!==d&&(f=d)}}return f}o=o||0;for(var n=e.length;n>0&&e[n-1][2]>o;n--)e[n]=e[n-1];e[n]=[t,i,o]},r.d=(e,f)=>{for(var t in f)r.o(f,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:f[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((f,t)=>(r.f[t](e,f),f),[])),r.u=e=>e+"."+{125:"86ea6e8d56a4e1a7",456:"a7433b9c5b34e0df",570:"a47a5e74ba9177e8",758:"b6dcd2f2b36dacf0"}[e]+".js",r.miniCssF=e=>{},r.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),(()=>{var e={},f="RTLApp:";r.l=(t,i,o,n)=>{if(e[t])e[t].push(i);else{var a,c;if(void 0!==o)for(var l=document.getElementsByTagName("script"),d=0;d<l.length;d++){var u=l[d];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==f+o){a=u;break}}a||(c=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",f+o),a.src=r.tu(t)),e[t]=[i];var s=(g,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(y=>y(b)),g)return g(b)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:f=>f},typeof trustedTypes<"u"&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(i,o)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)o.push(n[2]);else if(666!=i){var a=new Promise((u,s)=>n=e[i]=[u,s]);o.push(n[2]=a);var c=r.p+r.u(i),l=new Error;r.l(c,u=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var s=u&&("load"===u.type?"missing":u.type),p=u&&u.target&&u.target.src;l.message="Loading chunk "+i+" failed.\n("+s+": "+p+")",l.name="ChunkLoadError",l.type=s,l.request=p,n[1](l)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var f=(i,o)=>{var l,d,[n,a,c]=o,u=0;if(n.some(p=>0!==e[p])){for(l in a)r.o(a,l)&&(r.m[l]=a[l]);if(c)var s=c(r)}for(i&&i(o);u<n.length;u++)r.o(e,d=n[u])&&e[d]&&e[d][0](),e[d]=0;return r.O(s)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(f.bind(null,0)),t.push=f.bind(null,t.push.bind(t))})()})();

@ -0,0 +1 @@
(()=>{"use strict";var e,v={},m={};function r(e){var o=m[e];if(void 0!==o)return o.exports;var t=m[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(o,t,i,d)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,d]=e[n],c=!0,f=0;f<t.length;f++)(!1&d||a>=d)&&Object.keys(r.O).every(b=>r.O[b](t[f]))?t.splice(f--,1):(c=!1,d<a&&(a=d));if(c){e.splice(n--,1);var u=i();void 0!==u&&(o=u)}}return o}d=d||0;for(var n=e.length;n>0&&e[n-1][2]>d;n--)e[n]=e[n-1];e[n]=[t,i,d]},r.d=(e,o)=>{for(var t in o)r.o(o,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:o[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((o,t)=>(r.f[t](e,o),o),[])),r.u=e=>e+"."+{125:"c9e382333be6e677",456:"b73706bd7985d63a",570:"58fb22012be84615",758:"b6dcd2f2b36dacf0"}[e]+".js",r.miniCssF=e=>{},r.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),(()=>{var e={},o="RTLApp:";r.l=(t,i,d,n)=>{if(e[t])e[t].push(i);else{var a,c;if(void 0!==d)for(var f=document.getElementsByTagName("script"),u=0;u<f.length;u++){var l=f[u];if(l.getAttribute("src")==t||l.getAttribute("data-webpack")==o+d){a=l;break}}a||(c=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",o+d),a.src=r.tu(t)),e[t]=[i];var s=(g,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(y=>y(b)),g)return g(b)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:o=>o},typeof trustedTypes<"u"&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(i,d)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)d.push(n[2]);else if(666!=i){var a=new Promise((l,s)=>n=e[i]=[l,s]);d.push(n[2]=a);var c=r.p+r.u(i),f=new Error;r.l(c,l=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var s=l&&("load"===l.type?"missing":l.type),p=l&&l.target&&l.target.src;f.message="Loading chunk "+i+" failed.\n("+s+": "+p+")",f.name="ChunkLoadError",f.type=s,f.request=p,n[1](f)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var o=(i,d)=>{var f,u,[n,a,c]=d,l=0;if(n.some(p=>0!==e[p])){for(f in a)r.o(a,f)&&(r.m[f]=a[f]);if(c)var s=c(r)}for(i&&i(d);l<n.length;l++)r.o(e,u=n[l])&&e[u]&&e[u][0](),e[u]=0;return r.O(s)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(o.bind(null,0)),t.push=o.bind(null,t.push.bind(t))})()})();

@ -45,7 +45,9 @@
<div fxFlex="100" fxLayout="row" fxLayoutAlign="space-between center">
<mat-form-field fxLayout="column" fxFlex="49">
<mat-label>Fee (Sats/vByte)</mat-label>
<input #fee="ngModel" matInput type="number" name="fee" tabindex="7" [step]="1" [min]="0" [(ngModel)]="feeRate">
<input #fee="ngModel" matInput type="number" name="fee" tabindex="7" [step]="1" [min]="recommendedFee.minimumFee" [(ngModel)]="feeRate">
<mat-hint>Mempool Min: {{recommendedFee.minimumFee}} (Sats/vByte)</mat-hint>
<mat-error *ngIf="feeRate && feeRate < recommendedFee.minimumFee">Lower than min feerate {{recommendedFee.minimumFee}} in the mempool.</mat-error>
</mat-form-field>
</div>
</div>

@ -3,13 +3,14 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { mockCLEffects, mockECLEffects, mockLNDEffects, mockMatDialogRef, mockRTLEffects } from '../../../../shared/test-helpers/mock-services';
import { SharedModule } from '../../../../shared/shared.module';
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 { mockCLEffects, mockDataService, mockECLEffects, mockLNDEffects, mockMatDialogRef, mockRTLEffects } from '../../../../shared/test-helpers/mock-services';
import { ECLOpenChannelComponent } from './open-channel.component';
describe('ECLOpenChannelComponent', () => {
@ -26,6 +27,7 @@ describe('ECLOpenChannelComponent', () => {
EffectsModule.forRoot([mockRTLEffects, mockLNDEffects, mockCLEffects, mockECLEffects])
],
providers: [
{ provide: DataService, useClass: mockDataService },
{ provide: MatDialogRef, useClass: mockMatDialogRef },
{ provide: MAT_DIALOG_DATA, useValue: { message: {} } }
]

@ -15,6 +15,9 @@ import { RTLState } from '../../../../store/rtl.state';
import { rootSelectedNode } from '../../../../store/rtl.selector';
import { saveNewChannel } from '../../../store/ecl.actions';
import { Node } from '../../../../shared/models/RTLconfig';
import { RecommendedFeeRates } from '../../../../shared/models/rtlModels';
import { LoggerService } from '../../../../shared/services/logger.service';
import { DataService } from '../../../../shared/services/data.service';
@Component({
selector: 'rtl-ecl-open-channel',
@ -40,9 +43,12 @@ export class ECLOpenChannelComponent implements OnInit, OnDestroy {
public selectedPubkey = '';
public isPrivate = false;
public feeRate: number | null = null;
public recommendedFee: RecommendedFeeRates = { fastestFee: 0, halfHourFee: 0, hourFee: 0 };
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(public dialogRef: MatDialogRef<ECLOpenChannelComponent>, @Inject(MAT_DIALOG_DATA) public data: ECLOpenChannelAlert, private store: Store<RTLState>, private actions: Actions) { }
constructor(private logger: LoggerService, public dialogRef: MatDialogRef<ECLOpenChannelComponent>,
@Inject(MAT_DIALOG_DATA) public data: ECLOpenChannelAlert, private store: Store<RTLState>,
private actions: Actions, private dataService: DataService) { }
ngOnInit() {
if (this.data.message) {
@ -131,11 +137,23 @@ export class ECLOpenChannelComponent implements OnInit, OnDestroy {
if (this.feeRate && this.feeRate > 0) {
this.advancedTitle = this.advancedTitle + ' | Fee (Sats/vByte): ' + this.feeRate;
}
} else {
this.dataService.getRecommendedFeeRates().pipe(takeUntil(this.unSubs[3])).subscribe({
next: (rfRes: RecommendedFeeRates) => {
this.recommendedFee = rfRes;
}, error: (err) => {
this.logger.error(err);
}
});
}
}
onOpenChannel(): boolean | void {
if ((!this.peer && !this.selectedPubkey) || (!this.fundingAmount || ((this.totalBalance - this.fundingAmount) < 0))) {
if (
(!this.peer && !this.selectedPubkey) ||
(!this.fundingAmount || ((this.totalBalance - this.fundingAmount) < 0)) ||
(this.feeRate && this.recommendedFee.minimumFee > this.feeRate)
) {
return true;
}
const saveChannelPayload: SaveChannel = { nodeId: ((!this.peer || !this.peer.nodeId) ? this.selectedPubkey : this.peer.nodeId), amount: this.fundingAmount, private: this.isPrivate };
@ -143,6 +161,7 @@ export class ECLOpenChannelComponent implements OnInit, OnDestroy {
this.store.dispatch(saveNewChannel({ payload: saveChannelPayload }));
}
ngOnDestroy() {
this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null);

Loading…
Cancel
Save