Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump fee with mempool information #1386

Merged
merged 4 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions backend/controllers/shared/RTLConf.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,54 @@ const logger = Logger;
const common = Common;
const wsServer = WSServer;
const databaseService = Database;
// Set local block explorer URL after first API call
// if the selected node block explorer has working REST API suite
// otherwise set it to mempool.space
let blockExplorerUrl = '';
export const getExplorerFeesRecommended = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Recommended Fee Rates..' });
options.url = (blockExplorerUrl === '') ?
req.session.selectedNode.settings.blockExplorerUrl + '/api/v1/fees/recommended' :
blockExplorerUrl + '/api/v1/fees/recommended';
request(options).then((body) => {
blockExplorerUrl = req.session.selectedNode.settings.blockExplorerUrl;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Recommended Fee Rates Received', data: body });
res.status(200).json(JSON.parse(body));
}).catch((errRes) => {
blockExplorerUrl = 'https://mempool.space';
options.url = blockExplorerUrl + '/api/v1/fees/recommended';
return request(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Recommended Fee Rates Received', data: body });
res.status(200).json(JSON.parse(body));
}).catch((errRes) => {
const errMsg = 'Get Recommended Fee Rates Error';
const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode);
return res.status(err.statusCode).json({ message: err.error, error: err.error });
});
});
};
export const getExplorerTransaction = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Transaction From Block Explorer..' });
options.url = (blockExplorerUrl === '') ?
req.session.selectedNode.settings.blockExplorerUrl + '/api/tx/' + req.params.txid :
blockExplorerUrl + '/api/tx/' + req.params.txid;
request(options).then((body) => {
blockExplorerUrl = req.session.selectedNode.settings.blockExplorerUrl;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Transaction From Block Explorer Received', data: body });
res.status(200).json(JSON.parse(body));
}).catch((errRes) => {
blockExplorerUrl = 'https://mempool.space';
options.url = blockExplorerUrl + '/api/tx/' + req.params.txid;
return request(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Transaction From Block Explorer Received', data: body });
res.status(200).json(JSON.parse(body));
}).catch((errRes) => {
const errMsg = 'Get Transaction From Block Explorer Error';
const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode);
return res.status(err.statusCode).json({ message: err.error, error: err.error });
});
});
};
export const getCurrencyRates = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Currency Rates..' });
options.url = 'https://blockchain.info/ticker';
Expand Down Expand Up @@ -99,6 +147,7 @@ export const updateSelectedNode = (req, res, next) => {
databaseService.loadDatabase(req.session);
}
}
blockExplorerUrl = '';
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Selected Node Updated To ' + req.session.selectedNode.lnNode || '' });
res.status(200).json(common.removeAuthSecureData(JSON.parse(JSON.stringify(req.session.selectedNode))));
};
Expand Down
4 changes: 3 additions & 1 deletion backend/routes/shared/RTLConf.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import exprs from 'express';
const { Router } = exprs;
import { isAuthenticated } from '../../utils/authCheck.js';
import { updateNodeSettings, getConfig, getFile, updateSelectedNode, updateApplicationSettings, getCurrencyRates, getApplicationSettings } from '../../controllers/shared/RTLConf.js';
import { updateNodeSettings, getConfig, getFile, updateSelectedNode, updateApplicationSettings, getCurrencyRates, getApplicationSettings, getExplorerFeesRecommended, getExplorerTransaction } from '../../controllers/shared/RTLConf.js';
const router = Router();
router.get('/', getApplicationSettings);
router.get('/rates', getCurrencyRates);
Expand All @@ -10,4 +10,6 @@ router.get('/updateSelNode/:currNodeIndex/:prevNodeIndex', updateSelectedNode);
router.get('/config/:nodeType', isAuthenticated, getConfig);
router.post('/node', isAuthenticated, updateNodeSettings);
router.post('/application', isAuthenticated, updateApplicationSettings);
router.get('/explorerFeesRecommended', getExplorerFeesRecommended);
router.get('/explorerTransaction/:txid', getExplorerTransaction);
export default router;
1 change: 0 additions & 1 deletion frontend/125.05cbc1feb7174532.js

This file was deleted.

1 change: 1 addition & 0 deletions frontend/125.2d8b0d451f9e6528.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/index.html

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions frontend/main.5525c82b788903bc.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion frontend/main.6a8227167750bd90.js

This file was deleted.

1 change: 1 addition & 0 deletions frontend/runtime.9565333e3d711f1e.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion frontend/runtime.d6a10674a23a1478.js

This file was deleted.

51 changes: 51 additions & 0 deletions server/controllers/shared/RTLConf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,56 @@ const logger: LoggerService = Logger;
const common: CommonService = Common;
const wsServer = WSServer;
const databaseService: DatabaseService = Database;
// Set local block explorer URL after first API call
// if the selected node block explorer has working REST API suite
// otherwise set it to mempool.space
let blockExplorerUrl = '';

export const getExplorerFeesRecommended = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Recommended Fee Rates..' });
options.url = (blockExplorerUrl === '') ?
req.session.selectedNode.settings.blockExplorerUrl + '/api/v1/fees/recommended' :
blockExplorerUrl + '/api/v1/fees/recommended';
request(options).then((body) => {
blockExplorerUrl = req.session.selectedNode.settings.blockExplorerUrl;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Recommended Fee Rates Received', data: body });
res.status(200).json(JSON.parse(body));
}).catch((errRes) => {
blockExplorerUrl = 'https://mempool.space';
options.url = blockExplorerUrl + '/api/v1/fees/recommended';
return request(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Recommended Fee Rates Received', data: body });
res.status(200).json(JSON.parse(body));
}).catch((errRes) => {
const errMsg = 'Get Recommended Fee Rates Error';
const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode);
return res.status(err.statusCode).json({ message: err.error, error: err.error });
});
});
};

export const getExplorerTransaction = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Transaction From Block Explorer..' });
options.url = (blockExplorerUrl === '') ?
req.session.selectedNode.settings.blockExplorerUrl + '/api/tx/' + req.params.txid :
blockExplorerUrl + '/api/tx/' + req.params.txid;
request(options).then((body) => {
blockExplorerUrl = req.session.selectedNode.settings.blockExplorerUrl;
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Transaction From Block Explorer Received', data: body });
res.status(200).json(JSON.parse(body));
}).catch((errRes) => {
blockExplorerUrl = 'https://mempool.space';
options.url = blockExplorerUrl + '/api/tx/' + req.params.txid;
return request(options).then((body) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Transaction From Block Explorer Received', data: body });
res.status(200).json(JSON.parse(body));
}).catch((errRes) => {
const errMsg = 'Get Transaction From Block Explorer Error';
const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode);
return res.status(err.statusCode).json({ message: err.error, error: err.error });
});
});
};

export const getCurrencyRates = (req, res, next) => {
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Currency Rates..' });
Expand Down Expand Up @@ -100,6 +150,7 @@ export const updateSelectedNode = (req, res, next) => {
databaseService.loadDatabase(req.session);
}
}
blockExplorerUrl = '';
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Selected Node Updated To ' + req.session.selectedNode.lnNode || '' });
res.status(200).json(common.removeAuthSecureData(JSON.parse(JSON.stringify(req.session.selectedNode))));
};
Expand Down
5 changes: 4 additions & 1 deletion server/routes/shared/RTLConf.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import exprs from 'express';
const { Router } = exprs;
import { isAuthenticated } from '../../utils/authCheck.js';
import { updateNodeSettings, getConfig, getFile, updateSelectedNode, updateApplicationSettings, getCurrencyRates, getApplicationSettings } from '../../controllers/shared/RTLConf.js';
import { updateNodeSettings, getConfig, getFile, updateSelectedNode, updateApplicationSettings, getCurrencyRates, getApplicationSettings,
getExplorerFeesRecommended, getExplorerTransaction } from '../../controllers/shared/RTLConf.js';

const router = Router();

Expand All @@ -12,5 +13,7 @@ router.get('/updateSelNode/:currNodeIndex/:prevNodeIndex', updateSelectedNode);
router.get('/config/:nodeType', isAuthenticated, getConfig);
router.post('/node', isAuthenticated, updateNodeSettings);
router.post('/application', isAuthenticated, updateApplicationSettings);
router.get('/explorerFeesRecommended', getExplorerFeesRecommended);
router.get('/explorerTransaction/:txid', getExplorerTransaction);

export default router;
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between stretch">
<div fxFlex="100" class="alert alert-info">
<fa-icon class="mr-1 alert-icon" [icon]="faInfoCircle" />
<span fxLayout="column" fxFlex="100">Bumping fee on pending open channels is an advanced feature, attempt it only if you are familiar with the functionality of Bitcoin transactions.
<div>Before attempting fee bump ensure the following:</div>
<div class="pl-1">1: Use a Bitcoin block explorer to ensure that channel opening transaction is not confirmed.</div>
<div class="pl-1">2: The channel opening transaction must have a sizable change output, which can be spent further. The fee cannot be bumped without the change output.</div>
<div class="pl-1">3: Find the index value of the change output via a block explorer.</div>
<div class="pl-1">4: Enter the index value of the change output in the form below and the desired fee rate.</div>
<div class="pl-1">5: Upon successful fee bump, use your block explorer to track the child transaction in the mempool, which should be linked with the change output transaction.</div>
<span fxLayout="column" fxFlex="100">
<div>Fee rates recommended by mempool.space (sat/vByte):</div>
<div>- High: {{recommendedFee.fastestFee || 'Unknown'}}</div>
<div>- Medium: {{recommendedFee.halfHourFee || 'Unknown'}}</div>
<div>- Low: {{recommendedFee.hourFee || 'Unknown'}}</div>
</span>
</div>
<div *ngIf="flgShowDustWarning" fxFlex="100" class="alert alert-warn">
<fa-icon class="mr-1 alert-icon" [icon]="faExclamationTriangle" />
<span>Change output balance <strong>{{dustOutputValue | number}}</strong> (Sats) may be insufficient for fee bumping, depending on the prevailing fee rates.</span>
</div>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between center">
<mat-form-field fxLayout="column" fxFlex="49">
<mat-label>Output Index</mat-label>
Expand Down
Loading
Loading