Skip to content

Commit 8a0304c

Browse files
Release 0.15.5 (#1492)
* Version Updated to 0.15.5-beta * Fix to show correct experimental-dual-fund configuration from listconfig (#1479) * feat: boltz swap in refund address (#1490) require a refund address when creating a swap in and paying it externally to make sure the swap can be refunded automatically if it fails. --------- Co-authored-by: jackstar12 <[email protected]>
1 parent 7a03673 commit 8a0304c

File tree

12 files changed

+71
-17
lines changed

12 files changed

+71
-17
lines changed

backend/controllers/shared/boltz.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export const getSwapInfo = (req, res, next) => {
7979
});
8080
};
8181
export const createSwap = (req, res, next) => {
82-
const { amount, sendFromInternal, address } = req.body;
82+
const { amount, sendFromInternal, address, refundAddress } = req.body;
8383
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Boltz', msg: 'Creating Swap..' });
8484
options = common.getBoltzServerOptions(req);
8585
if (options.url === '') {
@@ -88,7 +88,7 @@ export const createSwap = (req, res, next) => {
8888
return res.status(err.statusCode).json({ message: err.message, error: err.error });
8989
}
9090
options.url = options.url + '/v1/createswap';
91-
options.body = { amount: amount };
91+
options.body = { amount: amount, refundAddress };
9292
if (sendFromInternal) {
9393
options.body.send_from_internal = sendFromInternal;
9494
}

frontend/index.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

frontend/main.89468e89473d89c7.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

frontend/main.f5539fed9d1e4c46.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rtl",
3-
"version": "0.15.4-beta",
3+
"version": "0.15.5-beta",
44
"license": "MIT",
55
"type": "module",
66
"scripts": {

server/controllers/shared/boltz.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export const getSwapInfo = (req, res, next) => {
8080
};
8181

8282
export const createSwap = (req, res, next) => {
83-
const { amount, sendFromInternal, address } = req.body;
83+
const { amount, sendFromInternal, address, refundAddress } = req.body;
8484
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Boltz', msg: 'Creating Swap..' });
8585
options = common.getBoltzServerOptions(req);
8686
if (options.url === '') {
@@ -89,7 +89,7 @@ export const createSwap = (req, res, next) => {
8989
return res.status(err.statusCode).json({ message: err.message, error: err.error });
9090
}
9191
options.url = options.url + '/v1/createswap';
92-
options.body = { amount: amount };
92+
options.body = { amount: amount, refundAddress };
9393
if (sendFromInternal) { options.body.send_from_internal = sendFromInternal; }
9494
if (address && address !== '') { options.body.address = address; }
9595
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Boltz', msg: 'Create Swap Options Body', data: options.body });

src/app/shared/components/ln-services/boltz/swap-modal/swap-modal.component.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
3838
<mat-icon matTooltip="Pay from the node's onchain wallet" matTooltipPosition="above" class="info-icon mt-2">info_outline</mat-icon>
3939
</div>
4040
</div>
41+
<div disabled="direction === swapTypeEnum.SWAP_IN && isSendFromInternalCompatible && !inputFormGroup?.controls?.sendFromInternal.value" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" class="mt-1">
42+
<mat-form-field fxLayout="column" fxFlex="100">
43+
<mat-label>Refund Address</mat-label>
44+
<input matInput type="text" tabindex="3" formControlName="refundAddress" [required]="!inputFormGroup?.controls?.sendFromInternal.value">
45+
<mat-hint>The address where funds will be returned in case of a failed swap</mat-hint>
46+
<mat-error *ngIf="inputFormGroup?.controls?.refundAddress?.errors?.required">
47+
Refund address is required when not using internal wallet.
48+
</mat-error>
49+
</mat-form-field>
50+
</div>
4151
</div>
4252
<div class="mt-2" fxLayout="row" fxLayoutAlign="start center" fxFlex="100">
4353
<button *ngIf="direction === swapTypeEnum.SWAP_OUT" mat-button color="primary" tabindex="2" type="button" matStepperNext>Next</button>

src/app/shared/components/ln-services/boltz/swap-modal/swap-modal.component.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ export class SwapModalComponent implements OnInit, AfterViewInit, OnDestroy {
5656
this.inputFormGroup = this.formBuilder.group({
5757
amount: [this.serviceInfo.limits?.minimal, [Validators.required, Validators.min(this.serviceInfo.limits?.minimal || 0), Validators.max(this.serviceInfo.limits?.maximal || 0)]],
5858
acceptZeroConf: [false],
59-
sendFromInternal: [true]
59+
sendFromInternal: [true],
60+
refundAddress: [{ value: '', disabled: true }]
6061
});
6162
this.addressFormGroup = this.formBuilder.group({
6263
addressType: ['local', [Validators.required]],
@@ -89,6 +90,25 @@ export class SwapModalComponent implements OnInit, AfterViewInit, OnDestroy {
8990
this.addressFormGroup.setErrors({ Invalid: true });
9091
});
9192
}
93+
if (this.direction === SwapTypeEnum.SWAP_IN) {
94+
this.inputFormGroup.controls.sendFromInternal.valueChanges.
95+
pipe(takeUntil(this.unSubs[4])).
96+
subscribe(() => {
97+
this.onSendFromInternalChange();
98+
});
99+
}
100+
}
101+
102+
onSendFromInternalChange() {
103+
if (!this.inputFormGroup.controls.sendFromInternal.value) {
104+
this.inputFormGroup.controls.refundAddress.enable();
105+
this.inputFormGroup.controls.refundAddress.setValidators([Validators.required]);
106+
this.inputFormGroup.controls.refundAddress.updateValueAndValidity();
107+
} else {
108+
this.inputFormGroup.controls.refundAddress.disable();
109+
this.inputFormGroup.controls.refundAddress.clearValidators();
110+
this.inputFormGroup.controls.refundAddress.updateValueAndValidity();
111+
}
92112
}
93113

94114
onAddressTypeChange(event: any) {
@@ -115,7 +135,22 @@ export class SwapModalComponent implements OnInit, AfterViewInit, OnDestroy {
115135
this.stepper.selected?.stepControl.setErrors(null);
116136
this.stepper.next();
117137
if (this.direction === SwapTypeEnum.SWAP_IN) {
118-
this.boltzService.swapIn(this.inputFormGroup.controls.amount.value, this.isSendFromInternalCompatible ? this.inputFormGroup.controls.sendFromInternal.value : null).pipe(takeUntil(this.unSubs[2])).
138+
const refundAddress = this.inputFormGroup.controls.sendFromInternal.value ?
139+
null : this.inputFormGroup.controls.refundAddress.value;
140+
141+
const sendFromInternal = this.isSendFromInternalCompatible ? this.inputFormGroup.controls.sendFromInternal.value : null;
142+
143+
if (!sendFromInternal && !refundAddress) {
144+
this.stepper.selected?.stepControl.setErrors({ Invalid: true });
145+
this.flgEditable = true;
146+
return;
147+
}
148+
149+
this.boltzService.swapIn(
150+
this.inputFormGroup.controls.amount.value,
151+
sendFromInternal,
152+
refundAddress
153+
).pipe(takeUntil(this.unSubs[2])).
119154
subscribe({
120155
next: (swapStatus: CreateSwapResponse) => {
121156
this.swapStatus = swapStatus;
@@ -156,7 +191,11 @@ export class SwapModalComponent implements OnInit, AfterViewInit, OnDestroy {
156191
case 1:
157192
if (this.inputFormGroup.controls.amount.value) {
158193
if (this.direction === SwapTypeEnum.SWAP_IN) {
159-
this.inputFormLabel = this.swapDirectionCaption + ' Amount: ' + (this.decimalPipe.transform(this.inputFormGroup.controls.amount.value ? this.inputFormGroup.controls.amount.value : 0)) + ' Sats | Send from Internal Wallet: ' + (this.inputFormGroup.controls.sendFromInternal.value ? 'Yes' : 'No');
194+
let summary = this.swapDirectionCaption + ' Amount: ' + (this.decimalPipe.transform(this.inputFormGroup.controls.amount.value ? this.inputFormGroup.controls.amount.value : 0)) + ' Sats | Send from Internal Wallet: ' + (this.inputFormGroup.controls.sendFromInternal.value ? 'Yes' : 'No');
195+
if (!this.inputFormGroup.controls.sendFromInternal.value && this.inputFormGroup.controls.refundAddress.value) {
196+
summary += ' | Refund Address: ' + this.inputFormGroup.controls.refundAddress.value;
197+
}
198+
this.inputFormLabel = summary;
160199
} else {
161200
this.inputFormLabel = this.swapDirectionCaption + ' Amount: ' + (this.decimalPipe.transform(this.inputFormGroup.controls.amount.value ? this.inputFormGroup.controls.amount.value : 0)) + ' Sats | Zero Conf: ' + (this.inputFormGroup.controls.acceptZeroConf.value ? 'Yes' : 'No');
162201
}
@@ -201,7 +240,12 @@ export class SwapModalComponent implements OnInit, AfterViewInit, OnDestroy {
201240
onRestart() {
202241
this.stepper.reset();
203242
this.flgEditable = true;
204-
this.inputFormGroup.reset({ amount: this.serviceInfo.limits?.minimal, acceptZeroConf: false, sendFromInternal: true });
243+
this.inputFormGroup.reset({
244+
amount: this.serviceInfo.limits?.minimal,
245+
acceptZeroConf: false,
246+
sendFromInternal: true,
247+
refundAddress: ''
248+
});
205249
this.statusFormGroup.reset();
206250
this.addressFormGroup.reset({ addressType: 'local', address: '' });
207251
this.addressFormGroup.controls.address.disable();

src/app/shared/components/node-config/experimental-settings/experimental-settings.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class ExperimentalSettingsComponent implements OnInit, OnDestroy {
4747
this.dataService.listConfigs().pipe(takeUntil(this.unSubs[0])).subscribe({
4848
next: (res: any) => {
4949
this.logger.info('Received List Configs: ' + JSON.stringify(res));
50-
this.features[1].enabled = !!res['experimental-dual-fund'];
50+
this.features[1].enabled = !!res['configs']['experimental-dual-fund']['set'];
5151
}, error: (err) => {
5252
this.logger.error('List Configs Error: ' + JSON.stringify(err));
5353
this.features[1].enabled = false;

0 commit comments

Comments
 (0)