mirror of
https://github.com/Ride-The-Lightning/RTL.git
synced 2026-08-13 12:33:07 +02:00
Release 0.15.1 (#1406)
* rm .DS_Store * Add watchfrontenddev command for npm * Fix toggle issues in sidenav (pinning and on page refresh) * Add copy-to-clipboard fallback if navigator.clipboard is not available (#1336) * add copy-to-clipboard fallback if navigator.clipboard is not available * amend copy fallback * clipboard copy lint fixes and frontend build * fix: add missing boltz state `transaction.lockupFailed` (#1349) * fix: boltzd docs link (#1354) * exit gracefully (#1356) * allow for eclair updated relayed audit format (#1363) * feat: add boltz service to cln (#1352) * lint fix * Request Params Cleanup * cln: Boltz auto-send (#1366) * Bug-fix (CLN Boltz): Hide claim tx id and routing fee for non-zero conf reverse swap * cln: Boltz auto-send - Added auto send option for Swap In - Checking compatiblity with v2.0.0 and above * Test import fixes * Update help.component.ts (#1379) Fixed broken link under "Help" -> "Node Settings" * Backend config fix (#1382) * Updating Common Application Configuration * Fixed get RTL Conf * Update Application Settings * application and settings case change * Unified config models * Default node update * 2FA and Password reset * Final application settings update * Config Settings and Authentication case fixed * Node Setting Fix * Fiat currency Symbol fix * CLN: Fiat symbol fix * All: Fiat symbol fix * Update node settings * Services UI fix * CLN: Removed child node settings * All: Removed child node settings * Test fixes * mempool links for onchain information (#1383) * Tests fix Tests fix * UI for Block Explorer Configuration (#1385) * Bump fee with mempool information (#1386) * Mempool openchannel minfee (#1388) Open channel model block if min fee is higher * Show error on login screen if rune is incorrect and getinfo throws error (#1391) * cln: Removed channel lookup call for update policy (#1392) * ECL: On-chain Transactions, Invoice and Payments pagination (#1393) Done most of the UI changes to accommodate pagination on transactions, payments and invoices tables but true pagination cannot be implemented till total number of records are missing from the API response. Once the issue https://github.com/ACINQ/eclair/issues/2855 is fixed, I will uncomment pagination changes in the frontend. * lnd: Onchain CPFP (#1394) - UTXO label bug fix - Warning on utxo label for "sweep" in text. * Bug fixes after testing * Testing bug fixes (#1401) * Bug fix 2: lnd: Link channel point to explorer and show fee on close channel too * lnd: explorer link on pending channels * Node lookup link on view channel peer pubkey * Testing bug fixes (#1402) * Bug fix 2: lnd: Link channel point to explorer and show fee on close channel too * lnd: explorer link on pending channels * Node lookup link on view channel peer pubkey * test fixes * ng update to v18.0.x * Updating install with --legacy-peer-deps --------- Co-authored-by: Grzegorz Kućmierz <gkucmierz@gmail.com> Co-authored-by: lacksfish <lacksfish@gmail.com> Co-authored-by: jackstar12 <62219658+jackstar12@users.noreply.github.com> Co-authored-by: Kilian <19181985+kilrau@users.noreply.github.com> Co-authored-by: Taylor King <taylorbradleyking@gmail.com> Co-authored-by: Fishcake <128653975+fishcakeday@users.noreply.github.com> Co-authored-by: Ant <72945059+2140data@users.noreply.github.com>
This commit is contained in:
parent
ea7f300360
commit
22ab6d1154
384 changed files with 9400 additions and 9035 deletions
|
|
@ -11,7 +11,7 @@ export const listPeerChannels = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Peer Channels..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listpeerchannels';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listpeerchannels';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: body.channels });
|
||||
return Promise.all(body.channels?.map((channel) => {
|
||||
|
|
@ -32,7 +32,7 @@ export const openChannel = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Opening Channel..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/fundchannel';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/fundchannel';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Open Channel Options', data: options.body });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -48,7 +48,7 @@ export const setChannelFee = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Setting Channel Fee..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/setchannel';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/setchannel';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Update Channel Policy Options', data: options.body });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -65,7 +65,7 @@ export const closeChannel = (req, res, next) => {
|
|||
req.setTimeout(60000 * 10); // timeout 10 mins
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/close';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/close';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Closing Channel', data: options.url });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -78,14 +78,15 @@ export const closeChannel = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const listForwards = (req, res, next) => {
|
||||
const { status } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Channel List Forwards..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listforwards';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listforwards';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Forwarding History Received For Status ' + req.body.status, data: body });
|
||||
body.forwards = !body.forwards ? [] : (req.body.status === 'failed' || req.body.status === 'local_failed') ? body.forwards.slice(Math.max(0, body.forwards.length - 1000), Math.max(1000, body.forwards.length)).reverse() : body.forwards.reverse();
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Forwarding History Received For Status ' + status, data: body });
|
||||
body.forwards = !body.forwards ? [] : (status === 'failed' || status === 'local_failed') ? body.forwards.slice(Math.max(0, body.forwards.length - 1000), Math.max(1000, body.forwards.length)).reverse() : body.forwards.reverse();
|
||||
res.status(200).json(body.forwards);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'Forwarding History Error', req.session.selectedNode);
|
||||
|
|
@ -97,7 +98,7 @@ export const funderUpdatePolicy = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting or Updating Funder Policy..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/funderupdate';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/funderupdate';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Funder Update Body', data: options.body });
|
||||
request.post(options).then((body) => {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ export const getInfo = (req, res, next) => {
|
|||
common.setOptions(req);
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/getinfo';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Selected Node ' + req.session.selectedNode.ln_node });
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/getinfo';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Selected Node ' + req.session.selectedNode.lnNode });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Calling Info from Core Lightning server url ' + options.url });
|
||||
if (!options.headers || !options.headers.rune) {
|
||||
const errMsg = 'Core lightning get info failed due to missing rune!';
|
||||
|
|
@ -45,7 +45,7 @@ export const getInfo = (req, res, next) => {
|
|||
body.uris.push(body.id + '@' + addr.address + ':' + addr.port);
|
||||
});
|
||||
}
|
||||
req.session.selectedNode.ln_version = body.version || '';
|
||||
req.session.selectedNode.lnVersion = body.version || '';
|
||||
req.session.selectedNode.api_version = body.api_version || '';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Connecting to the Core Lightning\'s Websocket Server.' });
|
||||
clWsClient.updateSelectedNode(req.session.selectedNode);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const deleteExpiredInvoice = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Deleting Expired Invoices..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/delexpiredinvoice';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/delexpiredinvoice';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Invoices Deleted', data: body });
|
||||
|
|
@ -24,7 +24,7 @@ export const listInvoices = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Getting Invoices..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listinvoices';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listinvoices';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Invoice', msg: 'Invoices List URL', data: options.url });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -40,7 +40,7 @@ export const addInvoice = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Creating Invoice..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/invoice';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/invoice';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Invoice Created', data: body });
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
|
|
@ -11,7 +11,7 @@ export const getRoute = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Getting Network Routes..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/getroute';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/getroute';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Network Routes Received', data: body });
|
||||
|
|
@ -29,7 +29,7 @@ export const listChannels = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Channel Lookup..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listchannels';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listchannels';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Channel Lookup Finished', data: body });
|
||||
|
|
@ -41,13 +41,14 @@ export const listChannels = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const feeRates = (req, res, next) => {
|
||||
const { style } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Getting Network Fee Rates..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/feerates';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/feerates';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Network Fee Rates Received for ' + req.body.style, data: body });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Network Fee Rates Received for ' + style, data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Network', 'Fee Rates Error', req.session.selectedNode);
|
||||
|
|
@ -56,12 +57,12 @@ export const feeRates = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const listNodes = (req, res, next) => {
|
||||
const filter_liquidity_ads = !!req.body.liquidity_ads;
|
||||
delete req.body.liquidity_ads;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'List Nodes..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listnodes';
|
||||
const filter_liquidity_ads = !!req.body.liquidity_ads;
|
||||
delete req.body.liquidity_ads;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listnodes';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Network', msg: 'List Nodes URL' + options.url });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -77,8 +78,8 @@ export const listNodes = (req, res, next) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const getAlias = (selNode: CommonSelectedNode, peer: any, id: string) => {
|
||||
options.url = selNode.ln_server_url + '/v1/listnodes';
|
||||
export const getAlias = (selNode: SelectedNode, peer: any, id: string) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/v1/listnodes';
|
||||
if (!peer[id]) {
|
||||
logger.log({ selectedNode: selNode, level: 'ERROR', fileName: 'Network', msg: 'Empty Peer ID' });
|
||||
peer.alias = '';
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@ export const listOfferBookmarks = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const deleteOfferBookmark = (req, res, next) => {
|
||||
const { offer_str } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Deleting Offer Bookmark..' });
|
||||
databaseService.remove(req.session.selectedNode, CollectionsEnum.OFFERS, CollectionFieldsEnum.BOLT12, req.body.offer_str).then((deleteRes) => {
|
||||
databaseService.remove(req.session.selectedNode, CollectionsEnum.OFFERS, CollectionFieldsEnum.BOLT12, offer_str).then((deleteRes) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offer Bookmark Deleted', data: deleteRes });
|
||||
res.status(204).json(req.body.offer_str);
|
||||
res.status(204).json(offer_str);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Offers', 'Offer Bookmark Delete Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
|
|
@ -35,7 +36,7 @@ export const listOffers = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Getting Offers..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listoffers';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listoffers';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Offers', msg: 'Offers List URL', data: options.url });
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offers List Received', data: body });
|
||||
|
|
@ -50,7 +51,7 @@ export const createOffer = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Creating Offer..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/offer';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/offer';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offer Created', data: body });
|
||||
|
|
@ -65,7 +66,7 @@ export const fetchOfferInvoice = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Getting Offer Invoice..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/fetchinvoice';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/fetchinvoice';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Offers', msg: 'Offer Invoice Body', data: options.body });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -81,7 +82,7 @@ export const disableOffer = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Disabling Offer..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/disableOffer';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/disableOffer';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offer Disabled', data: body });
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const getNewAddress = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Generating New Address..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/newaddr';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/newaddr';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'New Address Generated', data: body });
|
||||
|
|
@ -24,7 +24,7 @@ export const onChainWithdraw = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Withdrawing from On Chain..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/withdraw';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/withdraw';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'OnChain', msg: 'OnChain Withdraw Options', data: options.body });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -40,7 +40,7 @@ export const getUTXOs = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Listing Funds..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listfunds';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listfunds';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Funds List Received', data: body });
|
||||
// Local Remote Balance Calculation
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ import { Logger, LoggerService } from '../../utils/logger.js';
|
|||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { Database, DatabaseService } from '../../utils/database.js';
|
||||
import { CollectionFieldsEnum, CollectionsEnum, Offer } from '../../models/database.model.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
const databaseService: DatabaseService = Database;
|
||||
|
||||
export const getMemo = (selNode: CommonSelectedNode, payment: any) => {
|
||||
options.url = selNode.ln_server_url + '/v1/decode';
|
||||
export const getMemo = (selNode: SelectedNode, payment: any) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/v1/decode';
|
||||
options.body = { string: payment.bolt11 };
|
||||
return request.post(options).then((res) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment Decode Received', data: res });
|
||||
|
|
@ -74,7 +74,7 @@ export const listPayments = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'List Payments..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listsendpays';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listsendpays';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment List Received', data: body.payments });
|
||||
body.payments = body.payments && body.payments.length && body.payments.length > 0 ? groupBy(body.payments) : [];
|
||||
|
|
@ -89,12 +89,13 @@ export const listPayments = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const postPayment = (req, res, next) => {
|
||||
const { paymentType, saveToDB, bolt12, zeroAmtOffer, amount_msat, title, issuer, description } = req.body;
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
const options_body = JSON.parse(JSON.stringify(req.body));
|
||||
if (req.body.paymentType === 'KEYSEND') {
|
||||
if (paymentType === 'KEYSEND') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Keysend Payment..' });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/keysend';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/keysend';
|
||||
delete options_body.uiMessage;
|
||||
delete options_body.fromDialog;
|
||||
delete options_body.paymentType;
|
||||
|
|
@ -112,12 +113,12 @@ export const postPayment = (req, res, next) => {
|
|||
delete options_body.saveToDB;
|
||||
options.body = options_body;
|
||||
} else {
|
||||
if (req.body.paymentType === 'OFFER') {
|
||||
if (paymentType === 'OFFER') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Sending Offer Payment..' });
|
||||
} else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Sending Invoice Payment..' });
|
||||
}
|
||||
if (req.body.paymentType === 'OFFER') {
|
||||
if (paymentType === 'OFFER') {
|
||||
// delete amount for zero amt offer also as fetchinvoice already has amount information
|
||||
delete options_body.amount_msat;
|
||||
}
|
||||
|
|
@ -133,18 +134,18 @@ export const postPayment = (req, res, next) => {
|
|||
delete options_body.pubkey;
|
||||
delete options_body.saveToDB;
|
||||
options.body = options_body;
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/pay';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/pay';
|
||||
}
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Sent', data: body });
|
||||
if (req.body.paymentType === 'OFFER') {
|
||||
if (req.body.saveToDB && req.body.bolt12) {
|
||||
const offerToUpdate: Offer = { bolt12: req.body.bolt12, amountMSat: (req.body.zeroAmtOffer ? 0 : req.body.amount_msat), title: req.body.title, lastUpdatedAt: new Date(Date.now()).getTime() };
|
||||
if (req.body.issuer) { offerToUpdate['issuer'] = req.body.issuer; }
|
||||
if (req.body.description) { offerToUpdate['description'] = req.body.description; }
|
||||
if (paymentType === 'OFFER') {
|
||||
if (saveToDB && bolt12) {
|
||||
const offerToUpdate: Offer = { bolt12: bolt12, amountMSat: (zeroAmtOffer ? 0 : amount_msat), title: title, lastUpdatedAt: new Date(Date.now()).getTime() };
|
||||
if (issuer) { offerToUpdate['issuer'] = issuer; }
|
||||
if (description) { offerToUpdate['description'] = description; }
|
||||
// eslint-disable-next-line arrow-body-style
|
||||
return databaseService.validateDocument(CollectionsEnum.OFFERS, offerToUpdate).then((validated) => {
|
||||
return databaseService.update(req.session.selectedNode, CollectionsEnum.OFFERS, offerToUpdate, CollectionFieldsEnum.BOLT12, req.body.bolt12).then((updatedOffer) => {
|
||||
return databaseService.update(req.session.selectedNode, CollectionsEnum.OFFERS, offerToUpdate, CollectionFieldsEnum.BOLT12, bolt12).then((updatedOffer) => {
|
||||
logger.log({ level: 'DEBUG', fileName: 'Payments', msg: 'Offer Updated', data: updatedOffer });
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: updatedOffer });
|
||||
}).catch((errDB) => {
|
||||
|
|
@ -159,10 +160,10 @@ export const postPayment = (req, res, next) => {
|
|||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: 'NA' });
|
||||
}
|
||||
}
|
||||
if (req.body.paymentType === 'INVOICE') {
|
||||
if (paymentType === 'INVOICE') {
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: 'NA' });
|
||||
}
|
||||
if (req.body.paymentType === 'KEYSEND') {
|
||||
if (paymentType === 'KEYSEND') {
|
||||
return res.status(201).json(body);
|
||||
}
|
||||
}).catch((errRes) => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export const getPeers = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'List Peers..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listpeers';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listpeers';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers List Received', data: body });
|
||||
const peers = !body.peers ? [] : body.peers;
|
||||
|
|
@ -29,12 +29,12 @@ export const postPeer = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Connecting Peer..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/connect';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/connect';
|
||||
options.body = req.body;
|
||||
request.post(options).then((connectRes) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peer Connected', data: connectRes });
|
||||
const listOptions = common.getOptions(req);
|
||||
listOptions.url = req.session.selectedNode.ln_server_url + '/v1/listpeers';
|
||||
listOptions.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listpeers';
|
||||
request.post(listOptions).then((listPeersRes) => {
|
||||
const peers = listPeersRes && listPeersRes.peers ? common.newestOnTop(listPeersRes.peers, 'id', connectRes.id) : [];
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peers List after Connect Received', data: peers });
|
||||
|
|
@ -53,7 +53,7 @@ export const deletePeer = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Disconnecting Peer..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/disconnect';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/disconnect';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peer Disconnected', data: body });
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const decodePayment = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Decoding Payment..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/decode';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/decode';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Decoded', data: body });
|
||||
|
|
@ -25,7 +25,7 @@ export const signMessage = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Signing Message..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/signmessage';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/signmessage';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Signed', data: body });
|
||||
|
|
@ -40,7 +40,7 @@ export const verifyMessage = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Verifying Message..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/checkmessage';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/checkmessage';
|
||||
options.body = req.body;
|
||||
request.post(options, (error, response, body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body });
|
||||
|
|
@ -55,7 +55,7 @@ export const listConfigs = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Utility', msg: 'List Configs..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listconfigs';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listconfigs';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Utility', msg: 'List Configs Received', data: body });
|
||||
res.status(200).json(body);
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ import socketIOClient from 'socket.io-client';
|
|||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { WSServer } from '../../utils/webSocketServer.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
|
||||
export class CLWebSocketClient {
|
||||
|
||||
public logger: LoggerService = Logger;
|
||||
public common: CommonService = Common;
|
||||
public wsServer = WSServer;
|
||||
public webSocketClients: Array<{ selectedNode: CommonSelectedNode, reConnect: boolean, webSocketClient: any }> = [];
|
||||
public webSocketClients: Array<{ selectedNode: SelectedNode, reConnect: boolean, webSocketClient: any }> = [];
|
||||
public reconnectTimeOut = null;
|
||||
public waitTime = 0.5;
|
||||
|
||||
|
|
@ -34,17 +34,17 @@ export class CLWebSocketClient {
|
|||
}, this.waitTime * 1000);
|
||||
};
|
||||
|
||||
public connect = (selectedNode: CommonSelectedNode) => {
|
||||
public connect = (selectedNode: SelectedNode) => {
|
||||
try {
|
||||
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
|
||||
if (!clientExists) {
|
||||
if (selectedNode.ln_server_url) {
|
||||
if (selectedNode.settings.lnServerUrl) {
|
||||
const newWebSocketClient = { selectedNode: selectedNode, reConnect: true, webSocketClient: null };
|
||||
this.connectWithClient(newWebSocketClient);
|
||||
this.webSocketClients.push(newWebSocketClient);
|
||||
}
|
||||
} else {
|
||||
if ((!clientExists.webSocketClient || !clientExists.webSocketClient.connected) && selectedNode.ln_server_url) {
|
||||
if ((!clientExists.webSocketClient || !clientExists.webSocketClient.connected) && selectedNode.settings.lnServerUrl) {
|
||||
clientExists.reConnect = true;
|
||||
this.connectWithClient(clientExists);
|
||||
}
|
||||
|
|
@ -57,11 +57,11 @@ export class CLWebSocketClient {
|
|||
public connectWithClient = (clWsClt) => {
|
||||
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Connecting to the Core Lightning\'s Websocket Server..' });
|
||||
try {
|
||||
if (!clWsClt.selectedNode.rune_value) {
|
||||
clWsClt.selectedNode.rune_value = this.common.getRuneValue(clWsClt.selectedNode.rune_path);
|
||||
if (!clWsClt.selectedNode.authentication.runeValue) {
|
||||
clWsClt.selectedNode.authentication.runeValue = this.common.getRuneValue(clWsClt.selectedNode.authentication.runePath);
|
||||
}
|
||||
clWsClt.webSocketClient = socketIOClient(clWsClt.selectedNode.ln_server_url, {
|
||||
extraHeaders: { rune: clWsClt.selectedNode.rune_value },
|
||||
clWsClt.webSocketClient = socketIOClient(clWsClt.selectedNode.settings.lnServerUrl, {
|
||||
extraHeaders: { rune: clWsClt.selectedNode.authentication.runeValue },
|
||||
transports: ['websocket'],
|
||||
secure: true,
|
||||
rejectUnauthorized: false
|
||||
|
|
@ -76,7 +76,7 @@ export class CLWebSocketClient {
|
|||
});
|
||||
|
||||
clWsClt.webSocketClient.on('disconnect', (reason) => {
|
||||
if (clWsClt && clWsClt.selectedNode && clWsClt.selectedNode.ln_implementation === 'CLN') {
|
||||
if (clWsClt && clWsClt.selectedNode && clWsClt.selectedNode.lnImplementation === 'CLN') {
|
||||
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Web socket disconnected, will reconnect again...', data: reason });
|
||||
clWsClt.webSocketClient.close();
|
||||
if (clWsClt.reConnect) { this.reconnect(clWsClt); }
|
||||
|
|
@ -97,7 +97,7 @@ export class CLWebSocketClient {
|
|||
});
|
||||
};
|
||||
|
||||
public disconnect = (selectedNode: CommonSelectedNode) => {
|
||||
public disconnect = (selectedNode: SelectedNode) => {
|
||||
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
|
||||
if (clientExists && clientExists.webSocketClient && clientExists.webSocketClient.connected) {
|
||||
this.logger.log({ selectedNode: clientExists.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Disconnecting from the Core Lightning\'s Websocket Server..' });
|
||||
|
|
@ -108,7 +108,7 @@ export class CLWebSocketClient {
|
|||
}
|
||||
};
|
||||
|
||||
public updateSelectedNode = (newSelectedNode: CommonSelectedNode) => {
|
||||
public updateSelectedNode = (newSelectedNode: SelectedNode) => {
|
||||
const clientIdx = this.webSocketClients.findIndex((wsc) => +wsc.selectedNode.index === +newSelectedNode.index);
|
||||
let newClient = this.webSocketClients[clientIdx];
|
||||
if (!newClient) { newClient = { selectedNode: null, reConnect: true, webSocketClient: null }; }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
import { createInvoiceRequestCall, listPendingInvoicesRequestCall } from './invoices.js';
|
||||
import { findRouteBetweenNodesRequestCall } from './network.js';
|
||||
import { getSentInfoFromPaymentRequest, sendPaymentToRouteRequestCall } from './payments.js';
|
||||
|
|
@ -10,7 +10,7 @@ let options = null;
|
|||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
||||
export const simplifyAllChannels = (selNode: CommonSelectedNode, channels) => {
|
||||
export const simplifyAllChannels = (selNode: SelectedNode, channels) => {
|
||||
let channelNodeIds = '';
|
||||
const simplifiedChannels = [];
|
||||
channels.forEach((channel) => {
|
||||
|
|
@ -30,7 +30,7 @@ export const simplifyAllChannels = (selNode: CommonSelectedNode, channels) => {
|
|||
});
|
||||
});
|
||||
channelNodeIds = channelNodeIds.substring(1);
|
||||
options.url = selNode.ln_server_url + '/nodes';
|
||||
options.url = selNode.settings.lnServerUrl + '/nodes';
|
||||
options.form = { nodeIds: channelNodeIds };
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Channels', msg: 'Node Ids to find alias', data: channelNodeIds });
|
||||
return request.post(options).then((nodes) => {
|
||||
|
|
@ -49,7 +49,7 @@ export const getChannels = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'List Channels..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/channels';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/channels';
|
||||
options.form = {};
|
||||
if (req.query && req.query.nodeId) {
|
||||
options.form = req.query;
|
||||
|
|
@ -57,7 +57,7 @@ export const getChannels = (req, res, next) => {
|
|||
}
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Options', data: options });
|
||||
if (common.read_dummy_data) {
|
||||
common.getDummyData('Channels', req.session.selectedNode.ln_implementation).then((data) => { res.status(200).json(data); });
|
||||
common.getDummyData('Channels', req.session.selectedNode.lnImplementation).then((data) => { res.status(200).json(data); });
|
||||
} else {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Channels List Received', data: body });
|
||||
|
|
@ -82,7 +82,7 @@ export const getChannelStats = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Channel States..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/channelstats';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/channelstats';
|
||||
const today = new Date(Date.now());
|
||||
const tillToday = (Math.round(today.getTime() / 1000)).toString();
|
||||
const fromLastMonth = (Math.round(new Date(today.getFullYear(), today.getMonth() - 1, today.getDate() + 1, 0, 0, 0).getTime() / 1000)).toString();
|
||||
|
|
@ -103,7 +103,7 @@ export const openChannel = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Opening Channel..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/open';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/open';
|
||||
options.form = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Open Channel Params', data: options.form });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -119,7 +119,7 @@ export const updateChannelRelayFee = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Updating Channel Relay Fee..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/updaterelayfee';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/updaterelayfee';
|
||||
options.form = req.query;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Update Relay Fee Params', data: options.form });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -136,10 +136,10 @@ export const closeChannel = (req, res, next) => {
|
|||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
if (req.query.force !== 'true') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Closing Channel..' });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/close';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/close';
|
||||
} else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Force Closing Channel..' });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/forceclose';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/forceclose';
|
||||
}
|
||||
options.form = { channelId: req.query.channelId };
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Close URL', data: options.url });
|
||||
|
|
@ -154,7 +154,8 @@ export const closeChannel = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const circularRebalance = (req, res, next) => {
|
||||
const crInvDescription = 'Circular rebalancing invoice for ' + (req.body.amountMsat / 1000) + ' Sats';
|
||||
const { amountMsat, sourceNodeId, targetNodeId, ignoreNodeIds, format, sourceShortChannelId, targetShortChannelId } = req.body;
|
||||
const crInvDescription = 'Circular rebalancing invoice for ' + (amountMsat / 1000) + ' Sats';
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.form = req.body;
|
||||
|
|
@ -162,22 +163,22 @@ export const circularRebalance = (req, res, next) => {
|
|||
const tillToday = (Math.round(new Date(Date.now()).getTime() / 1000)).toString();
|
||||
// Check if unpaid Invoice exists already
|
||||
listPendingInvoicesRequestCall(req.session.selectedNode).then((callRes: any[]) => {
|
||||
const foundExistingInvoice = callRes.find((inv) => inv.description.includes(crInvDescription) && inv.amount === req.body.amountMsat && inv.expiry && inv.timestamp && ((inv.expiry + inv.timestamp) >= tillToday));
|
||||
const foundExistingInvoice = callRes.find((inv) => inv.description.includes(crInvDescription) && inv.amount === amountMsat && inv.expiry && inv.timestamp && ((inv.expiry + inv.timestamp) >= tillToday));
|
||||
// Create new invoice if doesn't exist already
|
||||
const requestCalls = foundExistingInvoice && foundExistingInvoice.serialized ?
|
||||
[findRouteBetweenNodesRequestCall(req.session.selectedNode, req.body.amountMsat, req.body.sourceNodeId, req.body.targetNodeId, req.body.ignoreNodeIds, req.body.format)] :
|
||||
[findRouteBetweenNodesRequestCall(req.session.selectedNode, req.body.amountMsat, req.body.sourceNodeId, req.body.targetNodeId, req.body.ignoreNodeIds, req.body.format), createInvoiceRequestCall(req.session.selectedNode, crInvDescription, req.body.amountMsat)];
|
||||
[findRouteBetweenNodesRequestCall(req.session.selectedNode, amountMsat, sourceNodeId, targetNodeId, ignoreNodeIds, format)] :
|
||||
[findRouteBetweenNodesRequestCall(req.session.selectedNode, amountMsat, sourceNodeId, targetNodeId, ignoreNodeIds, format), createInvoiceRequestCall(req.session.selectedNode, crInvDescription, amountMsat)];
|
||||
Promise.all(requestCalls).then((values: any[]) => {
|
||||
// eslint-disable-next-line arrow-body-style
|
||||
const routes = values[0]?.routes?.filter((route) => {
|
||||
return !((route.shortChannelIds[0] === req.body.sourceShortChannelId && route.shortChannelIds[1] === req.body.targetShortChannelId) ||
|
||||
(route.shortChannelIds[1] === req.body.sourceShortChannelId && route.shortChannelIds[0] === req.body.targetShortChannelId));
|
||||
return !((route.shortChannelIds[0] === sourceShortChannelId && route.shortChannelIds[1] === targetShortChannelId) ||
|
||||
(route.shortChannelIds[1] === sourceShortChannelId && route.shortChannelIds[0] === targetShortChannelId));
|
||||
});
|
||||
const firstRoute = routes[0].shortChannelIds.join() || '';
|
||||
const shortChannelIds = req.body.sourceShortChannelId + ',' + firstRoute + ',' + req.body.targetShortChannelId;
|
||||
const shortChannelIds = sourceShortChannelId + ',' + firstRoute + ',' + targetShortChannelId;
|
||||
const invoice = (foundExistingInvoice && foundExistingInvoice.serialized ? foundExistingInvoice.serialized : (values[1] ? values[1].serialized : '')) || '';
|
||||
const paymentHash = (foundExistingInvoice && foundExistingInvoice.paymentHash ? foundExistingInvoice.paymentHash : (values[1] ? values[1].paymentHash : '') || '');
|
||||
return sendPaymentToRouteRequestCall(req.session.selectedNode, shortChannelIds, invoice, req.body.amountMsat).then((payToRouteCallRes) => {
|
||||
return sendPaymentToRouteRequestCall(req.session.selectedNode, shortChannelIds, invoice, amountMsat).then((payToRouteCallRes) => {
|
||||
// eslint-disable-next-line arrow-body-style
|
||||
setTimeout(() => {
|
||||
return getSentInfoFromPaymentRequest(req.session.selectedNode, paymentHash).then((sentInfoCallRes) => {
|
||||
|
|
|
|||
|
|
@ -1,34 +1,35 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
||||
export const arrangeFees = (selNode: CommonSelectedNode, body, current_time) => {
|
||||
export const arrangeFees = (selNode: SelectedNode, body, current_time) => {
|
||||
const fees = { daily_fee: 0, daily_txs: 0, weekly_fee: 0, weekly_txs: 0, monthly_fee: 0, monthly_txs: 0 };
|
||||
const week_start_time = current_time - 604800000;
|
||||
const day_start_time = current_time - 86400000;
|
||||
let fee = 0;
|
||||
body.relayed.forEach((relayedEle) => {
|
||||
fee = Math.round((relayedEle.amountIn - relayedEle.amountOut) / 1000);
|
||||
if (relayedEle.timestamp) {
|
||||
if (relayedEle.timestamp.unix) {
|
||||
if ((relayedEle.timestamp.unix * 1000) >= day_start_time) {
|
||||
const relayedEleTimestamp = relayedEle.settledAt ? relayedEle.settledAt : relayedEle.timestamp;
|
||||
if (relayedEleTimestamp) {
|
||||
if (relayedEleTimestamp.unix) {
|
||||
if ((relayedEleTimestamp.unix * 1000) >= day_start_time) {
|
||||
fees.daily_fee = fees.daily_fee + fee;
|
||||
fees.daily_txs = fees.daily_txs + 1;
|
||||
}
|
||||
if ((relayedEle.timestamp.unix * 1000) >= week_start_time) {
|
||||
if ((relayedEleTimestamp.unix * 1000) >= week_start_time) {
|
||||
fees.weekly_fee = fees.weekly_fee + fee;
|
||||
fees.weekly_txs = fees.weekly_txs + 1;
|
||||
}
|
||||
} else {
|
||||
if (relayedEle.timestamp >= day_start_time) {
|
||||
if (relayedEleTimestamp >= day_start_time) {
|
||||
fees.daily_fee = fees.daily_fee + fee;
|
||||
fees.daily_txs = fees.daily_txs + 1;
|
||||
}
|
||||
if (relayedEle.timestamp >= week_start_time) {
|
||||
if (relayedEleTimestamp >= week_start_time) {
|
||||
fees.weekly_fee = fees.weekly_fee + fee;
|
||||
fees.weekly_txs = fees.weekly_txs + 1;
|
||||
}
|
||||
|
|
@ -41,7 +42,7 @@ export const arrangeFees = (selNode: CommonSelectedNode, body, current_time) =>
|
|||
return fees;
|
||||
};
|
||||
|
||||
export const arrangePayments = (selNode: CommonSelectedNode, body) => {
|
||||
export const arrangePayments = (selNode: SelectedNode, body) => {
|
||||
const payments = {
|
||||
sent: body && body.sent ? body.sent : [],
|
||||
received: body && body.received ? body.received : [],
|
||||
|
|
@ -68,7 +69,10 @@ export const arrangePayments = (selNode: CommonSelectedNode, body) => {
|
|||
}
|
||||
});
|
||||
payments.relayed.forEach((relayedEle) => {
|
||||
if (relayedEle.timestamp.unix) { relayedEle.timestamp = relayedEle.timestamp.unix * 1000; }
|
||||
// Changing the timestamp value to keep the response backward compatible.
|
||||
// ECL < 0.7.0 sent timestamp in unix milliseconds, then in {"iso", "unix"} object.
|
||||
// From v0.10.0, it sends settledAt in {"iso", "unix"} object too.
|
||||
relayedEle.timestamp = relayedEle.settledAt && relayedEle.settledAt.unix ? relayedEle.settledAt.unix * 1000 : relayedEle.timestamp && relayedEle.timestamp.unix ? relayedEle.timestamp.unix * 1000 : relayedEle.timestamp;
|
||||
if (relayedEle.amountIn) { relayedEle.amountIn = Math.round(relayedEle.amountIn / 1000); }
|
||||
if (relayedEle.amountOut) { relayedEle.amountOut = Math.round(relayedEle.amountOut / 1000); }
|
||||
});
|
||||
|
|
@ -80,7 +84,7 @@ export const getFees = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Getting Fees..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/audit';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/audit';
|
||||
const today = new Date(Date.now());
|
||||
const tillToday = (Math.round(today.getTime() / 1000)).toString();
|
||||
const fromLastMonth = (Math.round(new Date(today.getFullYear(), today.getMonth() - 1, today.getDate() + 1, 0, 0, 0).getTime() / 1000)).toString();
|
||||
|
|
@ -90,7 +94,7 @@ export const getFees = (req, res, next) => {
|
|||
};
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Fees', msg: 'Fee Audit Options', data: options.form });
|
||||
if (common.read_dummy_data) {
|
||||
common.getDummyData('Fees', req.session.selectedNode.ln_implementation).then((data) => { res.status(200).json(arrangeFees(req.session.selectedNode, data, Math.round((new Date().getTime())))); });
|
||||
common.getDummyData('Fees', req.session.selectedNode.lnImplementation).then((data) => { res.status(200).json(arrangeFees(req.session.selectedNode, data, Math.round((new Date().getTime())))); });
|
||||
} else {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Fee Received', data: body });
|
||||
|
|
@ -106,11 +110,13 @@ export const getPayments = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Getting Payments..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/audit';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/audit';
|
||||
const tillToday = (Math.round(new Date(Date.now()).getTime() / 1000)).toString();
|
||||
options.form = { from: 0, to: tillToday };
|
||||
if (req.query.count) { options.form.count = req.query.count; }
|
||||
if (req.query.skip) { options.form.skip = req.query.skip; }
|
||||
if (common.read_dummy_data) {
|
||||
common.getDummyData('Payments', req.session.selectedNode.ln_implementation).then((data) => { res.status(200).json(arrangePayments(req.session.selectedNode, data)); });
|
||||
common.getDummyData('Payments', req.session.selectedNode.lnImplementation).then((data) => { res.status(200).json(arrangePayments(req.session.selectedNode, data)); });
|
||||
} else {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Payments Received', data: body });
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@ export const getInfo = (req, res, next) => {
|
|||
common.setOptions(req);
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/getinfo';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/getinfo';
|
||||
options.form = {};
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Selected Node ' + req.session.selectedNode.ln_node });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Selected Node ' + req.session.selectedNode.lnNode });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Calling Info from Eclair server url ' + options.url });
|
||||
if (common.read_dummy_data) {
|
||||
common.getDummyData('GetInfo', req.session.selectedNode.ln_implementation).then((data: any) => {
|
||||
common.getDummyData('GetInfo', req.session.selectedNode.lnImplementation).then((data: any) => {
|
||||
data.lnImplementation = 'Eclair';
|
||||
return res.status(200).json(data);
|
||||
});
|
||||
|
|
@ -34,7 +34,7 @@ export const getInfo = (req, res, next) => {
|
|||
return request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Connecting to the Eclair\'s Websocket Server.' });
|
||||
body.lnImplementation = 'Eclair';
|
||||
req.session.selectedNode.ln_version = body.version.split('-')[0] || '';
|
||||
req.session.selectedNode.lnVersion = body.version.split('-')[0] || '';
|
||||
eclWsClient.updateSelectedNode(req.session.selectedNode);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Node Information Received', data: body });
|
||||
return res.status(200).json(body);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from 'server/models/config.model.js';
|
||||
import { SelectedNode } from 'server/models/config.model.js';
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
|
@ -37,7 +37,7 @@ export const getInvoice = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Invoice..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/getinvoice';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/getinvoice';
|
||||
options.form = { paymentHash: req.params.paymentHash };
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Invoice Found', data: body });
|
||||
|
|
@ -52,11 +52,14 @@ export const getInvoice = (req, res, next) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const listPendingInvoicesRequestCall = (selectedNode: CommonSelectedNode) => {
|
||||
export const listPendingInvoicesRequestCall = (selectedNode: SelectedNode, count?: number, skip?: number) => {
|
||||
logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'List Pending Invoices..' });
|
||||
options = selectedNode.options;
|
||||
options.url = selectedNode.ln_server_url + '/listpendinginvoices';
|
||||
options = selectedNode.authentication.options;
|
||||
options.url = selectedNode.settings.lnServerUrl + '/listpendinginvoices';
|
||||
options.form = { from: 0, to: (Math.round(new Date(Date.now()).getTime() / 1000)).toString() };
|
||||
// Limit the number of invoices till provided count
|
||||
if (count) { options.form.count = count; }
|
||||
if (skip) { options.form.skip = skip; }
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post(options).then((pendingInvoicesResponse) => {
|
||||
logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Pending Invoices List ', data: pendingInvoicesResponse });
|
||||
|
|
@ -72,28 +75,28 @@ export const listInvoices = (req, res, next) => {
|
|||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
const tillToday = (Math.round(new Date(Date.now()).getTime() / 1000)).toString();
|
||||
options.form = { from: 0, to: tillToday };
|
||||
const options1 = JSON.parse(JSON.stringify(options));
|
||||
options1.url = req.session.selectedNode.ln_server_url + '/listinvoices';
|
||||
options1.url = req.session.selectedNode.settings.lnServerUrl + '/listinvoices';
|
||||
options1.form = { from: 0, to: tillToday };
|
||||
if (req.query.count) { options1.form.count = req.query.count; }
|
||||
if (req.query.skip) { options1.form.skip = req.query.skip; }
|
||||
const options2 = JSON.parse(JSON.stringify(options));
|
||||
options2.url = req.session.selectedNode.ln_server_url + '/listpendinginvoices';
|
||||
options2.url = req.session.selectedNode.settings.lnServerUrl + '/listpendinginvoices';
|
||||
options2.form = { from: 0, to: tillToday };
|
||||
if (common.read_dummy_data) {
|
||||
return common.getDummyData('Invoices', req.session.selectedNode.ln_implementation).then((body) => {
|
||||
const invoices = (!body[0] || body[0].length <= 0) ? [] : body[0];
|
||||
pendingInvoices = (!body[1] || body[1].length <= 0) ? [] : body[1];
|
||||
return Promise.all(invoices?.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
|
||||
return common.getDummyData('Invoices', req.session.selectedNode.lnImplementation).then(([invoices, pendingInvoicesRes]: any[]) => {
|
||||
pendingInvoices = pendingInvoicesRes;
|
||||
return Promise.all(invoices?.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.settings.lnServerUrl, invoice))).
|
||||
then((values) => res.status(200).json(invoices));
|
||||
});
|
||||
} else {
|
||||
return Promise.all([request(options1), request(options2)]).
|
||||
then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Invoice', msg: 'Invoices List Received', data: body });
|
||||
const invoices = (!body[0] || body[0].length <= 0) ? [] : body[0];
|
||||
pendingInvoices = (!body[1] || body[1].length <= 0) ? [] : body[1];
|
||||
then(([invoices, pendingInvoicesRes]) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Invoice', msg: 'Invoices List Received', data: invoices });
|
||||
// pendingInvoices will be used to get the status (paid/unpaid) of the invoice via getReceivedPaymentInfo
|
||||
pendingInvoices = pendingInvoicesRes;
|
||||
if (invoices && invoices.length > 0) {
|
||||
return Promise.all(invoices?.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.ln_server_url, invoice))).
|
||||
return Promise.all(invoices?.map((invoice) => getReceivedPaymentInfo(req.session.selectedNode.settings.lnServerUrl, invoice))).
|
||||
then((values) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Sorted Invoices List Received', data: invoices });
|
||||
return res.status(200).json(invoices);
|
||||
|
|
@ -114,10 +117,10 @@ export const listInvoices = (req, res, next) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const createInvoiceRequestCall = (selectedNode: CommonSelectedNode, description: string, amount: number) => {
|
||||
export const createInvoiceRequestCall = (selectedNode: SelectedNode, description: string, amount: number) => {
|
||||
logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Creating Invoice..' });
|
||||
options = selectedNode.options;
|
||||
options.url = selectedNode.ln_server_url + '/createinvoice';
|
||||
options = selectedNode.authentication.options;
|
||||
options.url = selectedNode.settings.lnServerUrl + '/createinvoice';
|
||||
options.form = { description: description, amountMsat: amount };
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post(options).then((invResponse) => {
|
||||
|
|
@ -131,10 +134,11 @@ export const createInvoiceRequestCall = (selectedNode: CommonSelectedNode, descr
|
|||
};
|
||||
|
||||
export const createInvoice = (req, res, next) => {
|
||||
const { description, amountMsat } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Creating Invoice..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
createInvoiceRequestCall(req.session.selectedNode, req.body.description, req.body.amountMsat).then((invRes) => {
|
||||
createInvoiceRequestCall(req.session.selectedNode, description, amountMsat).then((invRes) => {
|
||||
res.status(201).json(invRes);
|
||||
}).catch((err) => res.status(err.statusCode).json({ message: err.message, error: err.error }));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from 'server/models/config.model.js';
|
||||
import { SelectedNode } from 'server/models/config.model.js';
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
|
@ -10,7 +10,7 @@ export const getNodes = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Node Lookup..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/nodes';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/nodes';
|
||||
options.form = { nodeIds: req.params.id };
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Node Lookup Finished', data: body });
|
||||
|
|
@ -21,10 +21,10 @@ export const getNodes = (req, res, next) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const findRouteBetweenNodesRequestCall = (selectedNode: CommonSelectedNode, amountMsat: number, sourceNodeId: string, targetNodeId: string, ignoreNodeIds: string[] = [], format: string = 'shortChannelId') => {
|
||||
export const findRouteBetweenNodesRequestCall = (selectedNode: SelectedNode, amountMsat: number, sourceNodeId: string, targetNodeId: string, ignoreNodeIds: string[] = [], format: string = 'shortChannelId') => {
|
||||
logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'Network', msg: 'Find Route Between Nodes..' });
|
||||
options = selectedNode.options;
|
||||
options.url = selectedNode.ln_server_url + '/findroutebetweennodes';
|
||||
options = selectedNode.authentication.options;
|
||||
options.url = selectedNode.settings.lnServerUrl + '/findroutebetweennodes';
|
||||
options.form = { amountMsat: amountMsat, sourceNodeId: sourceNodeId, targetNodeId: targetNodeId, ignoreNodeIds: ignoreNodeIds, format: format };
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -37,9 +37,10 @@ export const findRouteBetweenNodesRequestCall = (selectedNode: CommonSelectedNod
|
|||
};
|
||||
|
||||
export const findRouteBetweenNodes = (req, res, next) => {
|
||||
const { amountMsat, sourceNodeId, targetNodeId, ignoreNodeIds, format } = req.body;
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
findRouteBetweenNodesRequestCall(req.session.selectedNode, req.body.amountMsat, req.body.sourceNodeId, req.body.targetNodeId, req.body.ignoreNodeIds, req.body.format).then((callRes) => {
|
||||
findRouteBetweenNodesRequestCall(req.session.selectedNode, amountMsat, sourceNodeId, targetNodeId, ignoreNodeIds, format).then((callRes) => {
|
||||
res.status(200).json(callRes);
|
||||
}).catch((err) => res.status(err.statusCode).json({ message: err.message, error: err.error }));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const getNewAddress = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Generating New Address..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/getnewaddress';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/getnewaddress';
|
||||
options.form = {};
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'New Address Generated', data: body });
|
||||
|
|
@ -32,10 +32,10 @@ export const getBalance = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Getting On Chain Balance..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/onchainbalance';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/onchainbalance';
|
||||
options.form = {};
|
||||
if (common.read_dummy_data) {
|
||||
common.getDummyData('OnChainBalance', req.session.selectedNode.ln_implementation).then((data) => { res.status(200).json(arrangeBalances(data)); });
|
||||
common.getDummyData('OnChainBalance', req.session.selectedNode.lnImplementation).then((data) => { res.status(200).json(arrangeBalances(data)); });
|
||||
} else {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'On Chain Balance Received', data: body });
|
||||
|
|
@ -52,7 +52,7 @@ export const getTransactions = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Getting On Chain Transactions..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/onchaintransactions';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/onchaintransactions';
|
||||
options.form = {
|
||||
count: req.query.count,
|
||||
skip: req.query.skip
|
||||
|
|
@ -68,15 +68,12 @@ export const getTransactions = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const sendFunds = (req, res, next) => {
|
||||
const { address, amount, blocks } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Sending On Chain Funds..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/sendonchain';
|
||||
options.form = {
|
||||
address: req.body.address,
|
||||
amountSatoshis: req.body.amount,
|
||||
confirmationTarget: req.body.blocks
|
||||
};
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/sendonchain';
|
||||
options.form = { address: address, amountSatoshis: amount, confirmationTarget: blocks };
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Onchain', msg: 'Send Funds Options', data: options.form });
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Onchain', msg: 'On Chain Funds Sent', data: body });
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
||||
export const getSentInfoFromPaymentRequest = (selNode: CommonSelectedNode, payment) => {
|
||||
options.url = selNode.ln_server_url + '/getsentinfo';
|
||||
export const getSentInfoFromPaymentRequest = (selNode: SelectedNode, payment) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/getsentinfo';
|
||||
options.form = { paymentHash: payment };
|
||||
return request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment Sent Information Received', data: body });
|
||||
|
|
@ -19,8 +19,8 @@ export const getSentInfoFromPaymentRequest = (selNode: CommonSelectedNode, payme
|
|||
}).catch((err) => err);
|
||||
};
|
||||
|
||||
export const getQueryNodes = (selNode: CommonSelectedNode, nodeIds) => {
|
||||
options.url = selNode.ln_server_url + '/nodes';
|
||||
export const getQueryNodes = (selNode: SelectedNode, nodeIds) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/nodes';
|
||||
options.form = { nodeIds: nodeIds?.reduce((acc, curr) => acc + ',' + curr) };
|
||||
return request.post(options).then((nodes) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Payments', msg: 'Query Nodes Received', data: nodes });
|
||||
|
|
@ -32,7 +32,7 @@ export const decodePayment = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Decoding Payment..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/parseinvoice';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/parseinvoice';
|
||||
options.form = { invoice: req.params.invoice };
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Decoded', data: body });
|
||||
|
|
@ -48,7 +48,7 @@ export const postPayment = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Paying Invoice..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/payinvoice';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/payinvoice';
|
||||
options.form = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Send Payment Options', data: options.form });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -64,7 +64,7 @@ export const queryPaymentRoute = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Querying Payment Route..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/findroutetonode';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/findroutetonode';
|
||||
options.form = {
|
||||
nodeId: req.query.nodeId,
|
||||
amountMsat: req.query.amountMsat
|
||||
|
|
@ -98,11 +98,12 @@ export const queryPaymentRoute = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const getSentPaymentsInformation = (req, res, next) => {
|
||||
const { payments } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Getting Sent Payment Information..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
if (req.body.payments) {
|
||||
const paymentsArr = req.body.payments.split(',');
|
||||
if (payments) {
|
||||
const paymentsArr = payments.split(',');
|
||||
return Promise.all(paymentsArr?.map((payment) => getSentInfoFromPaymentRequest(req.session.selectedNode, payment))).
|
||||
then((values) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Sent Information Received', data: values });
|
||||
|
|
@ -118,10 +119,10 @@ export const getSentPaymentsInformation = (req, res, next) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const sendPaymentToRouteRequestCall = (selectedNode: CommonSelectedNode, shortChannelIds: string, invoice: string, amountMsat: number) => {
|
||||
export const sendPaymentToRouteRequestCall = (selectedNode: SelectedNode, shortChannelIds: string, invoice: string, amountMsat: number) => {
|
||||
logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'Invoices', msg: 'Creating Invoice..' });
|
||||
options = selectedNode.options;
|
||||
options.url = selectedNode.ln_server_url + '/sendtoroute';
|
||||
options = selectedNode.authentication.options;
|
||||
options.url = selectedNode.settings.lnServerUrl + '/sendtoroute';
|
||||
options.form = { shortChannelIds: shortChannelIds, amountMsat: amountMsat, invoice: invoice };
|
||||
return new Promise((resolve, reject) => {
|
||||
logger.log({ selectedNode: selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Send Payment To Route Options', data: options.form });
|
||||
|
|
@ -135,10 +136,11 @@ export const sendPaymentToRouteRequestCall = (selectedNode: CommonSelectedNode,
|
|||
};
|
||||
|
||||
export const sendPaymentToRoute = (req, res, next) => {
|
||||
const { shortChannelIds, invoice, amountMsat } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Send Payment To Route..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
sendPaymentToRouteRequestCall(req.session.selectedNode, req.body.shortChannelIds, req.body.invoice, req.body.amountMsat).then((callRes) => {
|
||||
sendPaymentToRouteRequestCall(req.session.selectedNode, shortChannelIds, invoice, amountMsat).then((callRes) => {
|
||||
res.status(200).json(callRes);
|
||||
}).catch((err) => res.status(err.statusCode).json({ message: err.message, error: err.error }));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
||||
export const getFilteredNodes = (selNode: CommonSelectedNode, peersNodeIds) => {
|
||||
options.url = selNode.ln_server_url + '/nodes';
|
||||
export const getFilteredNodes = (selNode: SelectedNode, peersNodeIds) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/nodes';
|
||||
options.form = { nodeIds: peersNodeIds };
|
||||
return request.post(options).then((nodes) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Peers', msg: 'Filtered Nodes Received', data: nodes });
|
||||
|
|
@ -19,10 +19,10 @@ export const getPeers = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Getting Peers..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/peers';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/peers';
|
||||
options.form = {};
|
||||
if (common.read_dummy_data) {
|
||||
common.getDummyData('Peers', req.session.selectedNode.ln_implementation).then((data) => { res.status(200).json(data); });
|
||||
common.getDummyData('Peers', req.session.selectedNode.lnImplementation).then((data) => { res.status(200).json(data); });
|
||||
} else {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers List Received', data: body });
|
||||
|
|
@ -56,7 +56,7 @@ export const connectPeer = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Conneting Peer..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/connect';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/connect';
|
||||
options.form = {};
|
||||
if (req.query) {
|
||||
options.form = req.query;
|
||||
|
|
@ -71,7 +71,7 @@ export const connectPeer = (req, res, next) => {
|
|||
const err = common.handleError({ statusCode: 500, message: 'Connect Peer Error', error: body }, 'Peers', body, req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/peers';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/peers';
|
||||
options.form = {};
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers List after Connect', data: body });
|
||||
|
|
@ -107,7 +107,7 @@ export const deletePeer = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Disconneting Peer..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/disconnect';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/disconnect';
|
||||
options.form = {};
|
||||
if (req.params.nodeId) {
|
||||
options.form = { nodeId: req.params.nodeId };
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import WebSocket from 'ws';
|
|||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { WSServer } from '../../utils/webSocketServer.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
import { ECLWSEventsEnum } from '../../models/ecl.model.js';
|
||||
|
||||
export class ECLWebSocketClient {
|
||||
|
|
@ -11,7 +11,7 @@ export class ECLWebSocketClient {
|
|||
public logger: LoggerService = Logger;
|
||||
public common: CommonService = Common;
|
||||
public wsServer = WSServer;
|
||||
public webSocketClients: Array<{ selectedNode: CommonSelectedNode, reConnect: boolean, webSocketClient: any }> = [];
|
||||
public webSocketClients: Array<{ selectedNode: SelectedNode, reConnect: boolean, webSocketClient: any }> = [];
|
||||
public reconnectTimeOut = null;
|
||||
public waitTime = 0.5;
|
||||
|
||||
|
|
@ -36,17 +36,17 @@ export class ECLWebSocketClient {
|
|||
}, this.waitTime * 1000);
|
||||
};
|
||||
|
||||
public connect = (selectedNode: CommonSelectedNode) => {
|
||||
public connect = (selectedNode: SelectedNode) => {
|
||||
try {
|
||||
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
|
||||
if (!clientExists) {
|
||||
if (selectedNode.ln_server_url) {
|
||||
if (selectedNode.settings.lnServerUrl) {
|
||||
const newWebSocketClient = { selectedNode: selectedNode, reConnect: true, webSocketClient: null };
|
||||
this.connectWithClient(newWebSocketClient);
|
||||
this.webSocketClients.push(newWebSocketClient);
|
||||
}
|
||||
} else {
|
||||
if ((!clientExists.webSocketClient || clientExists.webSocketClient.readyState !== WebSocket.OPEN) && selectedNode.ln_server_url) {
|
||||
if ((!clientExists.webSocketClient || clientExists.webSocketClient.readyState !== WebSocket.OPEN) && selectedNode.settings.lnServerUrl) {
|
||||
clientExists.reConnect = true;
|
||||
this.connectWithClient(clientExists);
|
||||
}
|
||||
|
|
@ -58,9 +58,9 @@ export class ECLWebSocketClient {
|
|||
|
||||
public connectWithClient = (eclWsClt) => {
|
||||
this.logger.log({ selectedNode: eclWsClt.selectedNode, level: 'INFO', fileName: 'ECLWebSocket', msg: 'Connecting to the Eclair\'s Websocket Server..' });
|
||||
const UpdatedLNServerURL = (eclWsClt.selectedNode.ln_server_url)?.replace(/^http/, 'ws');
|
||||
const UpdatedLNServerURL = (eclWsClt.selectedNode.settings.lnServerUrl)?.replace(/^http/, 'ws');
|
||||
const firstSubStrIndex = (UpdatedLNServerURL.indexOf('//') + 2);
|
||||
const WS_LINK = UpdatedLNServerURL.slice(0, firstSubStrIndex) + ':' + eclWsClt.selectedNode.ln_api_password + '@' + UpdatedLNServerURL.slice(firstSubStrIndex) + '/ws';
|
||||
const WS_LINK = UpdatedLNServerURL.slice(0, firstSubStrIndex) + ':' + eclWsClt.selectedNode.authentication.lnApiPassword + '@' + UpdatedLNServerURL.slice(firstSubStrIndex) + '/ws';
|
||||
eclWsClt.webSocketClient = new WebSocket(WS_LINK);
|
||||
eclWsClt.webSocketClient.onopen = () => {
|
||||
this.logger.log({ selectedNode: eclWsClt.selectedNode, level: 'INFO', fileName: 'ECLWebSocket', msg: 'Connected to the Eclair\'s Websocket Server..' });
|
||||
|
|
@ -69,7 +69,7 @@ export class ECLWebSocketClient {
|
|||
};
|
||||
|
||||
eclWsClt.webSocketClient.onclose = (e) => {
|
||||
if (eclWsClt && eclWsClt.selectedNode && eclWsClt.selectedNode.ln_implementation === 'ECL') {
|
||||
if (eclWsClt && eclWsClt.selectedNode && eclWsClt.selectedNode.lnImplementation === 'ECL') {
|
||||
this.logger.log({ selectedNode: eclWsClt.selectedNode, level: 'INFO', fileName: 'ECLWebSocket', msg: 'Web socket disconnected, will reconnect again...' });
|
||||
eclWsClt.webSocketClient.close();
|
||||
if (eclWsClt.reConnect) { this.reconnet(eclWsClt); }
|
||||
|
|
@ -87,7 +87,7 @@ export class ECLWebSocketClient {
|
|||
};
|
||||
|
||||
eclWsClt.webSocketClient.onerror = (err) => {
|
||||
if (eclWsClt.selectedNode.ln_version === '' || !eclWsClt.selectedNode.ln_version || this.common.isVersionCompatible(eclWsClt.selectedNode.ln, '0.5.0')) {
|
||||
if (eclWsClt.selectedNode.lnVersion === '' || !eclWsClt.selectedNode.lnVersion || this.common.isVersionCompatible(eclWsClt.selectedNode.ln, '0.5.0')) {
|
||||
this.logger.log({ selectedNode: eclWsClt.selectedNode, level: 'ERROR', fileName: 'ECLWebSocket', msg: 'Web socket error', error: err });
|
||||
const errStr = ((typeof err === 'object' && err.message) ? JSON.stringify({ error: err.message }) : (typeof err === 'object') ? JSON.stringify({ error: err }) : ('{ "error": ' + err + ' }'));
|
||||
this.wsServer.sendErrorToAllLNClients(errStr, eclWsClt.selectedNode);
|
||||
|
|
@ -99,7 +99,7 @@ export class ECLWebSocketClient {
|
|||
};
|
||||
};
|
||||
|
||||
public disconnect = (selectedNode: CommonSelectedNode) => {
|
||||
public disconnect = (selectedNode: SelectedNode) => {
|
||||
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
|
||||
if (clientExists && clientExists.webSocketClient && clientExists.webSocketClient.readyState === WebSocket.OPEN) {
|
||||
this.logger.log({ selectedNode: clientExists.selectedNode, level: 'INFO', fileName: 'ECLWebSocket', msg: 'Disconnecting from the Eclair\'s Websocket Server..' });
|
||||
|
|
@ -110,7 +110,7 @@ export class ECLWebSocketClient {
|
|||
}
|
||||
};
|
||||
|
||||
public updateSelectedNode = (newSelectedNode: CommonSelectedNode) => {
|
||||
public updateSelectedNode = (newSelectedNode: SelectedNode) => {
|
||||
const clientIdx = this.webSocketClients.findIndex((wsc) => +wsc.selectedNode.index === +newSelectedNode.index);
|
||||
let newClient = this.webSocketClients[clientIdx];
|
||||
if (!newClient) { newClient = { selectedNode: null, reConnect: true, webSocketClient: null }; }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const getBlockchainBalance = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Balance', msg: 'Getting Balance..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/balance/blockchain';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/balance/blockchain';
|
||||
options.qs = req.query;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Balance', msg: 'Request params', data: req.params });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Balance', msg: 'Request Query', data: req.query });
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
||||
export const getAliasForChannel = (selNode: CommonSelectedNode, channel) => {
|
||||
export const getAliasForChannel = (selNode: SelectedNode, channel) => {
|
||||
const pubkey = (channel.remote_pubkey) ? channel.remote_pubkey : (channel.remote_node_pub) ? channel.remote_node_pub : '';
|
||||
options.url = selNode.ln_server_url + '/v1/graph/node/' + pubkey;
|
||||
options.url = selNode.settings.lnServerUrl + '/v1/graph/node/' + pubkey;
|
||||
return request(options).then((aliasBody) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Channels', msg: 'Alias Received', data: aliasBody.node.alias });
|
||||
channel.remote_alias = aliasBody.node.alias && aliasBody.node.alias !== '' ? aliasBody.node.alias : aliasBody.node.pub_key.slice(0, 20);
|
||||
|
|
@ -23,7 +23,7 @@ export const getAllChannels = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Channels..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels';
|
||||
options.qs = req.query;
|
||||
let local = 0;
|
||||
let remote = 0;
|
||||
|
|
@ -61,7 +61,7 @@ export const getPendingChannels = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Pending Channels..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/pending';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels/pending';
|
||||
options.qs = req.query;
|
||||
request(options).then((body) => {
|
||||
if (!body.total_limbo_balance) {
|
||||
|
|
@ -98,7 +98,7 @@ export const getClosedChannels = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Closed Channels..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/closed';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels/closed';
|
||||
options.qs = req.query;
|
||||
request(options).then((body) => {
|
||||
if (body.channels && body.channels.length > 0) {
|
||||
|
|
@ -125,23 +125,24 @@ export const getClosedChannels = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const postChannel = (req, res, next) => {
|
||||
const { node_pubkey, private: privateChannel, spend_unconfirmed, local_funding_amount, trans_type, trans_type_value, commitment_type } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Opening Channel..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels';
|
||||
options.form = {
|
||||
node_pubkey_string: req.body.node_pubkey,
|
||||
local_funding_amount: req.body.local_funding_amount,
|
||||
private: req.body.private,
|
||||
spend_unconfirmed: req.body.spend_unconfirmed
|
||||
node_pubkey_string: node_pubkey,
|
||||
local_funding_amount: local_funding_amount,
|
||||
private: privateChannel,
|
||||
spend_unconfirmed: spend_unconfirmed
|
||||
};
|
||||
if (req.body.trans_type === '1') {
|
||||
options.form.target_conf = req.body.trans_type_value;
|
||||
} else if (req.body.trans_type === '2') {
|
||||
options.form.sat_per_byte = req.body.trans_type_value;
|
||||
if (trans_type === '1') {
|
||||
options.form.target_conf = trans_type_value;
|
||||
} else if (trans_type === '2') {
|
||||
options.form.sat_per_byte = trans_type_value;
|
||||
}
|
||||
if (req.body.commitment_type) {
|
||||
options.form.commitment_type = req.body.commitment_type;
|
||||
if (commitment_type) {
|
||||
options.form.commitment_type = commitment_type;
|
||||
}
|
||||
options.form = JSON.stringify(options.form);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Channel Open Options', data: options.form });
|
||||
|
|
@ -155,18 +156,19 @@ export const postChannel = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const postTransactions = (req, res, next) => {
|
||||
const { paymentReq, paymentAmount, feeLimit, outgoingChannel, allowSelfPayment, lastHopPubkey } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Sending Payment..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/transaction-stream';
|
||||
options.form = { payment_request: req.body.paymentReq };
|
||||
if (req.body.paymentAmount) {
|
||||
options.form.amt = req.body.paymentAmount;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels/transaction-stream';
|
||||
options.form = { payment_request: paymentReq };
|
||||
if (paymentAmount) {
|
||||
options.form.amt = paymentAmount;
|
||||
}
|
||||
if (req.body.feeLimit) { options.form.fee_limit = req.body.feeLimit; }
|
||||
if (req.body.outgoingChannel) { options.form.outgoing_chan_id = req.body.outgoingChannel; }
|
||||
if (req.body.allowSelfPayment) { options.form.allow_self_payment = req.body.allowSelfPayment; }
|
||||
if (req.body.lastHopPubkey) { options.form.last_hop_pubkey = Buffer.from(req.body.lastHopPubkey, 'hex').toString('base64'); }
|
||||
if (feeLimit) { options.form.fee_limit = feeLimit; }
|
||||
if (outgoingChannel) { options.form.outgoing_chan_id = outgoingChannel; }
|
||||
if (allowSelfPayment) { options.form.allow_self_payment = allowSelfPayment; }
|
||||
if (lastHopPubkey) { options.form.last_hop_pubkey = Buffer.from(lastHopPubkey, 'hex').toString('base64'); }
|
||||
options.form = JSON.stringify(options.form);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Send Payment Options', data: options.form });
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -194,7 +196,7 @@ export const closeChannel = (req, res, next) => {
|
|||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
const channelpoint = req.params.channelPoint?.replace(':', '/');
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/' + channelpoint + '?force=' + req.query.force;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels/' + channelpoint + '?force=' + req.query.force;
|
||||
if (req.query.target_conf) { options.url = options.url + '&target_conf=' + req.query.target_conf; }
|
||||
if (req.query.sat_per_byte) { options.url = options.url + '&sat_per_byte=' + req.query.sat_per_byte; }
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Closing Channel Options URL', data: options.url });
|
||||
|
|
@ -208,32 +210,33 @@ export const closeChannel = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const postChanPolicy = (req, res, next) => {
|
||||
const { chanPoint, baseFeeMsat, feeRate, timeLockDelta, max_htlc_msat, min_htlc_msat } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Updating Channel Policy..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/chanpolicy';
|
||||
if (req.body.chanPoint === 'all') {
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/chanpolicy';
|
||||
if (chanPoint === 'all') {
|
||||
options.form = JSON.stringify({
|
||||
global: true,
|
||||
base_fee_msat: req.body.baseFeeMsat,
|
||||
fee_rate: parseFloat((req.body.feeRate / 1000000).toString()),
|
||||
time_lock_delta: parseInt(req.body.timeLockDelta)
|
||||
base_fee_msat: baseFeeMsat,
|
||||
fee_rate: parseFloat((feeRate / 1000000).toString()),
|
||||
time_lock_delta: parseInt(timeLockDelta)
|
||||
});
|
||||
} else {
|
||||
const breakPoint = req.body.chanPoint.indexOf(':');
|
||||
const txid_str = req.body.chanPoint.substring(0, breakPoint);
|
||||
const output_idx = req.body.chanPoint.substring(breakPoint + 1, req.body.chanPoint.length);
|
||||
const breakPoint = chanPoint.indexOf(':');
|
||||
const txid_str = chanPoint.substring(0, breakPoint);
|
||||
const output_idx = chanPoint.substring(breakPoint + 1, chanPoint.length);
|
||||
const optionsBody = {
|
||||
base_fee_msat: req.body.baseFeeMsat,
|
||||
fee_rate: parseFloat((req.body.feeRate / 1000000).toString()),
|
||||
time_lock_delta: parseInt(req.body.timeLockDelta),
|
||||
base_fee_msat: baseFeeMsat,
|
||||
fee_rate: parseFloat((feeRate / 1000000).toString()),
|
||||
time_lock_delta: parseInt(timeLockDelta),
|
||||
chan_point: { funding_txid_str: txid_str, output_index: parseInt(output_idx) }
|
||||
};
|
||||
if (req.body.max_htlc_msat) {
|
||||
optionsBody['max_htlc_msat'] = req.body.max_htlc_msat;
|
||||
if (max_htlc_msat) {
|
||||
optionsBody['max_htlc_msat'] = max_htlc_msat;
|
||||
}
|
||||
if (req.body.min_htlc_msat) {
|
||||
optionsBody['min_htlc_msat'] = req.body.min_htlc_msat;
|
||||
if (min_htlc_msat) {
|
||||
optionsBody['min_htlc_msat'] = min_htlc_msat;
|
||||
optionsBody['min_htlc_msat_specified'] = true;
|
||||
}
|
||||
options.form = JSON.stringify(optionsBody);
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@ export const getBackup = (req, res, next) => {
|
|||
let channel_backup_file = '';
|
||||
let message = '';
|
||||
if (req.params.channelPoint === 'ALL') {
|
||||
channel_backup_file = req.session.selectedNode.channel_backup_path + sep + 'channel-all.bak';
|
||||
channel_backup_file = req.session.selectedNode.settings.channelBackupPath + sep + 'channel-all.bak';
|
||||
message = 'All Channels Backup Successful.';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/backup';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels/backup';
|
||||
} else {
|
||||
channel_backup_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
|
||||
channel_backup_file = req.session.selectedNode.settings.channelBackupPath + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
|
||||
message = 'Channel Backup Successful.';
|
||||
const channelpoint = req.params.channelPoint?.replace(':', '/');
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/backup/' + channelpoint;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels/backup/' + channelpoint;
|
||||
const exists = fs.existsSync(channel_backup_file);
|
||||
if (exists) {
|
||||
fs.writeFile(channel_backup_file, '', () => { });
|
||||
|
|
@ -81,13 +81,13 @@ export const postBackupVerify = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'ChannelBackup', msg: 'Verifying Channel Backup..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/backup/verify';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels/backup/verify';
|
||||
let channel_verify_file = '';
|
||||
let message = '';
|
||||
let verify_backup = '';
|
||||
if (req.params.channelPoint === 'ALL') {
|
||||
message = 'All Channels Verify Successful.';
|
||||
channel_verify_file = req.session.selectedNode.channel_backup_path + sep + 'channel-all.bak';
|
||||
channel_verify_file = req.session.selectedNode.settings.channelBackupPath + sep + 'channel-all.bak';
|
||||
const exists = fs.existsSync(channel_verify_file);
|
||||
if (exists) {
|
||||
verify_backup = fs.readFileSync(channel_verify_file, 'utf-8');
|
||||
|
|
@ -108,7 +108,7 @@ export const postBackupVerify = (req, res, next) => {
|
|||
}
|
||||
} else {
|
||||
message = 'Channel Verify Successful.';
|
||||
channel_verify_file = req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
|
||||
channel_verify_file = req.session.selectedNode.settings.channelBackupPath + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
|
||||
const exists = fs.existsSync(channel_verify_file);
|
||||
if (exists) {
|
||||
verify_backup = fs.readFileSync(channel_verify_file, 'utf-8');
|
||||
|
|
@ -136,13 +136,13 @@ export const postRestore = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'ChannelBackup', msg: 'Restoring Channel Backup..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channels/backup/restore';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/channels/backup/restore';
|
||||
let channel_restore_file = '';
|
||||
let message = '';
|
||||
let restore_backup = '';
|
||||
if (req.params.channelPoint === 'ALL') {
|
||||
message = 'All Channels Restore Successful.';
|
||||
channel_restore_file = req.session.selectedNode.channel_backup_path + sep + 'restore' + sep;
|
||||
channel_restore_file = req.session.selectedNode.settings.channelBackupPath + sep + 'restore' + sep;
|
||||
const exists = fs.existsSync(channel_restore_file + 'channel-all.bak');
|
||||
const downloaded_exists = fs.existsSync(channel_restore_file + 'backup-channel-all.bak');
|
||||
if (exists) {
|
||||
|
|
@ -173,7 +173,7 @@ export const postRestore = (req, res, next) => {
|
|||
}
|
||||
} else {
|
||||
message = 'Channel Restore Successful.';
|
||||
channel_restore_file = req.session.selectedNode.channel_backup_path + sep + 'restore' + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
|
||||
channel_restore_file = req.session.selectedNode.settings.channelBackupPath + sep + 'restore' + sep + 'channel-' + req.params.channelPoint?.replace(':', '-') + '.bak';
|
||||
const exists = fs.existsSync(channel_restore_file);
|
||||
if (exists) {
|
||||
restore_backup = fs.readFileSync(channel_restore_file, 'utf-8');
|
||||
|
|
@ -190,7 +190,7 @@ export const postRestore = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'ChannelBackup', msg: 'Channel Restored', data: body });
|
||||
if (req.params.channelPoint === 'ALL') { channel_restore_file = channel_restore_file + 'channel-all.bak'; }
|
||||
fs.rename(channel_restore_file, channel_restore_file + '.restored', () => {
|
||||
getFilesList(req.session.selectedNode.channel_backup_path, (getFilesListRes) => {
|
||||
getFilesList(req.session.selectedNode.settings.channelBackupPath, (getFilesListRes) => {
|
||||
if (getFilesListRes.error) {
|
||||
const errMsg = getFilesListRes.error;
|
||||
const err = common.handleError({ statusCode: 500, message: 'Restore Channel Error', error: errMsg }, 'ChannelBackup', errMsg, req.session.selectedNode);
|
||||
|
|
@ -210,7 +210,7 @@ export const postRestore = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const getRestoreList = (req, res, next) => {
|
||||
getFilesList(req.session.selectedNode.channel_backup_path, (getFilesListRes) => {
|
||||
getFilesList(req.session.selectedNode.settings.channelBackupPath, (getFilesListRes) => {
|
||||
if (getFilesListRes.error) {
|
||||
return res.status(getFilesListRes.statusCode).json(getFilesListRes);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const getFees = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Getting Fees..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/fees';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/fees';
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Fee Received', data: body });
|
||||
const today = new Date(Date.now());
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ export const getInfo = (req, res, next) => {
|
|||
common.setOptions(req);
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/getinfo';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Selected Node ' + req.session.selectedNode.ln_node });
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/getinfo';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Selected Node ' + req.session.selectedNode.lnNode });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Calling Info from LND server url ' + options.url });
|
||||
if (!options.headers || !options.headers['Grpc-Metadata-macaroon']) {
|
||||
const errMsg = 'LND Get info failed due to bad or missing macaroon! Please check RTL-Config.json to verify the setup!';
|
||||
|
|
@ -25,7 +25,7 @@ export const getInfo = (req, res, next) => {
|
|||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
} else {
|
||||
common.nodes?.map((node: any) => {
|
||||
if (node.ln_implementation === 'LND') {
|
||||
if (node.lnImplementation === 'LND') {
|
||||
common.getAllNodeAllChannelBackup(node);
|
||||
}
|
||||
return node;
|
||||
|
|
@ -38,7 +38,7 @@ export const getInfo = (req, res, next) => {
|
|||
const err = common.handleError(body, 'GetInfo', 'Get Info Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
} else {
|
||||
req.session.selectedNode.ln_version = body.version.split('-')[0] || '';
|
||||
req.session.selectedNode.lnVersion = body.version.split('-')[0] || '';
|
||||
lndWsClient.updateSelectedNode(req.session.selectedNode);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Node Information Received', data: body });
|
||||
return res.status(200).json(body);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
||||
export const getAliasFromPubkey = (selNode: CommonSelectedNode, pubkey) => {
|
||||
options.url = selNode.ln_server_url + '/v1/graph/node/' + pubkey;
|
||||
export const getAliasFromPubkey = (selNode: SelectedNode, pubkey) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/v1/graph/node/' + pubkey;
|
||||
return request(options).then((res) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Graph', msg: 'Alias Received', data: res.node.alias });
|
||||
return res.node.alias;
|
||||
|
|
@ -19,7 +19,7 @@ export const getDescribeGraph = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Getting Network Graph..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/graph';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/graph';
|
||||
request.get(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Network Graph Received', data: body });
|
||||
res.status(200).json(body);
|
||||
|
|
@ -33,7 +33,7 @@ export const getGraphInfo = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Getting Graph Information..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/graph/info';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/graph/info';
|
||||
request.get(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Graph Information Received', data: body });
|
||||
res.status(200).json(body);
|
||||
|
|
@ -47,7 +47,7 @@ export const getGraphNode = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Getting Graph Node Information..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/graph/node/' + req.params.pubKey;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/graph/node/' + req.params.pubKey;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Graph Node Information Received', data: body });
|
||||
res.status(200).json(body);
|
||||
|
|
@ -61,7 +61,7 @@ export const getGraphEdge = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Getting Graph Edge Information..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/graph/edge/' + req.params.chanid;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/graph/edge/' + req.params.chanid;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Graph Edge Information Received', data: body });
|
||||
res.status(200).json(body);
|
||||
|
|
@ -75,7 +75,7 @@ export const getQueryRoutes = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Getting Graph Routes..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/graph/routes/' + req.params.destPubkey + '/' + req.params.amount;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/graph/routes/' + req.params.destPubkey + '/' + req.params.amount;
|
||||
if (req.query.outgoing_chan_id) {
|
||||
options.url = options.url + '?outgoing_chan_id=' + req.query.outgoing_chan_id;
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ export const getRemoteFeePolicy = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Graph', msg: 'Getting Remote Fee Policy..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/graph/edge/' + req.params.chanid;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/graph/edge/' + req.params.chanid;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Graph', msg: 'Edge Info Received', data: body });
|
||||
let remoteNodeFee = {};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const invoiceLookup = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Getting Invoice Information..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v2/invoices/lookup';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v2/invoices/lookup';
|
||||
if (req.query.payment_addr) {
|
||||
options.url = options.url + '?payment_addr=' + req.query.payment_addr;
|
||||
} else {
|
||||
|
|
@ -34,7 +34,7 @@ export const listInvoices = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Getting List Invoices..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/invoices?num_max_invoices=' + req.query.num_max_invoices + '&index_offset=' + req.query.index_offset +
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/invoices?num_max_invoices=' + req.query.num_max_invoices + '&index_offset=' + req.query.index_offset +
|
||||
'&reversed=' + req.query.reversed;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Invoice', msg: 'Invoices List Received', data: body });
|
||||
|
|
@ -57,7 +57,7 @@ export const addInvoice = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Adding Invoice..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/invoices';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/invoices';
|
||||
options.form = JSON.stringify(req.body);
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Invoice Added', data: body });
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ const logger: LoggerService = Logger;
|
|||
const common: CommonService = Common;
|
||||
|
||||
export const signMessage = (req, res, next) => {
|
||||
const { message } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Signing Message..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/signmessage';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/signmessage';
|
||||
options.form = JSON.stringify({
|
||||
msg: Buffer.from(req.body.message).toString('base64')
|
||||
msg: Buffer.from(message).toString('base64')
|
||||
});
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Signed', data: body });
|
||||
|
|
@ -23,13 +24,14 @@ export const signMessage = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const verifyMessage = (req, res, next) => {
|
||||
const { message, signature } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Verifying Message..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/verifymessage';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/verifymessage';
|
||||
options.form = JSON.stringify({
|
||||
msg: Buffer.from(req.body.message).toString('base64'),
|
||||
signature: req.body.signature
|
||||
msg: Buffer.from(message).toString('base64'),
|
||||
signature: signature
|
||||
});
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body });
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const getNewAddress = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'NewAddress', msg: 'Getting New Address..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/newaddress?type=' + req.query.type;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/newaddress?type=' + req.query.type;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'NewAddress', msg: 'New Address Generated', data: body });
|
||||
res.status(200).json(body);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
||||
export const decodePaymentFromPaymentRequest = (selNode: CommonSelectedNode, payment) => {
|
||||
options.url = selNode.ln_server_url + '/v1/payreq/' + payment;
|
||||
export const decodePaymentFromPaymentRequest = (selNode: SelectedNode, payment) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/v1/payreq/' + payment;
|
||||
return request(options).then((res) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'PayReq', msg: 'Description Received', data: res.description });
|
||||
return res;
|
||||
|
|
@ -19,7 +19,7 @@ export const decodePayment = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'PayRequest', msg: 'Decoding Payment..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/payreq/' + req.params.payRequest;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/payreq/' + req.params.payRequest;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'PayRequest', msg: 'Payment Decoded', data: body });
|
||||
res.status(200).json(body);
|
||||
|
|
@ -30,11 +30,12 @@ export const decodePayment = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const decodePayments = (req, res, next) => {
|
||||
const { payments } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'PayRequest', msg: 'Decoding Payments List..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
if (req.body.payments) {
|
||||
const paymentsArr = req.body.payments.split(',');
|
||||
if (payments) {
|
||||
const paymentsArr = payments.split(',');
|
||||
return Promise.all(paymentsArr?.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
|
||||
then((values) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'PayRequest', msg: 'Payment List Decoded', data: values });
|
||||
|
|
@ -54,7 +55,7 @@ export const getPayments = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Getting Payments List..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/payments?max_payments=' + req.query.max_payments + '&index_offset=' + req.query.index_offset + '&reversed=' + req.query.reversed;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/payments?max_payments=' + req.query.max_payments + '&index_offset=' + req.query.index_offset + '&reversed=' + req.query.reversed;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment List Received', data: body });
|
||||
res.status(200).json(body);
|
||||
|
|
@ -68,8 +69,8 @@ export const getAllLightningTransactions = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Getting All Lightning Transactions..' });
|
||||
const options1 = JSON.parse(JSON.stringify(common.getOptions(req)));
|
||||
const options2 = JSON.parse(JSON.stringify(common.getOptions(req)));
|
||||
// options1.url = req.session.selectedNode.ln_server_url + '/v1/payments?max_payments=100000&index_offset=0&reversed=true';
|
||||
options2.url = req.session.selectedNode.ln_server_url + '/v1/invoices?num_max_invoices=100000&index_offset=0&reversed=true';
|
||||
// options1.url = req.session.selectedNode.settings.lnServerUrl + '/v1/payments?max_payments=100000&index_offset=0&reversed=true';
|
||||
options2.url = req.session.selectedNode.settings.lnServerUrl + '/v1/invoices?num_max_invoices=100000&index_offset=0&reversed=true';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'All Payments Options', data: options1 });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'All Invoices Options', data: options2 });
|
||||
// return Promise.all([request(options1), request(options2)]).then((values) => {
|
||||
|
|
@ -86,7 +87,7 @@ export const paymentLookup = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Looking up Payment..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v2/router/track/' + req.params.paymentHash;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v2/router/track/' + req.params.paymentHash;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Information Received for ' + req.params.paymentHash, data: body });
|
||||
res.status(200).json(body.result || body);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
let options = null;
|
||||
const logger: LoggerService = Logger;
|
||||
const common: CommonService = Common;
|
||||
|
||||
export const getAliasForPeers = (selNode: CommonSelectedNode, peer) => {
|
||||
options.url = selNode.ln_server_url + '/v1/graph/node/' + peer.pub_key;
|
||||
export const getAliasForPeers = (selNode: SelectedNode, peer) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/v1/graph/node/' + peer.pub_key;
|
||||
return request(options).then((aliasBody) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Peers', msg: 'Alias Received', data: aliasBody.node.alias });
|
||||
peer.alias = aliasBody.node.alias;
|
||||
|
|
@ -22,7 +22,7 @@ export const getPeers = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Getting Peers..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/peers';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/peers';
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers List Received', data: body });
|
||||
const peers = !body.peers ? [] : body.peers;
|
||||
|
|
@ -37,22 +37,23 @@ export const getPeers = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const postPeer = (req, res, next) => {
|
||||
const { host, pubkey, perm } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Connecting Peer..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/peers';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/peers';
|
||||
options.form = JSON.stringify({
|
||||
addr: { host: req.body.host, pubkey: req.body.pubkey },
|
||||
perm: req.body.perm
|
||||
addr: { host: host, pubkey: pubkey },
|
||||
perm: perm
|
||||
});
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peer Connected', data: body });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/peers';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/peers';
|
||||
request(options).then((body) => {
|
||||
const peers = (!body.peers) ? [] : body.peers;
|
||||
return Promise.all(peers?.map((peer) => getAliasForPeers(req.session.selectedNode, peer))).then((values) => {
|
||||
if (body.peers) {
|
||||
body.peers = common.newestOnTop(body.peers, 'pub_key', req.body.pubkey);
|
||||
body.peers = common.newestOnTop(body.peers, 'pub_key', pubkey);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peers List after Connect Received', data: body });
|
||||
}
|
||||
res.status(201).json(body.peers);
|
||||
|
|
@ -74,7 +75,7 @@ export const deletePeer = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Disconnecting Peer..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/peers/' + req.params.peerPubKey;
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/peers/' + req.params.peerPubKey;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peer Disconnect Pubkey', data: req.params.peerPubKey });
|
||||
request.delete(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peer Disconneted', data: body });
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ const responseData = { switch: { forwarding_events: [], last_offset_index: 0 },
|
|||
const num_max_events = 100;
|
||||
|
||||
export const forwardingHistory = (req, res, next) => {
|
||||
getAllForwardingEvents(req, req.body.start_time, req.body.end_time, 0, 'switch', (eventsResponse) => {
|
||||
const { start_time, end_time } = req.body;
|
||||
getAllForwardingEvents(req, start_time, end_time, 0, 'switch', (eventsResponse) => {
|
||||
if (eventsResponse.error) {
|
||||
res.status(eventsResponse.error.statusCode).json(eventsResponse);
|
||||
} else {
|
||||
|
|
@ -24,7 +25,7 @@ export const getAllForwardingEvents = (req, start, end, offset, caller, callback
|
|||
const err = common.handleError({ message: 'Session Expired after a day\'s inactivity.', statusCode: 401 }, 'Balance', 'Get Balance Error', req.session.selectedNode);
|
||||
return callback({ message: err.message, error: err.error, statusCode: err.statusCode });
|
||||
} options = common.getOptions(req);
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/switch';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/switch';
|
||||
options.form = {};
|
||||
if (start) { options.form.start_time = start; }
|
||||
if (end) { options.form.end_time = end; }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const getTransactions = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Transactions', msg: 'Getting Transactions..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/transactions';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/transactions';
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Transactions', msg: 'Transactions List Received', data: body });
|
||||
res.status(200).json(body.transactions);
|
||||
|
|
@ -20,19 +20,18 @@ export const getTransactions = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const postTransactions = (req, res, next) => {
|
||||
const { amount, address, fees, blocks, sendAll } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Transactions', msg: 'Sending Transaction..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/transactions';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/transactions';
|
||||
options.form = {
|
||||
amount: req.body.amount,
|
||||
addr: req.body.address,
|
||||
sat_per_byte: req.body.fees,
|
||||
target_conf: req.body.blocks
|
||||
amount: amount,
|
||||
addr: address,
|
||||
sat_per_byte: fees,
|
||||
target_conf: blocks
|
||||
};
|
||||
if (req.body.sendAll) {
|
||||
options.form.send_all = req.body.sendAll;
|
||||
}
|
||||
if (sendAll) { options.form.send_all = sendAll; }
|
||||
options.form = JSON.stringify(options.form);
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Transactions', msg: 'Transaction Sent', data: body });
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ export const genSeed = (req, res, next) => {
|
|||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
if (req.params.passphrase) {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/genseed?aezeed_passphrase=' + Buffer.from(atob(req.params.passphrase)).toString('base64');
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/genseed?aezeed_passphrase=' + Buffer.from(atob(req.params.passphrase)).toString('base64');
|
||||
} else {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/genseed';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/genseed';
|
||||
}
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Seed Generated', data: body });
|
||||
|
|
@ -25,30 +25,31 @@ export const genSeed = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const operateWallet = (req, res, next) => {
|
||||
const { wallet_password, aezeed_passphrase, cipher_seed_mnemonic } = req.body;
|
||||
let err_message = '';
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.method = 'POST';
|
||||
if (!req.params.operation || req.params.operation === 'unlockwallet') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Unlocking Wallet..' });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/unlockwallet';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/unlockwallet';
|
||||
options.form = JSON.stringify({
|
||||
wallet_password: Buffer.from(atob(req.body.wallet_password)).toString('base64')
|
||||
wallet_password: Buffer.from(atob(wallet_password)).toString('base64')
|
||||
});
|
||||
err_message = 'Unlocking wallet failed! Verify that lnd is running and the wallet is locked!';
|
||||
} else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Initializing Wallet..' });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/initwallet';
|
||||
if (req.body.aezeed_passphrase && req.body.aezeed_passphrase !== '') {
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/initwallet';
|
||||
if (aezeed_passphrase && aezeed_passphrase !== '') {
|
||||
options.form = JSON.stringify({
|
||||
wallet_password: Buffer.from(atob(req.body.wallet_password)).toString('base64'),
|
||||
cipher_seed_mnemonic: req.body.cipher_seed_mnemonic,
|
||||
aezeed_passphrase: Buffer.from(atob(req.body.aezeed_passphrase)).toString('base64')
|
||||
wallet_password: Buffer.from(atob(wallet_password)).toString('base64'),
|
||||
cipher_seed_mnemonic: cipher_seed_mnemonic,
|
||||
aezeed_passphrase: Buffer.from(atob(aezeed_passphrase)).toString('base64')
|
||||
});
|
||||
} else {
|
||||
options.form = JSON.stringify({
|
||||
wallet_password: Buffer.from(atob(req.body.wallet_password)).toString('base64'),
|
||||
cipher_seed_mnemonic: req.body.cipher_seed_mnemonic
|
||||
wallet_password: Buffer.from(atob(wallet_password)).toString('base64'),
|
||||
cipher_seed_mnemonic: cipher_seed_mnemonic
|
||||
});
|
||||
}
|
||||
err_message = 'Initializing wallet failed!';
|
||||
|
|
@ -93,8 +94,8 @@ export const getUTXOs = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Getting UTXOs..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v2/wallet/utxos';
|
||||
if (common.isVersionCompatible(req.session.selectedNode.ln_version, '0.14.0')) {
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v2/wallet/utxos';
|
||||
if (common.isVersionCompatible(req.session.selectedNode.lnVersion, '0.14.0')) {
|
||||
options.form = JSON.stringify({ max_confs: req.query.max_confs });
|
||||
} else {
|
||||
options.url = options.url + '?max_confs=' + req.query.max_confs;
|
||||
|
|
@ -109,19 +110,20 @@ export const getUTXOs = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const bumpFee = (req, res, next) => {
|
||||
const { txid, outputIndex, targetConf, satPerByte } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Bumping Fee..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v2/wallet/bumpfee';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v2/wallet/bumpfee';
|
||||
options.form = {};
|
||||
options.form.outpoint = {
|
||||
txid_str: req.body.txid,
|
||||
output_index: req.body.outputIndex
|
||||
txid_str: txid,
|
||||
output_index: outputIndex
|
||||
};
|
||||
if (req.body.targetConf) {
|
||||
options.form.target_conf = req.body.targetConf;
|
||||
} else if (req.body.satPerByte) {
|
||||
options.form.sat_per_byte = req.body.satPerByte;
|
||||
if (targetConf) {
|
||||
options.form.target_conf = targetConf;
|
||||
} else if (satPerByte) {
|
||||
options.form.sat_per_byte = satPerByte;
|
||||
}
|
||||
options.form = JSON.stringify(options.form);
|
||||
request.post(options).then((body) => {
|
||||
|
|
@ -137,12 +139,8 @@ export const labelTransaction = (req, res, next) => {
|
|||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Labelling Transaction..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v2/wallet/tx/label';
|
||||
options.form = {};
|
||||
options.form.txid = req.body.txid;
|
||||
options.form.label = req.body.label;
|
||||
options.form.overwrite = req.body.overwrite;
|
||||
options.form = JSON.stringify(options.form);
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v2/wallet/tx/label';
|
||||
options.form = JSON.stringify(req.body);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Wallet', msg: 'Label Transaction Options', data: options.form });
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Transaction Labelled', data: body });
|
||||
|
|
@ -154,15 +152,16 @@ export const labelTransaction = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const leaseUTXO = (req, res, next) => {
|
||||
const { txid, outputIndex } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Leasing UTXO..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v2/wallet/utxos/lease';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v2/wallet/utxos/lease';
|
||||
options.form = {};
|
||||
options.form.id = req.body.txid;
|
||||
options.form.id = txid;
|
||||
options.form.outpoint = {
|
||||
txid_bytes: req.body.txid,
|
||||
output_index: req.body.outputIndex
|
||||
txid_bytes: txid,
|
||||
output_index: outputIndex
|
||||
};
|
||||
options.form = JSON.stringify(options.form);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Wallet', msg: 'UTXO Lease Options', data: options.form });
|
||||
|
|
@ -176,15 +175,16 @@ export const leaseUTXO = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const releaseUTXO = (req, res, next) => {
|
||||
const { txid, outputIndex } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Wallet', msg: 'Releasing UTXO..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v2/wallet/utxos/release';
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v2/wallet/utxos/release';
|
||||
options.form = {};
|
||||
options.form.id = req.body.txid;
|
||||
options.form.id = txid;
|
||||
options.form.outpoint = {
|
||||
txid_bytes: req.body.txid,
|
||||
output_index: req.body.outputIndex
|
||||
txid_bytes: txid,
|
||||
output_index: outputIndex
|
||||
};
|
||||
options.form = JSON.stringify(options.form);
|
||||
request.post(options).then((body) => {
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ import { join } from 'path';
|
|||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { WSServer } from '../../utils/webSocketServer.js';
|
||||
import { CommonSelectedNode } from '../../models/config.model.js';
|
||||
import { SelectedNode } from '../../models/config.model.js';
|
||||
|
||||
export class LNDWebSocketClient {
|
||||
|
||||
public logger: LoggerService = Logger;
|
||||
public common: CommonService = Common;
|
||||
public wsServer = WSServer;
|
||||
public webSocketClients: Array<{ selectedNode: CommonSelectedNode }> = [];
|
||||
public webSocketClients: Array<{ selectedNode: SelectedNode }> = [];
|
||||
|
||||
constructor() {
|
||||
this.wsServer.eventEmitterLND.on('CONNECT', (nodeIndex) => {
|
||||
|
|
@ -23,10 +23,10 @@ export class LNDWebSocketClient {
|
|||
});
|
||||
}
|
||||
|
||||
public connect = (selectedNode: CommonSelectedNode) => {
|
||||
public connect = (selectedNode: SelectedNode) => {
|
||||
try {
|
||||
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
|
||||
if (!clientExists && selectedNode.ln_server_url) {
|
||||
if (!clientExists && selectedNode.settings.lnServerUrl) {
|
||||
const newWebSocketClient = { selectedNode: selectedNode };
|
||||
this.webSocketClients.push(newWebSocketClient);
|
||||
}
|
||||
|
|
@ -35,10 +35,10 @@ export class LNDWebSocketClient {
|
|||
}
|
||||
};
|
||||
|
||||
public fetchUnpaidInvoices = (selectedNode: CommonSelectedNode) => {
|
||||
public fetchUnpaidInvoices = (selectedNode: SelectedNode) => {
|
||||
this.logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'WebSocketClient', msg: 'Getting Unpaid Invoices..' });
|
||||
const options = this.setOptionsForSelNode(selectedNode);
|
||||
options.url = selectedNode.ln_server_url + '/v1/invoices?pending_only=true';
|
||||
options.url = selectedNode.settings.lnServerUrl + '/v1/invoices?pending_only=true';
|
||||
return request(options).then((body) => {
|
||||
this.logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'WebSocketClient', msg: 'Unpaid Invoices Received', data: body });
|
||||
if (body.invoices && body.invoices.length > 0) {
|
||||
|
|
@ -55,10 +55,10 @@ export class LNDWebSocketClient {
|
|||
});
|
||||
};
|
||||
|
||||
public subscribeToInvoice = (options: any, selectedNode: CommonSelectedNode, rHash: string) => {
|
||||
public subscribeToInvoice = (options: any, selectedNode: SelectedNode, rHash: string) => {
|
||||
rHash = rHash?.replace(/\+/g, '-')?.replace(/[/]/g, '_');
|
||||
this.logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'WebSocketClient', msg: 'Subscribing to Invoice ' + rHash + ' ..' });
|
||||
options.url = selectedNode.ln_server_url + '/v2/invoices/subscribe/' + rHash;
|
||||
options.url = selectedNode.settings.lnServerUrl + '/v2/invoices/subscribe/' + rHash;
|
||||
request(options).then((msg) => {
|
||||
this.logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'WebSocketClient', msg: 'Invoice Information Received for ' + rHash });
|
||||
if (typeof msg === 'string') {
|
||||
|
|
@ -80,9 +80,9 @@ export class LNDWebSocketClient {
|
|||
});
|
||||
};
|
||||
|
||||
public subscribeToPayment = (options: any, selectedNode: CommonSelectedNode, paymentHash: string) => {
|
||||
public subscribeToPayment = (options: any, selectedNode: SelectedNode, paymentHash: string) => {
|
||||
this.logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'WebSocketClient', msg: 'Subscribing to Payment ' + paymentHash + ' ..' });
|
||||
options.url = selectedNode.ln_server_url + '/v2/router/track/' + paymentHash;
|
||||
options.url = selectedNode.settings.lnServerUrl + '/v2/router/track/' + paymentHash;
|
||||
request(options).then((msg) => {
|
||||
this.logger.log({ selectedNode: selectedNode, level: 'INFO', fileName: 'WebSocketClient', msg: 'Payment Information Received for ' + paymentHash });
|
||||
msg['type'] = 'payment';
|
||||
|
|
@ -97,17 +97,17 @@ export class LNDWebSocketClient {
|
|||
});
|
||||
};
|
||||
|
||||
public setOptionsForSelNode = (selectedNode: CommonSelectedNode) => {
|
||||
public setOptionsForSelNode = (selectedNode: SelectedNode) => {
|
||||
const options = { url: '', rejectUnauthorized: false, json: true, form: null };
|
||||
try {
|
||||
options['headers'] = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(selectedNode.macaroon_path, 'admin.macaroon')).toString('hex') };
|
||||
options['headers'] = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(selectedNode.authentication.macaroonPath, 'admin.macaroon')).toString('hex') };
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: selectedNode, level: 'ERROR', fileName: 'WebSocketClient', msg: 'Set Options Error', error: JSON.stringify(err) });
|
||||
}
|
||||
return options;
|
||||
};
|
||||
|
||||
public disconnect = (selectedNode: CommonSelectedNode) => {
|
||||
public disconnect = (selectedNode: SelectedNode) => {
|
||||
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
|
||||
if (clientExists) {
|
||||
this.logger.log({ selectedNode: clientExists.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Disconnecting from the LND\'s Websocket Server..' });
|
||||
|
|
@ -116,13 +116,13 @@ export class LNDWebSocketClient {
|
|||
}
|
||||
};
|
||||
|
||||
public updateSelectedNode = (newSelectedNode: CommonSelectedNode) => {
|
||||
public updateSelectedNode = (newSelectedNode: SelectedNode) => {
|
||||
const clientIdx = this.webSocketClients.findIndex((wsc) => +wsc.selectedNode.index === +newSelectedNode.index);
|
||||
let newClient = this.webSocketClients[clientIdx];
|
||||
if (!newClient) { newClient = { selectedNode: null }; }
|
||||
newClient.selectedNode = JSON.parse(JSON.stringify(newSelectedNode));
|
||||
this.webSocketClients[clientIdx] = newClient;
|
||||
if (this.webSocketClients[clientIdx].selectedNode.ln_version === '' || !this.webSocketClients[clientIdx].selectedNode.ln_version || this.common.isVersionCompatible(this.webSocketClients[clientIdx].selectedNode.ln_version, '0.11.0')) {
|
||||
if (this.webSocketClients[clientIdx].selectedNode.lnVersion === '' || !this.webSocketClients[clientIdx].selectedNode.lnVersion || this.common.isVersionCompatible(this.webSocketClients[clientIdx].selectedNode.lnVersion, '0.11.0')) {
|
||||
this.fetchUnpaidInvoices(this.webSocketClients[clientIdx].selectedNode);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import jwt from 'jsonwebtoken';
|
||||
import * as fs from 'fs';
|
||||
import { sep } from 'path';
|
||||
import ini from 'ini';
|
||||
|
|
@ -7,18 +8,139 @@ import { Database, DatabaseService } from '../../utils/database.js';
|
|||
import { Logger, LoggerService } from '../../utils/logger.js';
|
||||
import { Common, CommonService } from '../../utils/common.js';
|
||||
import { WSServer } from '../../utils/webSocketServer.js';
|
||||
import { AuthenticationConfiguration, NodeSettingsConfiguration } from '../../models/config.model.js';
|
||||
import { Authentication, SSO } from '../../models/config.model.js';
|
||||
|
||||
const options = { url: '' };
|
||||
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..' });
|
||||
options.url = 'https://blockchain.info/ticker';
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Currency Rates Received', data: body });
|
||||
res.status(200).json(JSON.parse(body));
|
||||
}).catch((errRes) => {
|
||||
const errMsg = 'Get 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 getFile = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting File..' });
|
||||
const file = req.query.path ? req.query.path : (req.session.selectedNode.settings.channelBackupPath + sep + 'channel-' + req.query.channel?.replace(':', '-') + '.bak');
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'Channel Point', data: req.query.channel });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'File Path', data: file });
|
||||
fs.readFile(file, 'utf8', (errRes, data) => {
|
||||
if (errRes) {
|
||||
if (errRes.code && errRes.code === 'ENOENT') { errRes.code = 'File Not Found!'; }
|
||||
const errMsg = 'Reading File 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 });
|
||||
} else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'File Data Received', data: data });
|
||||
res.status(200).json(data);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getApplicationSettings = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting RTL Configuration..' });
|
||||
const confFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json';
|
||||
fs.readFile(confFile, 'utf8', (errRes, data) => {
|
||||
if (errRes) {
|
||||
const errMsg = 'Get Node Config 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 });
|
||||
} else {
|
||||
const appConfData = common.removeSecureData(JSON.parse(data));
|
||||
appConfData.allowPasswordUpdate = common.appConfig.allowPasswordUpdate;
|
||||
appConfData.enable2FA = common.appConfig.enable2FA;
|
||||
appConfData.selectedNodeIndex = (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.selectedNode.index);
|
||||
common.appConfig.selectedNodeIndex = appConfData.selectedNodeIndex;
|
||||
const token = req.headers.authorization ? req.headers.authorization.split(' ')[1] : '';
|
||||
jwt.verify(token, common.secret_key, (err, user) => {
|
||||
if (err) {
|
||||
// Delete unnecessary data for initial response (without security token)
|
||||
const selNodeIdx = appConfData.nodes.findIndex((node) => node.index === appConfData.selectedNodeIndex) || 0;
|
||||
appConfData.SSO = new SSO();
|
||||
appConfData.secret2FA = '';
|
||||
appConfData.dbDirectoryPath = '';
|
||||
appConfData.nodes[selNodeIdx].authentication = new Authentication();
|
||||
delete appConfData.nodes[selNodeIdx].settings.bitcoindConfigPath;
|
||||
delete appConfData.nodes[selNodeIdx].settings.lnServerUrl;
|
||||
delete appConfData.nodes[selNodeIdx].settings.swapServerUrl;
|
||||
delete appConfData.nodes[selNodeIdx].settings.boltzServerUrl;
|
||||
delete appConfData.nodes[selNodeIdx].settings.enableOffers;
|
||||
delete appConfData.nodes[selNodeIdx].settings.enablePeerswap;
|
||||
delete appConfData.nodes[selNodeIdx].settings.channelBackupPath;
|
||||
appConfData.nodes = [appConfData.nodes[selNodeIdx]];
|
||||
}
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'RTL Configuration Received', data: appConfData });
|
||||
res.status(200).json(appConfData);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const updateSelectedNode = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Selected Node..' });
|
||||
const selNodeIndex = req.params.currNodeIndex ? +req.params.currNodeIndex : common.initSelectedNode ? +common.initSelectedNode.index : 1;
|
||||
const selNodeIndex = req.params.currNodeIndex ? +req.params.currNodeIndex : common.selectedNode ? +common.selectedNode.index : 1;
|
||||
req.session.selectedNode = common.findNode(selNodeIndex);
|
||||
common.selectedNode = req.session.selectedNode;
|
||||
if (req.headers && req.headers.authorization && req.headers.authorization !== '') {
|
||||
wsServer.updateLNWSClientDetails(req.session.id, +req.session.selectedNode.index, +req.params.prevNodeIndex);
|
||||
if (req.params.prevNodeIndex !== '-1') {
|
||||
|
|
@ -28,187 +150,9 @@ export const updateSelectedNode = (req, res, next) => {
|
|||
databaseService.loadDatabase(req.session);
|
||||
}
|
||||
}
|
||||
const responseVal = !req.session.selectedNode.ln_node ? '' : req.session.selectedNode.ln_node;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Selected Node Updated To ' + responseVal });
|
||||
res.status(200).json({ status: 'Selected Node Updated To: ' + JSON.stringify(responseVal) + '!' });
|
||||
};
|
||||
|
||||
export const getRTLConfigInitial = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting Initial RTL Configuration..' });
|
||||
const confFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
fs.readFile(confFile, 'utf8', (errRes, data) => {
|
||||
if (errRes) {
|
||||
if (errRes.code === 'ENOENT') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'RTLConf', msg: 'Node config does not exist!', error: { error: 'Node config does not exist.' } });
|
||||
res.status(200).json({ defaultNodeIndex: 0, selectedNodeIndex: 0, sso: {}, nodes: [] });
|
||||
} else {
|
||||
const errMsg = 'Get Node Config 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 });
|
||||
}
|
||||
} else {
|
||||
const nodeConfData = JSON.parse(data);
|
||||
const sso = { rtlSSO: common.rtl_sso, logoutRedirectLink: common.logout_redirect_link };
|
||||
const enable2FA = !!common.rtl_secret2fa;
|
||||
const allowPasswordUpdate = common.flg_allow_password_update;
|
||||
const nodesArr = [];
|
||||
if (common.nodes && common.nodes.length > 0) {
|
||||
common.nodes.forEach((node, i) => {
|
||||
const settings: NodeSettingsConfiguration = { unannouncedChannels: false };
|
||||
settings.userPersona = node.user_persona ? node.user_persona : 'MERCHANT';
|
||||
settings.themeMode = (node.theme_mode) ? node.theme_mode : 'DAY';
|
||||
settings.themeColor = (node.theme_color) ? node.theme_color : 'PURPLE';
|
||||
settings.unannouncedChannels = !!node.unannounced_channels || false;
|
||||
settings.fiatConversion = (node.fiat_conversion) ? !!node.fiat_conversion : false;
|
||||
settings.currencyUnit = node.currency_unit;
|
||||
nodesArr.push({
|
||||
index: node.index,
|
||||
lnNode: node.ln_node,
|
||||
lnImplementation: node.ln_implementation,
|
||||
settings: settings,
|
||||
authentication: {}
|
||||
});
|
||||
});
|
||||
}
|
||||
const body = { defaultNodeIndex: nodeConfData.defaultNodeIndex, selectedNodeIndex: (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.initSelectedNode.index), sso: sso, enable2FA: enable2FA, allowPasswordUpdate: allowPasswordUpdate, nodes: nodesArr };
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Initial RTL Configuration Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getRTLConfig = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting RTL Configuration..' });
|
||||
const confFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
fs.readFile(confFile, 'utf8', (errRes, data) => {
|
||||
if (errRes) {
|
||||
if (errRes.code === 'ENOENT') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'RTLConf', msg: 'Node config does not exist!', error: { error: 'Node config does not exist.' } });
|
||||
res.status(200).json({ defaultNodeIndex: 0, selectedNodeIndex: 0, sso: {}, nodes: [] });
|
||||
} else {
|
||||
const errMsg = 'Get Node Config 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 });
|
||||
}
|
||||
} else {
|
||||
const nodeConfData = JSON.parse(data);
|
||||
const sso = { rtlSSO: common.rtl_sso, logoutRedirectLink: common.logout_redirect_link };
|
||||
const enable2FA = !!common.rtl_secret2fa;
|
||||
const allowPasswordUpdate = common.flg_allow_password_update;
|
||||
const nodesArr = [];
|
||||
if (common.nodes && common.nodes.length > 0) {
|
||||
common.nodes.forEach((node, i) => {
|
||||
const authentication: AuthenticationConfiguration = {};
|
||||
authentication.configPath = (node.config_path) ? node.config_path : '';
|
||||
authentication.swapMacaroonPath = (node.swap_macaroon_path) ? node.swap_macaroon_path : '';
|
||||
authentication.boltzMacaroonPath = (node.boltz_macaroon_path) ? node.boltz_macaroon_path : '';
|
||||
const settings: NodeSettingsConfiguration = { unannouncedChannels: false };
|
||||
settings.userPersona = node.user_persona ? node.user_persona : 'MERCHANT';
|
||||
settings.themeMode = (node.theme_mode) ? node.theme_mode : 'DAY';
|
||||
settings.themeColor = (node.theme_color) ? node.theme_color : 'PURPLE';
|
||||
settings.unannouncedChannels = !!node.unannounced_channels || false;
|
||||
settings.fiatConversion = (node.fiat_conversion) ? !!node.fiat_conversion : false;
|
||||
settings.bitcoindConfigPath = node.bitcoind_config_path;
|
||||
settings.logLevel = node.log_level ? node.log_level : 'ERROR';
|
||||
settings.lnServerUrl = node.ln_server_url;
|
||||
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({
|
||||
index: node.index,
|
||||
lnNode: node.ln_node,
|
||||
lnImplementation: node.ln_implementation,
|
||||
settings: settings,
|
||||
authentication: authentication
|
||||
});
|
||||
});
|
||||
}
|
||||
const body = { defaultNodeIndex: nodeConfData.defaultNodeIndex, selectedNodeIndex: (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.initSelectedNode.index), sso: sso, enable2FA: enable2FA, allowPasswordUpdate: allowPasswordUpdate, nodes: nodesArr };
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'RTL Configuration Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const updateUISettings = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating UI Settings..' });
|
||||
const RTLConfFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
const config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
|
||||
const node = config.nodes.find((node) => (node.index === req.session.selectedNode.index));
|
||||
if (node && node.Settings) {
|
||||
node.Settings.userPersona = req.body.updatedSettings.userPersona;
|
||||
node.Settings.themeMode = req.body.updatedSettings.themeMode;
|
||||
node.Settings.themeColor = req.body.updatedSettings.themeColor;
|
||||
node.Settings.unannouncedChannels = req.body.updatedSettings.unannouncedChannels;
|
||||
node.Settings.fiatConversion = req.body.updatedSettings.fiatConversion;
|
||||
if (req.body.updatedSettings.fiatConversion) {
|
||||
node.Settings.currencyUnit = req.body.updatedSettings.currencyUnit ? req.body.updatedSettings.currencyUnit : 'USD';
|
||||
} else {
|
||||
delete node.Settings.currencyUnit;
|
||||
}
|
||||
const selectedNode = common.findNode(req.session.selectedNode.index);
|
||||
selectedNode.user_persona = req.body.updatedSettings.userPersona;
|
||||
selectedNode.theme_mode = req.body.updatedSettings.themeMode;
|
||||
selectedNode.theme_color = req.body.updatedSettings.themeColor;
|
||||
selectedNode.unannounced_channels = req.body.updatedSettings.unannouncedChannels;
|
||||
selectedNode.fiat_conversion = req.body.updatedSettings.fiatConversion;
|
||||
if (req.body.updatedSettings.fiatConversion) {
|
||||
selectedNode.currency_unit = req.body.updatedSettings.currencyUnit ? req.body.updatedSettings.currencyUnit : 'USD';
|
||||
} else {
|
||||
delete selectedNode.currency_unit;
|
||||
}
|
||||
common.replaceNode(req, selectedNode);
|
||||
}
|
||||
try {
|
||||
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'UI Settings Updated', data: maskPasswords(config) });
|
||||
res.status(201).json({ message: 'Node Settings Updated Successfully' });
|
||||
} catch (errRes) {
|
||||
const errMsg = 'Update Node Settings 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 update2FASettings = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating 2FA Settings..' });
|
||||
const RTLConfFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
const config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
|
||||
if (req.body.secret2fa && req.body.secret2fa.trim() !== '') {
|
||||
config.secret2fa = req.body.secret2fa;
|
||||
} else {
|
||||
delete config.secret2fa;
|
||||
}
|
||||
const message = req.body.secret2fa.trim() === '' ? 'Two factor authentication disabled successfully.' : 'Two factor authentication enabled successfully.';
|
||||
try {
|
||||
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
|
||||
common.rtl_secret2fa = config.secret2fa;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: message });
|
||||
res.status(201).json({ message: message });
|
||||
} catch (errRes) {
|
||||
const errMsg = 'Update 2FA Settings 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 updateDefaultNode = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Default Node..' });
|
||||
const RTLConfFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
const config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
|
||||
config.defaultNodeIndex = req.body.defaultNodeIndex;
|
||||
try {
|
||||
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Default Node Updated', data: maskPasswords(config) });
|
||||
res.status(201).json({ message: 'Default Node Updated Successfully' });
|
||||
} catch (errRes) {
|
||||
const errMsg = 'Update Default Node 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 });
|
||||
}
|
||||
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))));
|
||||
};
|
||||
|
||||
export const getConfig = (req, res, next) => {
|
||||
|
|
@ -217,14 +161,14 @@ export const getConfig = (req, res, next) => {
|
|||
let fileFormat = 'INI';
|
||||
switch (req.params.nodeType) {
|
||||
case 'ln':
|
||||
confFile = req.session.selectedNode.config_path;
|
||||
confFile = req.session.selectedNode.authentication.configPath;
|
||||
break;
|
||||
case 'bitcoind':
|
||||
confFile = req.session.selectedNode.bitcoind_config_path;
|
||||
confFile = req.session.selectedNode.settings.bitcoindConfigPath;
|
||||
break;
|
||||
case 'rtl':
|
||||
fileFormat = 'JSON';
|
||||
confFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
confFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json';
|
||||
break;
|
||||
default:
|
||||
confFile = '';
|
||||
|
|
@ -248,12 +192,12 @@ export const getConfig = (req, res, next) => {
|
|||
if (jsonConfig['Application Options'] && jsonConfig['Application Options'].color) {
|
||||
jsonConfig['Application Options'].color = '#' + jsonConfig['Application Options'].color;
|
||||
}
|
||||
if (req.params.nodeType === 'ln' && req.session.selectedNode.ln_implementation === 'ECL' && !jsonConfig['eclair.api.password']) {
|
||||
if (req.params.nodeType === 'ln' && req.session.selectedNode.lnImplementation === 'ECL' && !jsonConfig['eclair.api.password']) {
|
||||
fileFormat = 'HOCON';
|
||||
jsonConfig = parseHocon(data);
|
||||
}
|
||||
}
|
||||
jsonConfig = maskPasswords(jsonConfig);
|
||||
jsonConfig = common.maskPasswords(jsonConfig);
|
||||
const responseJSON = (fileFormat === 'JSON') ? jsonConfig : ini.stringify(jsonConfig)?.replace('color=\\#', 'color=#');
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Configuration File Data Received', data: responseJSON });
|
||||
res.status(200).json({ format: fileFormat, data: responseJSON });
|
||||
|
|
@ -261,134 +205,62 @@ export const getConfig = (req, res, next) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const getFile = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Getting File..' });
|
||||
const file = req.query.path ? req.query.path : (req.session.selectedNode.channel_backup_path + sep + 'channel-' + req.query.channel?.replace(':', '-') + '.bak');
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'Channel Point', data: req.query.channel });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'RTLConf', msg: 'File Path', data: file });
|
||||
fs.readFile(file, 'utf8', (errRes, data) => {
|
||||
if (errRes) {
|
||||
if (errRes.code && errRes.code === 'ENOENT') { errRes.code = 'File Not Found!'; }
|
||||
const errMsg = 'Reading File 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 });
|
||||
} else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'File Data Received', data: data });
|
||||
res.status(200).json(data);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
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';
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Currency Rates Received', data: body });
|
||||
res.status(200).json(JSON.parse(body));
|
||||
}).catch((errRes) => {
|
||||
const errMsg = 'Get 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 updateSSO = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating SSO Settings..' });
|
||||
const RTLConfFile = common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
export const updateNodeSettings = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Node Settings..' });
|
||||
const RTLConfFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json';
|
||||
const config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
|
||||
delete config.SSO;
|
||||
config.SSO = req.body.SSO;
|
||||
const node = config.nodes.find((node) => (node.index === req.session.selectedNode.index));
|
||||
if (node && node.settings) {
|
||||
node.settings = req.body.settings;
|
||||
if (req.body.authentication.boltzMacaroonPath) {
|
||||
node.authentication.boltzMacaroonPath = req.body.authentication.boltzMacaroonPath;
|
||||
} else {
|
||||
delete node.authentication.boltzMacaroonPath;
|
||||
}
|
||||
if (req.body.authentication.swapMacaroonPath) {
|
||||
node.authentication.swapMacaroonPath = req.body.authentication.swapMacaroonPath;
|
||||
} else {
|
||||
delete node.authentication.swapMacaroonPath;
|
||||
}
|
||||
}
|
||||
try {
|
||||
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'SSO Setting Updated', data: maskPasswords(config) });
|
||||
res.status(201).json({ message: 'SSO Updated Successfully' });
|
||||
} catch (errRes) {
|
||||
const errMsg = 'Update SSO 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 updateServiceSettings = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Service Settings..' });
|
||||
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.forEach((node) => {
|
||||
if (node.index === req.session.selectedNode.index) {
|
||||
switch (req.body.service) {
|
||||
case 'LOOP':
|
||||
if (req.body.settings.enable) {
|
||||
node.Settings.swapServerUrl = req.body.settings.serverUrl;
|
||||
node.Authentication.swapMacaroonPath = req.body.settings.macaroonPath;
|
||||
selectedNode.swap_server_url = req.body.settings.serverUrl;
|
||||
selectedNode.swap_macaroon_path = req.body.settings.macaroonPath;
|
||||
} else {
|
||||
delete node.Settings.swapServerUrl;
|
||||
delete node.Authentication.swapMacaroonPath;
|
||||
delete selectedNode.swap_server_url;
|
||||
delete selectedNode.swap_macaroon_path;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'BOLTZ':
|
||||
if (req.body.settings.enable) {
|
||||
node.Settings.boltzServerUrl = req.body.settings.serverUrl;
|
||||
node.Authentication.boltzMacaroonPath = req.body.settings.macaroonPath;
|
||||
selectedNode.boltz_server_url = req.body.settings.serverUrl;
|
||||
selectedNode.boltz_macaroon_path = req.body.settings.macaroonPath;
|
||||
} else {
|
||||
delete node.Settings.boltzServerUrl;
|
||||
delete node.Authentication.boltzMacaroonPath;
|
||||
delete selectedNode.boltz_server_url;
|
||||
delete selectedNode.boltz_macaroon_path;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'OFFERS':
|
||||
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;
|
||||
}
|
||||
const selectedNode = common.findNode(req.session.selectedNode.index);
|
||||
if (selectedNode && selectedNode.settings) {
|
||||
selectedNode.settings = req.body.settings;
|
||||
selectedNode.authentication.boltzMacaroonPath = req.body.authentication.boltzMacaroonPath;
|
||||
selectedNode.authentication.swapMacaroonPath = req.body.authentication.swapMacaroonPath;
|
||||
common.replaceNode(req, selectedNode);
|
||||
}
|
||||
return node;
|
||||
});
|
||||
try {
|
||||
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Service Settings Updated', data: maskPasswords(config) });
|
||||
res.status(201).json({ message: 'Service Settings Updated Successfully' });
|
||||
let responseNode = JSON.parse(JSON.stringify(common.selectedNode));
|
||||
responseNode = common.removeAuthSecureData(responseNode);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Node Settings Updated', data: responseNode });
|
||||
res.status(201).json(responseNode);
|
||||
} catch (errRes) {
|
||||
const errMsg = 'Update Service Settings Error';
|
||||
const errMsg = 'Update Node Settings 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 maskPasswords = (obj) => {
|
||||
const keys = Object.keys(obj);
|
||||
const length = keys.length;
|
||||
if (length !== 0) {
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (typeof obj[keys[i]] === 'object') {
|
||||
keys[keys[i]] = maskPasswords(obj[keys[i]]);
|
||||
}
|
||||
if (typeof keys[i] === 'string' &&
|
||||
(keys[i].toLowerCase().includes('password') || keys[i].toLowerCase().includes('multipass') ||
|
||||
keys[i].toLowerCase().includes('rpcpass') || keys[i].toLowerCase().includes('rpcpassword') ||
|
||||
keys[i].toLowerCase().includes('rpcuser'))
|
||||
) {
|
||||
obj[keys[i]] = '********************';
|
||||
}
|
||||
}
|
||||
export const updateApplicationSettings = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Updating Application Settings..' });
|
||||
const RTLConfFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json';
|
||||
try {
|
||||
const config = common.addSecureData(req.body);
|
||||
common.appConfig = JSON.parse(JSON.stringify(config));
|
||||
delete config.selectedNodeIndex;
|
||||
delete config.enable2FA;
|
||||
delete config.allowPasswordUpdate;
|
||||
delete config.rtlConfFilePath;
|
||||
delete config.rtlPass;
|
||||
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
|
||||
const newConfig = JSON.parse(JSON.stringify(common.appConfig));
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: common.maskPasswords(newConfig) });
|
||||
res.status(201).json(common.removeSecureData(newConfig));
|
||||
} catch (errRes) {
|
||||
const errMsg = 'Update Default Node 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 });
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,18 +47,19 @@ const handleMultipleFailedAttemptsError = (failed, currentTime, errMsg) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const verifyToken = (twoFAToken) => !!(common.rtl_secret2fa && common.rtl_secret2fa !== '' && otplib.authenticator.check(twoFAToken, common.rtl_secret2fa));
|
||||
export const verifyToken = (twoFAToken) => !!(common.appConfig.secret2FA && common.appConfig.secret2FA !== '' && otplib.authenticator.check(twoFAToken, common.appConfig.secret2FA));
|
||||
|
||||
export const authenticateUser = (req, res, next) => {
|
||||
const { authenticateWith, authenticationValue, twoFAToken } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Authenticate', msg: 'Authenticating User..' });
|
||||
if (+common.rtl_sso) {
|
||||
if (req.body.authenticateWith === 'JWT' && jwt.verify(req.body.authenticationValue, common.secret_key)) {
|
||||
if (+common.appConfig.SSO.rtlSso) {
|
||||
if (authenticateWith === 'JWT' && jwt.verify(authenticationValue, common.secret_key)) {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Authenticate', msg: 'User Authenticated' });
|
||||
res.status(406).json({ message: 'SSO Authentication Error', error: 'Login with Password is not allowed with SSO.' });
|
||||
} else if (req.body.authenticateWith === 'PASSWORD') {
|
||||
if (common.cookie_value.trim().length >= 32 && crypto.timingSafeEqual(Buffer.from(crypto.createHash('sha256').update(common.cookie_value).digest('hex'), 'utf-8'), Buffer.from(req.body.authenticationValue, 'utf-8'))) {
|
||||
} else if (authenticateWith === 'PASSWORD') {
|
||||
if (common.appConfig.SSO.cookieValue.trim().length >= 32 && crypto.timingSafeEqual(Buffer.from(crypto.createHash('sha256').update(common.appConfig.SSO.cookieValue).digest('hex'), 'utf-8'), Buffer.from(authenticationValue, 'utf-8'))) {
|
||||
common.refreshCookie();
|
||||
if (!req.session.selectedNode) { req.session.selectedNode = common.initSelectedNode; }
|
||||
if (!req.session.selectedNode) { req.session.selectedNode = common.selectedNode; }
|
||||
const token = jwt.sign({ user: 'SSO_USER' }, common.secret_key);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Authenticate', msg: 'User Authenticated' });
|
||||
res.status(200).json({ token: token });
|
||||
|
|
@ -72,40 +73,40 @@ export const authenticateUser = (req, res, next) => {
|
|||
const currentTime = new Date().getTime();
|
||||
const reqIP = common.getRequestIP(req);
|
||||
const failed = getFailedInfo(reqIP, currentTime);
|
||||
const password = req.body.authenticationValue;
|
||||
if (common.rtl_pass === password && failed.count < ALLOWED_LOGIN_ATTEMPTS) {
|
||||
if (req.body.twoFAToken && req.body.twoFAToken !== '') {
|
||||
if (!verifyToken(req.body.twoFAToken)) {
|
||||
const password = authenticationValue;
|
||||
if (common.appConfig.rtlPass === password && failed.count < ALLOWED_LOGIN_ATTEMPTS) {
|
||||
if (twoFAToken && twoFAToken !== '') {
|
||||
if (!verifyToken(twoFAToken)) {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'Authenticate', msg: 'Invalid Token! Failed IP ' + reqIP, error: { error: 'Invalid token.' } });
|
||||
failed.count = failed.count + 1;
|
||||
failed.lastTried = currentTime;
|
||||
return res.status(401).json(handleMultipleFailedAttemptsError(failed, currentTime, 'Invalid 2FA Token!'));
|
||||
}
|
||||
}
|
||||
if (!req.session.selectedNode) { req.session.selectedNode = common.initSelectedNode; }
|
||||
if (!req.session.selectedNode) { req.session.selectedNode = common.selectedNode; }
|
||||
delete failedLoginAttempts[reqIP];
|
||||
const token = jwt.sign({ user: 'NODE_USER' }, common.secret_key);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Authenticate', msg: 'User Authenticated' });
|
||||
res.status(200).json({ token: token });
|
||||
} else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'Authenticate', msg: 'Invalid Password! Failed IP ' + reqIP, error: { error: 'Invalid password.' } });
|
||||
failed.count = common.rtl_pass !== password ? (failed.count + 1) : failed.count;
|
||||
failed.lastTried = common.rtl_pass !== password ? currentTime : failed.lastTried;
|
||||
failed.count = common.appConfig.rtlPass !== password ? (failed.count + 1) : failed.count;
|
||||
failed.lastTried = common.appConfig.rtlPass !== password ? currentTime : failed.lastTried;
|
||||
return res.status(401).json(handleMultipleFailedAttemptsError(failed, currentTime, 'Invalid Password!'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const resetPassword = (req, res, next) => {
|
||||
const { currPassword, newPassword } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Authenticate', msg: 'Resetting Password..' });
|
||||
if (+common.rtl_sso) {
|
||||
if (+common.appConfig.SSO.rtlSso) {
|
||||
const errMsg = 'Password cannot be reset for SSO authentication';
|
||||
const err = common.handleError({ statusCode: 401, message: 'Password Reset Error', error: errMsg }, 'Authenticate', errMsg, req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
} else {
|
||||
const currPassword = req.body.currPassword;
|
||||
if (common.rtl_pass === currPassword) {
|
||||
common.rtl_pass = common.replacePasswordWithHash(req.body.newPassword);
|
||||
if (common.appConfig.rtlPass === currPassword) {
|
||||
common.appConfig.rtlPass = common.replacePasswordWithHash(newPassword);
|
||||
const token = jwt.sign({ user: 'NODE_USER' }, common.secret_key);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Authenticate', msg: 'Password Reset Successful' });
|
||||
res.status(200).json({ token: token });
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ export const getSwapInfo = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const createSwap = (req, res, next) => {
|
||||
const { amount, sendFromInternal, address } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Boltz', msg: 'Creating Swap..' });
|
||||
options = common.getBoltzServerOptions(req);
|
||||
if (options.url === '') {
|
||||
|
|
@ -88,8 +89,9 @@ export const createSwap = (req, res, next) => {
|
|||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
}
|
||||
options.url = options.url + '/v1/createswap';
|
||||
options.body = { amount: req.body.amount };
|
||||
if (req.body.address !== '') { options.body.address = req.body.address; }
|
||||
options.body = { amount: amount };
|
||||
if (sendFromInternal) { options.body.send_from_internal = sendFromInternal; }
|
||||
if (address && address !== '') { options.body.address = address; }
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Boltz', msg: 'Create Swap Options Body', data: options.body });
|
||||
request.post(options).then((createSwapRes) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Boltz', msg: 'Swap Created', data: createSwapRes });
|
||||
|
|
@ -101,6 +103,7 @@ export const createSwap = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const createReverseSwap = (req, res, next) => {
|
||||
const { amount, acceptZeroConf, address } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Boltz', msg: 'Creating Reverse Swap..' });
|
||||
options = common.getBoltzServerOptions(req);
|
||||
if (options.url === '') {
|
||||
|
|
@ -109,8 +112,8 @@ export const createReverseSwap = (req, res, next) => {
|
|||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
}
|
||||
options.url = options.url + '/v1/createreverseswap';
|
||||
options.body = { amount: req.body.amount };
|
||||
if (req.body.address !== '') { options.body.address = req.body.address; }
|
||||
options.body = { amount: amount, accept_zero_conf: acceptZeroConf || false };
|
||||
if (address && address !== '') { options.body.address = address; }
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Boltz', msg: 'Create Reverse Swap Body', data: options.body });
|
||||
request.post(options).then((createReverseSwapRes) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Boltz', msg: 'Reverse Swap Created', data: createReverseSwapRes });
|
||||
|
|
@ -122,6 +125,7 @@ export const createReverseSwap = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const createChannel = (req, res, next) => {
|
||||
const { amount, address } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Boltz', msg: 'Creating Boltz Channel..' });
|
||||
options = common.getBoltzServerOptions(req);
|
||||
if (options.url === '') {
|
||||
|
|
@ -130,8 +134,8 @@ export const createChannel = (req, res, next) => {
|
|||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
}
|
||||
options.url = options.url + '/v1/createchannel';
|
||||
options.body = { amount: req.body.amount };
|
||||
if (req.body.address !== '') { options.body.address = req.body.address; }
|
||||
options.body = { amount: amount };
|
||||
if (address && address !== '') { options.body.address = address; }
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Boltz', msg: 'Create Channel Options Body', data: options.body });
|
||||
request.post(options).then((createChannelRes) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Boltz', msg: 'Boltz Channel Created', data: createChannelRes });
|
||||
|
|
|
|||
|
|
@ -6,21 +6,22 @@ const logger: LoggerService = Logger;
|
|||
const common: CommonService = Common;
|
||||
|
||||
export const loopOut = (req, res, next) => {
|
||||
const { amount, targetConf, swapRoutingFee, minerFee, prepayRoutingFee, prepayAmt, swapFee, swapPublicationDeadline, chanId, destAddress } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Loop', msg: 'Looping Out..' });
|
||||
options.uri = '/v1/loop/out';
|
||||
options.body = {
|
||||
amt: req.body.amount,
|
||||
sweep_conf_target: req.body.targetConf,
|
||||
max_swap_routing_fee: req.body.swapRoutingFee,
|
||||
max_miner_fee: req.body.minerFee,
|
||||
max_prepay_routing_fee: req.body.prepayRoutingFee,
|
||||
max_prepay_amt: req.body.prepayAmt,
|
||||
max_swap_fee: req.body.swapFee,
|
||||
swap_publication_deadline: req.body.swapPublicationDeadline,
|
||||
amt: amount,
|
||||
sweep_conf_target: targetConf,
|
||||
max_swap_routing_fee: swapRoutingFee,
|
||||
max_miner_fee: minerFee,
|
||||
max_prepay_routing_fee: prepayRoutingFee,
|
||||
max_prepay_amt: prepayAmt,
|
||||
max_swap_fee: swapFee,
|
||||
swap_publication_deadline: swapPublicationDeadline,
|
||||
initiator: 'RTL'
|
||||
};
|
||||
if (req.body.chanId !== '') { options.body['loop_out_channel'] = req.body.chanId; }
|
||||
if (req.body.destAddress !== '') { options.body['dest'] = req.body.destAddress; }
|
||||
if (chanId !== '') { options.body['loop_out_channel'] = chanId; }
|
||||
if (destAddress !== '') { options.body['dest'] = destAddress; }
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Loop', msg: 'Loop Out Body', data: options.body });
|
||||
request.post(options).then((loopOutRes) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Loop', msg: 'Looped Out', data: loopOutRes });
|
||||
|
|
@ -87,12 +88,13 @@ export const loopOutTermsAndQuotes = (req, res, next) => {
|
|||
};
|
||||
|
||||
export const loopIn = (req, res, next) => {
|
||||
const { amount, swapFee, minerFee } = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Loop', msg: 'Looping In..' });
|
||||
options.uri = '/v1/loop/in';
|
||||
options.body = {
|
||||
amt: req.body.amount,
|
||||
max_swap_fee: req.body.swapFee,
|
||||
max_miner_fee: req.body.minerFee,
|
||||
amt: amount,
|
||||
max_swap_fee: swapFee,
|
||||
max_miner_fee: minerFee,
|
||||
initiator: 'RTL'
|
||||
};
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Loop', msg: 'Loop In Body', data: options.body });
|
||||
|
|
|
|||
|
|
@ -1,71 +1,87 @@
|
|||
export class CommonSelectedNode {
|
||||
export class SSO {
|
||||
|
||||
constructor(
|
||||
public options?: any,
|
||||
public ln_server_url?: string,
|
||||
public macaroon_path?: string,
|
||||
public macaroon_value?: string,
|
||||
public rune_path?: string,
|
||||
public rune_value?: string,
|
||||
public ln_api_password?: string,
|
||||
public swap_server_url?: string,
|
||||
public boltz_server_url?: string,
|
||||
public config_path?: string,
|
||||
public rtl_conf_file_path?: string,
|
||||
public swap_macaroon_path?: string,
|
||||
public boltz_macaroon_path?: string,
|
||||
public bitcoind_config_path?: string,
|
||||
public channel_backup_path?: string,
|
||||
public log_level?: string,
|
||||
public log_file?: string,
|
||||
public index?: string,
|
||||
public ln_node?: string,
|
||||
public ln_implementation?: string,
|
||||
public user_persona?: string,
|
||||
public theme_mode?: string,
|
||||
public theme_color?: string,
|
||||
public unannounced_channels?: boolean,
|
||||
public fiat_conversion?: boolean,
|
||||
public currency_unit?: string,
|
||||
public ln_version?: string,
|
||||
public api_version?: string,
|
||||
public enable_offers?: boolean,
|
||||
public enable_peerswap?: boolean
|
||||
public rtlSso?: number,
|
||||
public rtlCookiePath?: string,
|
||||
public logoutRedirectLink?: string,
|
||||
public cookieValue?: string
|
||||
) { }
|
||||
|
||||
}
|
||||
|
||||
export class AuthenticationConfiguration {
|
||||
|
||||
constructor(
|
||||
public configPath?: string,
|
||||
public swapMacaroonPath?: string,
|
||||
public boltzMacaroonPath?: string
|
||||
) { }
|
||||
|
||||
}
|
||||
|
||||
export class NodeSettingsConfiguration {
|
||||
export class Settings {
|
||||
|
||||
constructor(
|
||||
public blockExplorerUrl: string,
|
||||
public lnServerUrl?: string,
|
||||
public swapServerUrl?: string,
|
||||
public boltzServerUrl?: string,
|
||||
public bitcoindConfigPath?: string,
|
||||
public channelBackupPath?: string,
|
||||
public logLevel?: string,
|
||||
public logFile?: string,
|
||||
public userPersona?: string,
|
||||
public themeMode?: string,
|
||||
public themeColor?: string,
|
||||
public unannouncedChannels?: boolean,
|
||||
public fiatConversion?: boolean,
|
||||
public currencyUnit?: string,
|
||||
public bitcoindConfigPath?: string,
|
||||
public logLevel?: string,
|
||||
public lnServerUrl?: string,
|
||||
public swapServerUrl?: string,
|
||||
public boltzServerUrl?: string,
|
||||
public channelBackupPath?: string,
|
||||
public enableOffers?: boolean,
|
||||
public enablePeerswap?: boolean
|
||||
) { }
|
||||
|
||||
}
|
||||
|
||||
export class Authentication {
|
||||
|
||||
constructor(
|
||||
public options?: any,
|
||||
public configPath?: string,
|
||||
public macaroonPath?: string,
|
||||
public macaroonValue?: string,
|
||||
public runePath?: string,
|
||||
public runeValue?: string,
|
||||
public lnApiPassword?: string,
|
||||
public swapMacaroonPath?: string,
|
||||
public boltzMacaroonPath?: string
|
||||
) { }
|
||||
|
||||
}
|
||||
|
||||
export class ApplicationConfig {
|
||||
|
||||
constructor(
|
||||
public defaultNodeIndex: number,
|
||||
public selectedNodeIndex: number,
|
||||
public dbDirectoryPath?: string,
|
||||
public rtlConfFilePath?: string,
|
||||
public rtlPass?: string,
|
||||
public multiPass?: string,
|
||||
public multiPassHashed?: string,
|
||||
public allowPasswordUpdate?: boolean,
|
||||
public enable2FA?: boolean,
|
||||
public secret2FA?: string,
|
||||
public SSO?: SSO,
|
||||
public nodes?: SelectedNode[]
|
||||
) {}
|
||||
|
||||
}
|
||||
|
||||
export class SelectedNode {
|
||||
|
||||
constructor(
|
||||
public logLevel?: string,
|
||||
public logFile?: string,
|
||||
public index?: number,
|
||||
public lnNode?: string,
|
||||
public lnImplementation?: string,
|
||||
public lnVersion?: string,
|
||||
public settings?: Settings,
|
||||
public authentication?: Authentication
|
||||
) { }
|
||||
|
||||
}
|
||||
|
||||
export class LogJSONObj {
|
||||
|
||||
constructor(
|
||||
|
|
@ -74,7 +90,7 @@ export class LogJSONObj {
|
|||
public data?: string | any | any[],
|
||||
public error?: string | any,
|
||||
public fileName?: string,
|
||||
public selectedNode?: CommonSelectedNode
|
||||
public selectedNode?: SelectedNode
|
||||
) { }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getRTLConfigInitial, getRTLConfig, updateUISettings, update2FASettings, getConfig, getFile, updateSelectedNode, updateDefaultNode, updateServiceSettings, updateSSO, getCurrencyRates } 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('/rtlconfinit', getRTLConfigInitial);
|
||||
router.get('/rtlconf', isAuthenticated, getRTLConfig);
|
||||
router.post('/', isAuthenticated, updateUISettings);
|
||||
router.post('/update2FA', isAuthenticated, update2FASettings);
|
||||
router.get('/config/:nodeType', isAuthenticated, getConfig);
|
||||
router.get('/', getApplicationSettings);
|
||||
router.get('/rates', getCurrencyRates);
|
||||
router.get('/file', isAuthenticated, getFile);
|
||||
router.get('/updateSelNode/:currNodeIndex/:prevNodeIndex', updateSelectedNode);
|
||||
router.post('/updateDefaultNode', updateDefaultNode);
|
||||
router.post('/updateServiceSettings', updateServiceSettings);
|
||||
router.post('/updateSSO', updateSSO);
|
||||
router.get('/rates', getCurrencyRates);
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export class ExpressApplication {
|
|||
public directoryName = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
constructor() {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'App', msg: 'Starting Express Application..' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'App', msg: 'Starting Express Application..' });
|
||||
this.app.set('trust proxy', true);
|
||||
this.app.use(sessions({ secret: this.common.secret_key, saveUninitialized: true, cookie: { secure: false, maxAge: ONE_DAY }, resave: false }));
|
||||
this.app.use(cookieParser(this.common.secret_key));
|
||||
|
|
@ -52,7 +52,7 @@ export class ExpressApplication {
|
|||
public setCSRF = () => { CSRF.mount(this.app); };
|
||||
|
||||
public setApplicationRoutes = () => {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'App', msg: 'Setting up Application Routes..' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'App', msg: 'Setting up Application Routes..' });
|
||||
this.app.use(this.common.baseHref + '/api', sharedRoutes);
|
||||
this.app.use(this.common.baseHref + '/api/lnd', lndRoutes);
|
||||
this.app.use(this.common.baseHref + '/api/cln', clnRoutes);
|
||||
|
|
@ -67,29 +67,29 @@ export class ExpressApplication {
|
|||
this.handleApplicationErrors(err, res);
|
||||
next();
|
||||
});
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'App', msg: 'Application Routes Set' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'App', msg: 'Application Routes Set' });
|
||||
};
|
||||
|
||||
public handleApplicationErrors = (err, res) => {
|
||||
switch (err.code) {
|
||||
case 'EACCES':
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'App', msg: 'Server requires elevated privileges' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'App', msg: 'Server requires elevated privileges' });
|
||||
res.status(406).send('Server requires elevated privileges.');
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'App', msg: 'Server is already in use' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'App', msg: 'Server is already in use' });
|
||||
res.status(409).send('Server is already in use.');
|
||||
break;
|
||||
case 'ECONNREFUSED':
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'App', msg: 'Server is down/locked' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'App', msg: 'Server is down/locked' });
|
||||
res.status(401).send('Server is down/locked.');
|
||||
break;
|
||||
case 'EBADCSRFTOKEN':
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'App', msg: 'Invalid CSRF token. Form tempered.' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'App', msg: 'Invalid CSRF token. Form tempered.' });
|
||||
res.status(403).send('Invalid CSRF token, form tempered.');
|
||||
break;
|
||||
default:
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'App', msg: 'DEFUALT ERROR', error: err });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'App', msg: 'DEFUALT ERROR', error: err });
|
||||
res.status(400).send(JSON.stringify(err));
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export const verifyWSUser = (info, next) => {
|
|||
} catch (err) {
|
||||
cookies = {};
|
||||
updatedReq['cookies'] = JSON.parse(cookies);
|
||||
logger.log({ selectedNode: common.initSelectedNode, level: 'WARN', fileName: 'AuthCheck', msg: '403 Unable to read CSRF token cookie', data: err });
|
||||
logger.log({ selectedNode: common.selectedNode, level: 'WARN', fileName: 'AuthCheck', msg: '403 Unable to read CSRF token cookie', data: err });
|
||||
}
|
||||
csurfProtection(updatedReq, null, (err) => {
|
||||
if (err) {
|
||||
|
|
@ -54,7 +54,7 @@ export const verifyWSUser = (info, next) => {
|
|||
}
|
||||
});
|
||||
} catch (err) {
|
||||
logger.log({ selectedNode: common.initSelectedNode, level: 'WARN', fileName: 'AuthCheck', msg: '403 Unable to verify CSRF token', data: err });
|
||||
logger.log({ selectedNode: common.selectedNode, level: 'WARN', fileName: 'AuthCheck', msg: '403 Unable to verify CSRF token', data: err });
|
||||
next(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,26 +4,17 @@ import { fileURLToPath } from 'url';
|
|||
import * as crypto from 'crypto';
|
||||
import request from 'request-promise';
|
||||
import { Logger, LoggerService } from './logger.js';
|
||||
import { CommonSelectedNode } from '../models/config.model.js';
|
||||
import { ApplicationConfig, SelectedNode } from '../models/config.model.js';
|
||||
|
||||
export class CommonService {
|
||||
|
||||
public logger: LoggerService = Logger;
|
||||
public nodes: CommonSelectedNode[] = [];
|
||||
public initSelectedNode: CommonSelectedNode = null;
|
||||
public rtl_conf_file_path = '';
|
||||
public nodes: SelectedNode[] = [];
|
||||
public selectedNode: SelectedNode = null;
|
||||
public ssoInit = { rtlSso: 0, rtlCookiePath: '', logoutRedirectLink: '', cookieValue: '' };
|
||||
public appConfig: ApplicationConfig = { defaultNodeIndex: 0, selectedNodeIndex: 0, rtlConfFilePath: '', dbDirectoryPath: join(dirname(fileURLToPath(import.meta.url)), '..', '..'), rtlPass: '', allowPasswordUpdate: true, enable2FA: false, secret2FA: '', SSO: this.ssoInit, nodes: [] };
|
||||
public port = 3000;
|
||||
public host = '';
|
||||
public db_directory_path = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
||||
public rtl_pass = '';
|
||||
public flg_allow_password_update = true;
|
||||
public rtl_secret2fa = '';
|
||||
public rtl_sso = 0;
|
||||
public rtl_cookie_path = '';
|
||||
public logout_redirect_link = '';
|
||||
public cookie_value = '';
|
||||
public ln_version = '';
|
||||
public api_version = '';
|
||||
public secret_key = crypto.randomBytes(64).toString('hex');
|
||||
public read_dummy_data = false;
|
||||
public baseHref = '/rtl';
|
||||
|
|
@ -33,101 +24,168 @@ export class CommonService {
|
|||
{ name: 'JUL', days: 31 }, { name: 'AUG', days: 31 }, { name: 'SEP', days: 30 }, { name: 'OCT', days: 31 }, { name: 'NOV', days: 30 }, { name: 'DEC', days: 31 }
|
||||
];
|
||||
|
||||
constructor() { }
|
||||
constructor() {}
|
||||
|
||||
public maskPasswords = (obj) => {
|
||||
const keys = Object.keys(obj);
|
||||
const length = keys.length;
|
||||
if (length !== 0) {
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (typeof obj[keys[i]] === 'object') {
|
||||
keys[keys[i]] = this.maskPasswords(obj[keys[i]]);
|
||||
}
|
||||
if (typeof keys[i] === 'string' &&
|
||||
((keys[i].toLowerCase().includes('password') && keys[i] !== 'allowPasswordUpdate') || keys[i].toLowerCase().includes('multipass') ||
|
||||
keys[i].toLowerCase().includes('rpcpass') || keys[i].toLowerCase().includes('rpcpassword') ||
|
||||
keys[i].toLowerCase().includes('rpcuser'))
|
||||
) {
|
||||
obj[keys[i]] = '*'.repeat(20);
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
public removeAuthSecureData = (node: SelectedNode) => {
|
||||
delete node.authentication.macaroonPath;
|
||||
delete node.authentication.runePath;
|
||||
delete node.authentication.runeValue;
|
||||
delete node.authentication.lnApiPassword;
|
||||
delete node.authentication.options;
|
||||
return node;
|
||||
};
|
||||
|
||||
public removeSecureData = (config: ApplicationConfig) => {
|
||||
delete config.rtlConfFilePath;
|
||||
delete config.rtlPass;
|
||||
delete config.multiPass;
|
||||
delete config.multiPassHashed;
|
||||
delete config.secret2FA;
|
||||
config.nodes?.map((node) => this.removeAuthSecureData(node));
|
||||
return config;
|
||||
};
|
||||
|
||||
public addSecureData = (config: ApplicationConfig) => {
|
||||
config.rtlConfFilePath = this.appConfig.rtlConfFilePath;
|
||||
config.rtlPass = this.appConfig.rtlPass;
|
||||
config.multiPassHashed = this.appConfig.multiPassHashed;
|
||||
config.SSO.rtlCookiePath = this.appConfig.SSO.rtlCookiePath;
|
||||
if (this.appConfig.multiPass) {
|
||||
config.multiPass = this.appConfig.multiPass;
|
||||
}
|
||||
if (config.secret2FA === this.appConfig.secret2FA) {
|
||||
config.secret2FA = this.appConfig.secret2FA;
|
||||
}
|
||||
config.nodes.map((node, i) => {
|
||||
if (this.appConfig && this.appConfig.nodes && this.appConfig.nodes.length > i && this.appConfig.nodes[i].authentication) {
|
||||
if (this.appConfig.nodes[i].authentication.macaroonPath) {
|
||||
node.authentication.macaroonPath = this.appConfig.nodes[i].authentication.macaroonPath;
|
||||
}
|
||||
if (this.appConfig.nodes[i].authentication.runePath) {
|
||||
node.authentication.runePath = this.appConfig.nodes[i].authentication.runePath;
|
||||
}
|
||||
if (this.appConfig.nodes[i].authentication.lnApiPassword) {
|
||||
node.authentication.lnApiPassword = this.appConfig.nodes[i].authentication.lnApiPassword;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
});
|
||||
return config;
|
||||
};
|
||||
|
||||
public setSwapServerOptions = (req) => {
|
||||
const swapOptions = {
|
||||
baseUrl: req.session.selectedNode.swap_server_url,
|
||||
baseUrl: req.session.selectedNode.settings.swapServerUrl,
|
||||
uri: '',
|
||||
rejectUnauthorized: false,
|
||||
json: true,
|
||||
headers: { 'Grpc-Metadata-macaroon': '' }
|
||||
};
|
||||
if (req.session.selectedNode.swap_macaroon_path) {
|
||||
if (req.session.selectedNode.authentication.swapMacaroonPath) {
|
||||
try {
|
||||
swapOptions.headers = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(req.session.selectedNode.swap_macaroon_path, 'loop.macaroon')).toString('hex') };
|
||||
swapOptions.headers = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(req.session.selectedNode.authentication.swapMacaroonPath, 'loop.macaroon')).toString('hex') };
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Loop macaroon Error', error: err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Loop macaroon Error', error: err });
|
||||
}
|
||||
}
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Swap Options', data: swapOptions });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Swap Options', data: swapOptions });
|
||||
return swapOptions;
|
||||
};
|
||||
|
||||
public getBoltzServerOptions = (req) => {
|
||||
const boltzOptions = {
|
||||
url: req.session.selectedNode.boltz_server_url,
|
||||
url: req.session.selectedNode.settings.boltzServerUrl,
|
||||
rejectUnauthorized: false,
|
||||
json: true,
|
||||
headers: { 'Grpc-Metadata-macaroon': '' }
|
||||
};
|
||||
if (req.session.selectedNode.boltz_macaroon_path) {
|
||||
if (req.session.selectedNode.authentication.boltzMacaroonPath) {
|
||||
try {
|
||||
boltzOptions.headers = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(req.session.selectedNode.boltz_macaroon_path, 'admin.macaroon')).toString('hex') };
|
||||
boltzOptions.headers = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(req.session.selectedNode.authentication.boltzMacaroonPath, 'admin.macaroon')).toString('hex') };
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Boltz macaroon Error', error: err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Boltz macaroon Error', error: err });
|
||||
}
|
||||
}
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Boltz Options', data: boltzOptions });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Boltz Options', data: boltzOptions });
|
||||
return boltzOptions;
|
||||
};
|
||||
|
||||
public getOptions = (req) => {
|
||||
if (req.session.selectedNode && req.session.selectedNode.options) {
|
||||
req.session.selectedNode.options.method = (req.session.selectedNode.ln_implementation && req.session.selectedNode.ln_implementation.toUpperCase() === 'LND') ? 'GET' : 'POST';
|
||||
delete req.session.selectedNode.options.form;
|
||||
delete req.session.selectedNode.options.body;
|
||||
req.session.selectedNode.options.qs = {};
|
||||
return req.session.selectedNode.options;
|
||||
if (req.session.selectedNode && req.session.selectedNode.authentication.options) {
|
||||
req.session.selectedNode.authentication.options.method = (req.session.selectedNode.lnImplementation && req.session.selectedNode.lnImplementation.toUpperCase() === 'LND') ? 'GET' : 'POST';
|
||||
delete req.session.selectedNode.authentication.options.form;
|
||||
delete req.session.selectedNode.authentication.options.body;
|
||||
req.session.selectedNode.authentication.options.qs = {};
|
||||
return req.session.selectedNode.authentication.options;
|
||||
}
|
||||
return this.handleError({ statusCode: 401, message: 'Session expired after a day\'s inactivity' }, 'Session Expired', 'Session Expiry Error', this.initSelectedNode);
|
||||
return this.handleError({ statusCode: 401, message: 'Session expired after a day\'s inactivity' }, 'Session Expired', 'Session Expiry Error', this.selectedNode);
|
||||
};
|
||||
|
||||
public updateSelectedNodeOptions = (req) => {
|
||||
if (!req.session.selectedNode) {
|
||||
req.session.selectedNode = {};
|
||||
}
|
||||
req.session.selectedNode.options = {
|
||||
req.session.selectedNode.authentication.options = {
|
||||
url: '',
|
||||
rejectUnauthorized: false,
|
||||
json: true,
|
||||
form: null
|
||||
};
|
||||
try {
|
||||
if (req.session.selectedNode && req.session.selectedNode.ln_implementation) {
|
||||
switch (req.session.selectedNode.ln_implementation.toUpperCase()) {
|
||||
if (req.session.selectedNode && req.session.selectedNode.lnImplementation) {
|
||||
switch (req.session.selectedNode.lnImplementation.toUpperCase()) {
|
||||
case 'CLN':
|
||||
try {
|
||||
if (!req.session.selectedNode.rune_value) {
|
||||
req.session.selectedNode.rune_value = this.getRuneValue(req.session.selectedNode.rune_path);
|
||||
if (!req.session.selectedNode.authentication.runeValue) {
|
||||
req.session.selectedNode.authentication.runeValue = this.getRuneValue(req.session.selectedNode.authentication.runePath);
|
||||
}
|
||||
req.session.selectedNode.options.headers = { rune: req.session.selectedNode.rune_value };
|
||||
req.session.selectedNode.authentication.options.headers = { rune: req.session.selectedNode.authentication.runeValue };
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ECL':
|
||||
req.session.selectedNode.options.headers = { authorization: 'Basic ' + Buffer.from(':' + req.session.selectedNode.ln_api_password).toString('base64') };
|
||||
req.session.selectedNode.authentication.options.headers = { authorization: 'Basic ' + Buffer.from(':' + req.session.selectedNode.authentication.lnApiPassword).toString('base64') };
|
||||
break;
|
||||
|
||||
default:
|
||||
req.session.selectedNode.options.headers = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(req.session.selectedNode.macaroon_path, 'admin.macaroon')).toString('hex') };
|
||||
req.session.selectedNode.authentication.options.headers = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(req.session.selectedNode.authentication.macaroonPath, 'admin.macaroon')).toString('hex') };
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (req.session.selectedNode) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Updated Node Options for ' + req.session.selectedNode.ln_node, data: req.session.selectedNode.options });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Updated Node Options for ' + req.session.selectedNode.lnNode, data: req.session.selectedNode.authentication.options });
|
||||
}
|
||||
return { status: 200, message: 'Updated Successfully' };
|
||||
} catch (err) {
|
||||
req.session.selectedNode.options = {
|
||||
req.session.selectedNode.authentication.options = {
|
||||
url: '',
|
||||
rejectUnauthorized: false,
|
||||
json: true,
|
||||
form: null
|
||||
};
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Update Selected Node Options Error', error: err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Update Selected Node Options Error', error: err });
|
||||
return { status: 502, message: err };
|
||||
}
|
||||
};
|
||||
|
|
@ -144,48 +202,48 @@ export class CommonService {
|
|||
};
|
||||
|
||||
public setOptions = (req) => {
|
||||
if (this.nodes[0].options && this.nodes[0].options.headers) { return; }
|
||||
if (this.nodes[0].authentication.options && this.nodes[0].authentication.options.headers) { return; }
|
||||
if (this.nodes && this.nodes.length > 0) {
|
||||
this.nodes.forEach((node) => {
|
||||
node.options = {
|
||||
node.authentication.options = {
|
||||
url: '',
|
||||
rejectUnauthorized: false,
|
||||
json: true,
|
||||
form: null
|
||||
};
|
||||
try {
|
||||
if (node.ln_implementation) {
|
||||
switch (node.ln_implementation.toUpperCase()) {
|
||||
if (node.lnImplementation) {
|
||||
switch (node.lnImplementation.toUpperCase()) {
|
||||
case 'CLN':
|
||||
try {
|
||||
if (!node.rune_value) {
|
||||
node.rune_value = this.getRuneValue(node.rune_path);
|
||||
if (!node.authentication.runeValue) {
|
||||
node.authentication.runeValue = this.getRuneValue(node.authentication.runePath);
|
||||
}
|
||||
node.options.headers = { rune: node.rune_value };
|
||||
node.authentication.options.headers = { rune: node.authentication.runeValue };
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ECL':
|
||||
node.options.headers = { authorization: 'Basic ' + Buffer.from(':' + node.ln_api_password).toString('base64') };
|
||||
node.authentication.options.headers = { authorization: 'Basic ' + Buffer.from(':' + node.authentication.lnApiPassword).toString('base64') };
|
||||
break;
|
||||
|
||||
default:
|
||||
node.options.headers = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(node.macaroon_path, 'admin.macaroon')).toString('hex') };
|
||||
node.authentication.options.headers = { 'Grpc-Metadata-macaroon': fs.readFileSync(join(node.authentication.macaroonPath, 'admin.macaroon')).toString('hex') };
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Common Set Options Error', error: err });
|
||||
node.options = {
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Common Set Options Error', error: err });
|
||||
node.authentication.options = {
|
||||
url: '',
|
||||
rejectUnauthorized: false,
|
||||
json: true,
|
||||
form: ''
|
||||
};
|
||||
}
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Set Node Options for ' + node.ln_node, data: node.options });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Set Node Options for ' + node.lnNode, data: node.authentication.options });
|
||||
});
|
||||
this.updateSelectedNodeOptions(req);
|
||||
}
|
||||
|
|
@ -264,17 +322,10 @@ export class CommonService {
|
|||
}
|
||||
};
|
||||
|
||||
public handleError = (errRes, fileName, errMsg, selectedNode: CommonSelectedNode) => {
|
||||
let err = JSON.parse(JSON.stringify(errRes));
|
||||
if (err && err.error && Object.keys(err.error).length === 0 && errRes.error && (errRes.error.stack || errRes.error.message)) {
|
||||
errRes.error = errRes.error.stack || errRes.error.message;
|
||||
err = JSON.parse(JSON.stringify(errRes));
|
||||
} else if (errRes.message || errRes.stack) {
|
||||
errRes.error = errRes.message || errRes.stack;
|
||||
err = JSON.parse(JSON.stringify(errRes));
|
||||
}
|
||||
if (!selectedNode) { selectedNode = this.initSelectedNode; }
|
||||
switch (selectedNode.ln_implementation) {
|
||||
public handleError = (errRes, fileName, errMsg, selectedNode: SelectedNode) => {
|
||||
const err = JSON.parse(JSON.stringify(errRes));
|
||||
if (!selectedNode) { selectedNode = this.selectedNode; }
|
||||
switch (selectedNode.lnImplementation) {
|
||||
case 'LND':
|
||||
if (err.options && err.options.headers && err.options.headers['Grpc-Metadata-macaroon']) {
|
||||
delete err.options.headers['Grpc-Metadata-macaroon'];
|
||||
|
|
@ -285,11 +336,11 @@ export class CommonService {
|
|||
break;
|
||||
|
||||
case 'CLN':
|
||||
if (err.options && err.options.headers && err.options.headers.macaroon) {
|
||||
delete err.options.headers.macaroon;
|
||||
if (err.options && err.options.headers && err.options.headers.rune) {
|
||||
delete err.options.headers.rune;
|
||||
}
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.macaroon) {
|
||||
delete err.response.request.headers.macaroon;
|
||||
if (err.response && err.response.request && err.response.request.headers && err.response.request.headers.rune) {
|
||||
delete err.response.request.headers.rune;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -328,7 +379,7 @@ export class CommonService {
|
|||
)
|
||||
};
|
||||
}
|
||||
if (selectedNode.ln_implementation === 'ECL' && err.message && err.message.indexOf('Authentication Error') < 0 && err.name && err.name === 'StatusCodeError') { newErrorObj.statusCode = 500; }
|
||||
if (selectedNode.lnImplementation === 'ECL' && err.message && err.message.indexOf('Authentication Error') < 0 && err.name && err.name === 'StatusCodeError') { newErrorObj.statusCode = 500; }
|
||||
return newErrorObj;
|
||||
};
|
||||
|
||||
|
|
@ -339,15 +390,15 @@ export class CommonService {
|
|||
(req.connection.socket ? req.connection.socket.remoteAddress : null));
|
||||
|
||||
public getDummyData = (dataKey, lnImplementation) => {
|
||||
const dummyDataFile = this.rtl_conf_file_path + sep + 'ECLDummyData.log';
|
||||
const dummyDataFile = this.appConfig.rtlConfFilePath + sep + 'ECLDummyData.log';
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.dummy_data_array_from_file.length === 0) {
|
||||
fs.readFile(dummyDataFile, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Dummy data file does not exist' });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Dummy data file does not exist' });
|
||||
} else {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Getting dummy data failed' });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Getting dummy data failed' });
|
||||
}
|
||||
} else {
|
||||
this.dummy_data_array_from_file = data.split('\n');
|
||||
|
|
@ -361,22 +412,22 @@ export class CommonService {
|
|||
};
|
||||
|
||||
public readCookie = () => {
|
||||
const exists = fs.existsSync(this.rtl_cookie_path);
|
||||
const exists = fs.existsSync(this.appConfig.SSO.rtlCookiePath);
|
||||
if (exists) {
|
||||
try {
|
||||
this.cookie_value = fs.readFileSync(this.rtl_cookie_path, 'utf-8');
|
||||
this.appConfig.SSO.cookieValue = fs.readFileSync(this.appConfig.SSO.rtlCookiePath, 'utf-8');
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Something went wrong while reading cookie: \n' + err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Something went wrong while reading cookie: \n' + err });
|
||||
throw new Error(err);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const directoryName = dirname(this.rtl_cookie_path);
|
||||
const directoryName = dirname(this.appConfig.SSO.rtlCookiePath);
|
||||
this.createDirectory(directoryName);
|
||||
fs.writeFileSync(this.rtl_cookie_path, crypto.randomBytes(64).toString('hex'));
|
||||
this.cookie_value = fs.readFileSync(this.rtl_cookie_path, 'utf-8');
|
||||
fs.writeFileSync(this.appConfig.SSO.rtlCookiePath, crypto.randomBytes(64).toString('hex'));
|
||||
this.appConfig.SSO.cookieValue = fs.readFileSync(this.appConfig.SSO.rtlCookiePath, 'utf-8');
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Something went wrong while reading the cookie: \n' + err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Something went wrong while reading the cookie: \n' + err });
|
||||
throw new Error(err);
|
||||
}
|
||||
}
|
||||
|
|
@ -384,10 +435,10 @@ export class CommonService {
|
|||
|
||||
public refreshCookie = () => {
|
||||
try {
|
||||
fs.writeFileSync(this.rtl_cookie_path, crypto.randomBytes(64).toString('hex'));
|
||||
this.cookie_value = fs.readFileSync(this.rtl_cookie_path, 'utf-8');
|
||||
fs.writeFileSync(this.appConfig.SSO.rtlCookiePath, crypto.randomBytes(64).toString('hex'));
|
||||
this.appConfig.SSO.cookieValue = fs.readFileSync(this.appConfig.SSO.rtlCookiePath, 'utf-8');
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Something went wrong while refreshing cookie', error: err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Something went wrong while refreshing cookie', error: err });
|
||||
throw new Error(err);
|
||||
}
|
||||
};
|
||||
|
|
@ -414,47 +465,47 @@ export class CommonService {
|
|||
};
|
||||
|
||||
public replacePasswordWithHash = (multiPassHashed) => {
|
||||
this.rtl_conf_file_path = process.env.RTL_CONFIG_PATH ? process.env.RTL_CONFIG_PATH : join(dirname(fileURLToPath(import.meta.url)), '../..');
|
||||
this.appConfig.rtlConfFilePath = process.env.RTL_CONFIG_PATH ? process.env.RTL_CONFIG_PATH : join(dirname(fileURLToPath(import.meta.url)), '../..');
|
||||
try {
|
||||
const RTLConfFile = this.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
const RTLConfFile = this.appConfig.rtlConfFilePath + sep + 'RTL-Config.json';
|
||||
const config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
|
||||
config.multiPassHashed = multiPassHashed;
|
||||
delete config.multiPass;
|
||||
fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Please note that, RTL has encrypted the plaintext password into its corresponding hash' });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Please note that, RTL has encrypted the plaintext password into its corresponding hash' });
|
||||
return config.multiPassHashed;
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Password hashing failed', error: err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Password hashing failed', error: err });
|
||||
}
|
||||
};
|
||||
|
||||
public getAllNodeAllChannelBackup = (node: CommonSelectedNode) => {
|
||||
const channel_backup_file = node.channel_backup_path + sep + 'channel-all.bak';
|
||||
public getAllNodeAllChannelBackup = (node: SelectedNode) => {
|
||||
const channel_backup_file = node.settings.channelBackupPath + sep + 'channel-all.bak';
|
||||
const options = {
|
||||
url: node.ln_server_url + '/v1/channels/backup',
|
||||
url: node.settings.lnServerUrl + '/v1/channels/backup',
|
||||
rejectUnauthorized: false,
|
||||
json: true,
|
||||
headers: { 'Grpc-Metadata-macaroon': fs.readFileSync(node.macaroon_path + '/admin.macaroon').toString('hex') }
|
||||
headers: { 'Grpc-Metadata-macaroon': fs.readFileSync(node.authentication.macaroonPath + '/admin.macaroon').toString('hex') }
|
||||
};
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Getting Channel Backup for Node ' + node.ln_node + '..' });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Getting Channel Backup for Node ' + node.lnNode + '..' });
|
||||
request(options).then((body) => {
|
||||
fs.writeFile(channel_backup_file, JSON.stringify(body), (err) => {
|
||||
if (err) {
|
||||
if (node.ln_node) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Error in Channel Backup for Node ' + node.ln_node, error: err });
|
||||
if (node.lnNode) {
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Error in Channel Backup for Node ' + node.lnNode, error: err });
|
||||
} else {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Error in Channel Backup for File ' + channel_backup_file, error: err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Error in Channel Backup for File ' + channel_backup_file, error: err });
|
||||
}
|
||||
} else {
|
||||
if (node.ln_node) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Successful in Channel Backup for Node ' + node.ln_node, data: body });
|
||||
if (node.lnNode) {
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Successful in Channel Backup for Node ' + node.lnNode, data: body });
|
||||
} else {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Successful in Channel Backup for File ' + channel_backup_file, data: body });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Successful in Channel Backup for File ' + channel_backup_file, data: body });
|
||||
}
|
||||
}
|
||||
});
|
||||
}, (err) => {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Error in Channel Backup for Node ' + node.ln_node, error: err });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Error in Channel Backup for Node ' + node.lnNode, error: err });
|
||||
fs.writeFile(channel_backup_file, '', () => { });
|
||||
});
|
||||
};
|
||||
|
|
@ -465,8 +516,8 @@ export class CommonService {
|
|||
const pattern = /v?(\d+(\.\d+)*)/;
|
||||
const match = currentVersion.match(pattern);
|
||||
if (match && match.length && match.length > 1) {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Global Version ' + match[1] });
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'INFO', fileName: 'Common', msg: 'Checking Compatiblility with Version ' + checkVersion });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Global Version ' + match[1] });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'INFO', fileName: 'Common', msg: 'Checking Compatiblility with Version ' + checkVersion });
|
||||
const currentVersionArr = match[1].split('.') || [];
|
||||
currentVersionArr[1] = currentVersionArr[1].substring(0, 2);
|
||||
const checkVersionsArr = checkVersion.split('.');
|
||||
|
|
@ -475,7 +526,7 @@ export class CommonService {
|
|||
(+currentVersionArr[0] === +checkVersionsArr[0] && +currentVersionArr[1] > +checkVersionsArr[1]) ||
|
||||
(+currentVersionArr[0] === +checkVersionsArr[0] && +currentVersionArr[1] === +checkVersionsArr[1] && +currentVersionArr[2] >= +checkVersionsArr[2]);
|
||||
} else {
|
||||
this.logger.log({ selectedNode: this.initSelectedNode, level: 'ERROR', fileName: 'Common', msg: 'Invalid Version String ' + currentVersion });
|
||||
this.logger.log({ selectedNode: this.selectedNode, level: 'ERROR', fileName: 'Common', msg: 'Invalid Version String ' + currentVersion });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -485,20 +536,10 @@ export class CommonService {
|
|||
public getMonthDays = (selMonth, selYear) => ((selMonth === 1 && selYear % 4 === 0) ? (this.MONTHS[selMonth].days + 1) : this.MONTHS[selMonth].days);
|
||||
|
||||
public logEnvVariables = (req) => {
|
||||
const selNode = <CommonSelectedNode>req.session.selectedNode;
|
||||
const selNode = <SelectedNode>req.session.selectedNode;
|
||||
if (selNode && selNode.index) {
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'PORT: ' + this.port });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'HOST: ' + this.host });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'DB_DIRECTORY_PATH: ' + this.db_directory_path });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'SSO: ' + this.rtl_sso });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'DEFAULT NODE INDEX: ' + selNode.index });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'INDEX: ' + selNode.index });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN NODE: ' + selNode.ln_node });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN IMPLEMENTATION: ' + selNode.ln_implementation });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'FIAT CONVERSION: ' + selNode.fiat_conversion });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'CURRENCY UNIT: ' + selNode.currency_unit });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LN SERVER URL: ' + selNode.ln_server_url });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'LOGOUT REDIRECT LINK: ' + this.logout_redirect_link + '\r\n' });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup:', msg: JSON.stringify(this.removeSecureData(JSON.parse(JSON.stringify(this.appConfig)))) });
|
||||
this.logger.log({ selectedNode: selNode, level: 'INFO', fileName: 'Config Setup Variable', msg: 'SSO: ' + this.appConfig.SSO.rtlSso });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -67,11 +67,11 @@ export class ConfigService {
|
|||
index: 1,
|
||||
lnNode: 'Node 1',
|
||||
lnImplementation: 'LND',
|
||||
Authentication: {
|
||||
authentication: {
|
||||
macaroonPath: macaroonPath,
|
||||
configPath: configPath
|
||||
},
|
||||
Settings: {
|
||||
settings: {
|
||||
userPersona: 'MERCHANT',
|
||||
themeMode: 'DAY',
|
||||
themeColor: 'PURPLE',
|
||||
|
|
@ -79,7 +79,8 @@ export class ConfigService {
|
|||
logLevel: 'ERROR',
|
||||
lnServerUrl: 'https://127.0.0.1:8080',
|
||||
fiatConversion: false,
|
||||
unannouncedChannels: false
|
||||
unannouncedChannels: false,
|
||||
blockExplorerUrl: 'https://mempool.space'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -103,15 +104,15 @@ export class ConfigService {
|
|||
|
||||
private updateLogByLevel = () => {
|
||||
let updateLogFlag = false;
|
||||
this.common.rtl_conf_file_path = process?.env?.RTL_CONFIG_PATH ? process?.env?.RTL_CONFIG_PATH : join(this.directoryName, '../..');
|
||||
this.common.appConfig.rtlConfFilePath = process?.env?.RTL_CONFIG_PATH ? process?.env?.RTL_CONFIG_PATH : join(this.directoryName, '../..');
|
||||
try {
|
||||
const RTLConfFile = this.common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
const RTLConfFile = this.common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json';
|
||||
const config = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
|
||||
config.nodes.forEach((node) => {
|
||||
if (node.Settings.hasOwnProperty('enableLogging')) {
|
||||
if (node.settings.hasOwnProperty('enableLogging')) {
|
||||
updateLogFlag = true;
|
||||
node.Settings.logLevel = node.Settings.enableLogging ? 'INFO' : 'ERROR';
|
||||
delete node.Settings.enableLogging;
|
||||
node.settings.logLevel = node.settings.enableLogging ? 'INFO' : 'ERROR';
|
||||
delete node.settings.enableLogging;
|
||||
}
|
||||
});
|
||||
if (updateLogFlag) {
|
||||
|
|
@ -123,18 +124,19 @@ export class ConfigService {
|
|||
};
|
||||
|
||||
private validateNodeConfig = (config) => {
|
||||
config.allowPasswordUpdate = true;
|
||||
if ((process?.env?.RTL_SSO && +process?.env?.RTL_SSO === 0) || (typeof process?.env?.RTL_SSO === 'undefined' && +config.SSO.rtlSSO === 0)) {
|
||||
if (process?.env?.APP_PASSWORD && process?.env?.APP_PASSWORD.trim() !== '') {
|
||||
this.common.rtl_pass = this.hash.update(process?.env?.APP_PASSWORD).digest('hex');
|
||||
this.common.flg_allow_password_update = false;
|
||||
config.rtlPass = this.hash.update(process?.env?.APP_PASSWORD).digest('hex');
|
||||
config.allowPasswordUpdate = false;
|
||||
} else if (config.multiPassHashed && config.multiPassHashed !== '') {
|
||||
this.common.rtl_pass = config.multiPassHashed;
|
||||
config.rtlPass = config.multiPassHashed;
|
||||
} else if (config.multiPass && config.multiPass !== '') {
|
||||
this.common.rtl_pass = this.common.replacePasswordWithHash(this.hash.update(config.multiPass).digest('hex'));
|
||||
config.rtlPass = this.common.replacePasswordWithHash(this.hash.update(config.multiPass).digest('hex'));
|
||||
} else {
|
||||
this.errMsg = this.errMsg + '\nNode Authentication can be set with multiPass only. Please set multiPass in RTL-Config.json';
|
||||
}
|
||||
this.common.rtl_secret2fa = config.secret2fa;
|
||||
config.enable2FA = !!config.secret2FA;
|
||||
} else {
|
||||
if (process?.env?.APP_PASSWORD && process?.env?.APP_PASSWORD.trim() !== '') {
|
||||
this.errMsg = this.errMsg + '\nRTL Password cannot be set with SSO. Please set SSO as 0 or remove password.';
|
||||
|
|
@ -142,20 +144,20 @@ export class ConfigService {
|
|||
}
|
||||
this.common.port = (process?.env?.PORT) ? this.normalizePort(process?.env?.PORT) : (config.port) ? this.normalizePort(config.port) : 3000;
|
||||
this.common.host = (process?.env?.HOST) ? process?.env?.HOST : (config.host) ? config.host : null;
|
||||
this.common.db_directory_path = (process?.env?.DB_DIRECTORY_PATH) ? process?.env?.DB_DIRECTORY_PATH : (config.dbDirectoryPath) ? config.dbDirectoryPath : join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
||||
config.dbDirectoryPath = (process?.env?.DB_DIRECTORY_PATH) ? process?.env?.DB_DIRECTORY_PATH : (config.dbDirectoryPath) ? config.dbDirectoryPath : join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
||||
if (config.nodes && config.nodes.length > 0) {
|
||||
config.nodes.forEach((node, idx) => {
|
||||
this.common.nodes[idx] = {};
|
||||
this.common.nodes[idx] = { settings: { blockExplorerUrl: '' }, authentication: {} };
|
||||
this.common.nodes[idx].index = node.index;
|
||||
this.common.nodes[idx].ln_node = node.lnNode;
|
||||
this.common.nodes[idx].ln_implementation = (process?.env?.LN_IMPLEMENTATION) ? process?.env?.LN_IMPLEMENTATION : node.lnImplementation ? node.lnImplementation : 'LND';
|
||||
if (this.common.nodes[idx].ln_implementation === 'CLT') { this.common.nodes[idx].ln_implementation = 'CLN'; }
|
||||
switch (this.common.nodes[idx].ln_implementation) {
|
||||
this.common.nodes[idx].lnNode = node.lnNode;
|
||||
this.common.nodes[idx].lnImplementation = (process?.env?.lnImplementation) ? process?.env?.lnImplementation : node.lnImplementation ? node.lnImplementation : 'LND';
|
||||
if (this.common.nodes[idx].lnImplementation === 'CLT') { this.common.nodes[idx].lnImplementation = 'CLN'; }
|
||||
switch (this.common.nodes[idx].lnImplementation) {
|
||||
case 'CLN':
|
||||
if (process?.env?.RUNE_PATH && process?.env?.RUNE_PATH.trim() !== '') {
|
||||
this.common.nodes[idx].rune_path = process?.env?.RUNE_PATH;
|
||||
} else if (node.Authentication && node.Authentication.runePath && node.Authentication.runePath.trim() !== '') {
|
||||
this.common.nodes[idx].rune_path = node.Authentication.runePath;
|
||||
this.common.nodes[idx].authentication.runePath = process?.env?.RUNE_PATH;
|
||||
} else if (node.authentication && node.authentication.runePath && node.authentication.runePath.trim() !== '') {
|
||||
this.common.nodes[idx].authentication.runePath = node.authentication.runePath;
|
||||
} else {
|
||||
this.errMsg = 'Please set rune path for node index ' + node.index + ' in RTL-Config.json!';
|
||||
}
|
||||
|
|
@ -163,118 +165,119 @@ export class ConfigService {
|
|||
|
||||
case 'ECL':
|
||||
if (process?.env?.LN_API_PASSWORD) {
|
||||
this.common.nodes[idx].ln_api_password = process?.env?.LN_API_PASSWORD;
|
||||
} else if (node.Authentication && node.Authentication.lnApiPassword) {
|
||||
this.common.nodes[idx].ln_api_password = node.Authentication.lnApiPassword;
|
||||
this.common.nodes[idx].authentication.lnApiPassword = process?.env?.LN_API_PASSWORD;
|
||||
} else if (node.authentication && node.authentication.lnApiPassword) {
|
||||
this.common.nodes[idx].authentication.lnApiPassword = node.authentication.lnApiPassword;
|
||||
} else {
|
||||
this.common.nodes[idx].ln_api_password = '';
|
||||
this.common.nodes[idx].authentication.lnApiPassword = '';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (process?.env?.MACAROON_PATH && process?.env?.MACAROON_PATH.trim() !== '') {
|
||||
this.common.nodes[idx].macaroon_path = process?.env?.MACAROON_PATH;
|
||||
} else if (node.Authentication && node.Authentication.macaroonPath && node.Authentication.macaroonPath.trim() !== '') {
|
||||
this.common.nodes[idx].macaroon_path = node.Authentication.macaroonPath;
|
||||
this.common.nodes[idx].authentication.macaroonPath = process?.env?.MACAROON_PATH;
|
||||
} else if (node.authentication && node.authentication.macaroonPath && node.authentication.macaroonPath.trim() !== '') {
|
||||
this.common.nodes[idx].authentication.macaroonPath = node.authentication.macaroonPath;
|
||||
} else {
|
||||
this.errMsg = 'Please set macaroon path for node index ' + node.index + ' in RTL-Config.json!';
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (process?.env?.CONFIG_PATH) {
|
||||
this.common.nodes[idx].config_path = process?.env?.CONFIG_PATH;
|
||||
} else if (node.Authentication && node.Authentication.configPath) {
|
||||
this.common.nodes[idx].config_path = node.Authentication.configPath;
|
||||
this.common.nodes[idx].authentication.configPath = process?.env?.CONFIG_PATH;
|
||||
} else if (node.authentication && node.authentication.configPath) {
|
||||
this.common.nodes[idx].authentication.configPath = node.authentication.configPath;
|
||||
} else {
|
||||
this.common.nodes[idx].config_path = '';
|
||||
this.common.nodes[idx].authentication.configPath = '';
|
||||
}
|
||||
if (this.common.nodes[idx].ln_implementation === 'ECL' && this.common.nodes[idx].ln_api_password === '' && this.common.nodes[idx].config_path !== '') {
|
||||
if (this.common.nodes[idx].lnImplementation === 'ECL' && this.common.nodes[idx].authentication.lnApiPassword === '' && this.common.nodes[idx].authentication.configPath !== '') {
|
||||
try {
|
||||
const exists = fs.existsSync(this.common.nodes[idx].config_path || '');
|
||||
const exists = fs.existsSync(this.common.nodes[idx].authentication.configPath || '');
|
||||
if (exists) {
|
||||
try {
|
||||
const configFile = fs.readFileSync((this.common.nodes[idx].config_path || ''), 'utf-8');
|
||||
const configFile = fs.readFileSync((this.common.nodes[idx].authentication.configPath || ''), 'utf-8');
|
||||
const iniParsed = ini.parse(configFile);
|
||||
this.common.nodes[idx].ln_api_password = iniParsed['eclair.api.password'] ? iniParsed['eclair.api.password'] : parseHocon(configFile).eclair.api.password;
|
||||
this.common.nodes[idx].authentication.lnApiPassword = iniParsed['eclair.api.password'] ? iniParsed['eclair.api.password'] : parseHocon(configFile).eclair.api.password;
|
||||
} catch (err) {
|
||||
this.errMsg = this.errMsg + '\nSomething went wrong while reading config file: \n' + err;
|
||||
}
|
||||
} else {
|
||||
this.errMsg = this.errMsg + '\nInvalid config path: ' + this.common.nodes[idx].config_path;
|
||||
this.errMsg = this.errMsg + '\nInvalid config path: ' + this.common.nodes[idx].authentication.configPath;
|
||||
}
|
||||
} catch (err) {
|
||||
this.errMsg = this.errMsg + '\nUnable to read config file: \n' + err;
|
||||
}
|
||||
}
|
||||
if (this.common.nodes[idx].ln_implementation === 'ECL' && this.common.nodes[idx].ln_api_password === '') {
|
||||
if (this.common.nodes[idx].lnImplementation === 'ECL' && this.common.nodes[idx].authentication.lnApiPassword === '') {
|
||||
this.errMsg = this.errMsg + '\nPlease set config path Or api password for node index ' + node.index + ' in RTL-Config.json! It is mandatory for Eclair authentication!';
|
||||
}
|
||||
|
||||
if (process?.env?.LN_SERVER_URL && process?.env?.LN_SERVER_URL.trim() !== '') {
|
||||
this.common.nodes[idx].ln_server_url = process?.env?.LN_SERVER_URL.endsWith('/v1') ? process?.env?.LN_SERVER_URL.slice(0, -3) : process?.env?.LN_SERVER_URL;
|
||||
this.common.nodes[idx].settings.lnServerUrl = process?.env?.LN_SERVER_URL.endsWith('/v1') ? process?.env?.LN_SERVER_URL.slice(0, -3) : process?.env?.LN_SERVER_URL;
|
||||
} else if (process?.env?.LND_SERVER_URL && process?.env?.LND_SERVER_URL.trim() !== '') {
|
||||
this.common.nodes[idx].ln_server_url = process?.env?.LND_SERVER_URL.endsWith('/v1') ? process?.env?.LND_SERVER_URL.slice(0, -3) : process?.env?.LND_SERVER_URL;
|
||||
} else if (node.Settings.lnServerUrl && node.Settings.lnServerUrl.trim() !== '') {
|
||||
this.common.nodes[idx].ln_server_url = node.Settings.lnServerUrl.endsWith('/v1') ? node.Settings.lnServerUrl.slice(0, -3) : node.Settings.lnServerUrl;
|
||||
} else if (node.Settings.lndServerUrl && node.Settings.lndServerUrl.trim() !== '') {
|
||||
this.common.nodes[idx].ln_server_url = node.Settings.lndServerUrl.endsWith('/v1') ? node.Settings.lndServerUrl.slice(0, -3) : node.Settings.lndServerUrl;
|
||||
this.common.nodes[idx].settings.lnServerUrl = process?.env?.LND_SERVER_URL.endsWith('/v1') ? process?.env?.LND_SERVER_URL.slice(0, -3) : process?.env?.LND_SERVER_URL;
|
||||
} else if (node.settings.lnServerUrl && node.settings.lnServerUrl.trim() !== '') {
|
||||
this.common.nodes[idx].settings.lnServerUrl = node.settings.lnServerUrl.endsWith('/v1') ? node.settings.lnServerUrl.slice(0, -3) : node.settings.lnServerUrl;
|
||||
} else if (node.settings.lndServerUrl && node.settings.lndServerUrl.trim() !== '') {
|
||||
this.common.nodes[idx].settings.lnServerUrl = node.settings.lndServerUrl.endsWith('/v1') ? node.settings.lndServerUrl.slice(0, -3) : node.settings.lndServerUrl;
|
||||
} else {
|
||||
this.errMsg = this.errMsg + '\nPlease set LN Server URL for node index ' + node.index + ' in RTL-Config.json!';
|
||||
}
|
||||
this.common.nodes[idx].user_persona = node.Settings.userPersona ? node.Settings.userPersona : 'MERCHANT';
|
||||
this.common.nodes[idx].theme_mode = node.Settings.themeMode ? node.Settings.themeMode : 'DAY';
|
||||
this.common.nodes[idx].theme_color = node.Settings.themeColor ? node.Settings.themeColor : 'PURPLE';
|
||||
this.common.nodes[idx].unannounced_channels = node.Settings.unannouncedChannels ? !!node.Settings.unannouncedChannels : false;
|
||||
this.common.nodes[idx].log_level = node.Settings.logLevel ? node.Settings.logLevel : 'ERROR';
|
||||
this.common.nodes[idx].fiat_conversion = node.Settings.fiatConversion ? !!node.Settings.fiatConversion : false;
|
||||
if (this.common.nodes[idx].fiat_conversion) {
|
||||
this.common.nodes[idx].currency_unit = node.Settings.currencyUnit ? node.Settings.currencyUnit : 'USD';
|
||||
this.common.nodes[idx].settings.userPersona = node.settings.userPersona ? node.settings.userPersona : 'MERCHANT';
|
||||
this.common.nodes[idx].settings.themeMode = node.settings.themeMode ? node.settings.themeMode : 'DAY';
|
||||
this.common.nodes[idx].settings.themeColor = node.settings.themeColor ? node.settings.themeColor : 'PURPLE';
|
||||
this.common.nodes[idx].settings.unannouncedChannels = node.settings.unannouncedChannels ? !!node.settings.unannouncedChannels : false;
|
||||
this.common.nodes[idx].settings.logLevel = node.settings.logLevel ? node.settings.logLevel : 'ERROR';
|
||||
this.common.nodes[idx].settings.fiatConversion = node.settings.fiatConversion ? !!node.settings.fiatConversion : false;
|
||||
if (this.common.nodes[idx].settings.fiatConversion) {
|
||||
this.common.nodes[idx].settings.currencyUnit = node.settings.currencyUnit ? node.settings.currencyUnit : 'USD';
|
||||
}
|
||||
if (process?.env?.SWAP_SERVER_URL && process?.env?.SWAP_SERVER_URL.trim() !== '') {
|
||||
this.common.nodes[idx].swap_server_url = process?.env?.SWAP_SERVER_URL.endsWith('/v1') ? process?.env?.SWAP_SERVER_URL.slice(0, -3) : process?.env?.SWAP_SERVER_URL;
|
||||
this.common.nodes[idx].swap_macaroon_path = process?.env?.SWAP_MACAROON_PATH;
|
||||
} else if (node.Settings.swapServerUrl && node.Settings.swapServerUrl.trim() !== '') {
|
||||
this.common.nodes[idx].swap_server_url = node.Settings.swapServerUrl.endsWith('/v1') ? node.Settings.swapServerUrl.slice(0, -3) : node.Settings.swapServerUrl;
|
||||
this.common.nodes[idx].swap_macaroon_path = node.Authentication.swapMacaroonPath ? node.Authentication.swapMacaroonPath : '';
|
||||
this.common.nodes[idx].settings.swapServerUrl = process?.env?.SWAP_SERVER_URL.endsWith('/v1') ? process?.env?.SWAP_SERVER_URL.slice(0, -3) : process?.env?.SWAP_SERVER_URL;
|
||||
this.common.nodes[idx].authentication.swapMacaroonPath = process?.env?.SWAP_MACAROON_PATH;
|
||||
} else if (node.settings.swapServerUrl && node.settings.swapServerUrl.trim() !== '') {
|
||||
this.common.nodes[idx].settings.swapServerUrl = node.settings.swapServerUrl.endsWith('/v1') ? node.settings.swapServerUrl.slice(0, -3) : node.settings.swapServerUrl;
|
||||
this.common.nodes[idx].authentication.swapMacaroonPath = node.authentication.swapMacaroonPath ? node.authentication.swapMacaroonPath : '';
|
||||
} else {
|
||||
this.common.nodes[idx].swap_server_url = '';
|
||||
this.common.nodes[idx].swap_macaroon_path = '';
|
||||
this.common.nodes[idx].settings.swapServerUrl = '';
|
||||
this.common.nodes[idx].authentication.swapMacaroonPath = '';
|
||||
}
|
||||
if (process?.env?.BOLTZ_SERVER_URL && process?.env?.BOLTZ_SERVER_URL.trim() !== '') {
|
||||
this.common.nodes[idx].boltz_server_url = process?.env?.BOLTZ_SERVER_URL.endsWith('/v1') ? process?.env?.BOLTZ_SERVER_URL.slice(0, -3) : process?.env?.BOLTZ_SERVER_URL;
|
||||
this.common.nodes[idx].boltz_macaroon_path = process?.env?.BOLTZ_MACAROON_PATH;
|
||||
} else if (node.Settings.boltzServerUrl && node.Settings.boltzServerUrl.trim() !== '') {
|
||||
this.common.nodes[idx].boltz_server_url = node.Settings.boltzServerUrl.endsWith('/v1') ? node.Settings.boltzServerUrl.slice(0, -3) : node.Settings.boltzServerUrl;
|
||||
this.common.nodes[idx].boltz_macaroon_path = node.Authentication.boltzMacaroonPath ? node.Authentication.boltzMacaroonPath : '';
|
||||
this.common.nodes[idx].settings.boltzServerUrl = process?.env?.BOLTZ_SERVER_URL.endsWith('/v1') ? process?.env?.BOLTZ_SERVER_URL.slice(0, -3) : process?.env?.BOLTZ_SERVER_URL;
|
||||
this.common.nodes[idx].authentication.boltzMacaroonPath = process?.env?.BOLTZ_MACAROON_PATH;
|
||||
} else if (node.settings.boltzServerUrl && node.settings.boltzServerUrl.trim() !== '') {
|
||||
this.common.nodes[idx].settings.boltzServerUrl = node.settings.boltzServerUrl.endsWith('/v1') ? node.settings.boltzServerUrl.slice(0, -3) : node.settings.boltzServerUrl;
|
||||
this.common.nodes[idx].authentication.boltzMacaroonPath = node.authentication.boltzMacaroonPath ? node.authentication.boltzMacaroonPath : '';
|
||||
} else {
|
||||
this.common.nodes[idx].boltz_server_url = '';
|
||||
this.common.nodes[idx].boltz_macaroon_path = '';
|
||||
this.common.nodes[idx].settings.boltzServerUrl = '';
|
||||
this.common.nodes[idx].authentication.boltzMacaroonPath = '';
|
||||
}
|
||||
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;
|
||||
this.common.nodes[idx].settings.enableOffers = process?.env?.ENABLE_OFFERS ? process?.env?.ENABLE_OFFERS : (node.settings.enableOffers) ? node.settings.enableOffers : false;
|
||||
this.common.nodes[idx].settings.enablePeerswap = process?.env?.ENABLE_PEERSWAP ? process?.env?.ENABLE_PEERSWAP : (node.settings.enablePeerswap) ? node.settings.enablePeerswap : false;
|
||||
this.common.nodes[idx].settings.bitcoindConfigPath = process?.env?.BITCOIND_CONFIG_PATH ? process?.env?.BITCOIND_CONFIG_PATH : (node.settings.bitcoindConfigPath) ? node.settings.bitcoindConfigPath : '';
|
||||
this.common.nodes[idx].settings.channelBackupPath = process?.env?.CHANNEL_BACKUP_PATH ? process?.env?.CHANNEL_BACKUP_PATH : (node.settings.channelBackupPath) ? node.settings.channelBackupPath : this.common.appConfig.rtlConfFilePath + sep + 'channels-backup' + sep + 'node-' + node.index;
|
||||
this.common.nodes[idx].settings.blockExplorerUrl = process?.env?.BLOCK_EXPLORER_URL ? process.env.BLOCK_EXPLORER_URL : (node.settings.blockExplorerUrl) ? node.settings.blockExplorerUrl : 'https://mempool.space';
|
||||
try {
|
||||
this.common.createDirectory(this.common.nodes[idx].channel_backup_path);
|
||||
const exists = fs.existsSync(this.common.nodes[idx].channel_backup_path + sep + 'channel-all.bak');
|
||||
this.common.createDirectory(this.common.nodes[idx].settings.channelBackupPath);
|
||||
const exists = fs.existsSync(this.common.nodes[idx].settings.channelBackupPath + sep + 'channel-all.bak');
|
||||
if (!exists) {
|
||||
try {
|
||||
if (this.common.nodes[idx].ln_implementation === 'LND') {
|
||||
if (this.common.nodes[idx].lnImplementation === 'LND') {
|
||||
this.common.getAllNodeAllChannelBackup(this.common.nodes[idx]);
|
||||
} else {
|
||||
const createStream = fs.createWriteStream(this.common.nodes[idx].channel_backup_path + sep + 'channel-all.bak');
|
||||
const createStream = fs.createWriteStream(this.common.nodes[idx].settings.channelBackupPath + sep + 'channel-all.bak');
|
||||
createStream.end();
|
||||
}
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'Config', msg: 'Something went wrong while creating backup file: \n' + err });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'Config', msg: 'Something went wrong while creating backup file: \n' + err });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'Config', msg: 'Something went wrong while creating the backup directory: \n' + err });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'Config', msg: 'Something went wrong while creating the backup directory: \n' + err });
|
||||
}
|
||||
this.common.nodes[idx].log_file = this.common.rtl_conf_file_path + '/logs/RTL-Node-' + node.index + '.log';
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'Config', msg: 'Node Config: ' + JSON.stringify(this.common.nodes[idx]) });
|
||||
const log_file = this.common.nodes[idx].log_file;
|
||||
this.common.nodes[idx].settings.logFile = config.rtlConfFilePath + '/logs/RTL-Node-' + node.index + '.log';
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'Config', msg: 'Node Config: ' + JSON.stringify(this.common.nodes[idx]) });
|
||||
const log_file = this.common.nodes[idx].settings.logFile;
|
||||
if (fs.existsSync(log_file || '')) {
|
||||
fs.writeFile((log_file || ''), '', () => { });
|
||||
} else {
|
||||
|
|
@ -284,7 +287,7 @@ export class ConfigService {
|
|||
const createStream = fs.createWriteStream(log_file || '');
|
||||
createStream.end();
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'Config', msg: 'Something went wrong while creating log file ' + log_file + ': \n' + err });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'Config', msg: 'Something went wrong while creating log file ' + log_file + ': \n' + err });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -295,27 +298,27 @@ export class ConfigService {
|
|||
|
||||
private setSSOParams = (config) => {
|
||||
if (process?.env?.RTL_SSO) {
|
||||
this.common.rtl_sso = +process?.env?.RTL_SSO;
|
||||
config.SSO.rtlSso = +process?.env?.RTL_SSO;
|
||||
} else if (config.SSO && config.SSO.rtlSSO) {
|
||||
this.common.rtl_sso = config.SSO.rtlSSO;
|
||||
config.SSO.rtlSso = config.SSO.rtlSSO;
|
||||
}
|
||||
|
||||
if (process?.env?.RTL_COOKIE_PATH) {
|
||||
this.common.rtl_cookie_path = process?.env?.RTL_COOKIE_PATH;
|
||||
config.SSO.rtlCookiePath = process?.env?.RTL_COOKIE_PATH;
|
||||
} else if (config.SSO && config.SSO.rtlCookiePath) {
|
||||
this.common.rtl_cookie_path = config.SSO.rtlCookiePath;
|
||||
config.SSO.rtlCookiePath = config.SSO.rtlCookiePath;
|
||||
} else {
|
||||
this.common.rtl_cookie_path = '';
|
||||
config.SSO.rtlCookiePath = '';
|
||||
}
|
||||
|
||||
if (process?.env?.LOGOUT_REDIRECT_LINK) {
|
||||
this.common.logout_redirect_link = process?.env?.LOGOUT_REDIRECT_LINK;
|
||||
config.SSO.logoutRedirectLink = process?.env?.LOGOUT_REDIRECT_LINK;
|
||||
} else if (config.SSO && config.SSO.logoutRedirectLink) {
|
||||
this.common.logout_redirect_link = config.SSO.logoutRedirectLink;
|
||||
config.SSO.logoutRedirectLink = config.SSO.logoutRedirectLink;
|
||||
}
|
||||
|
||||
if (+this.common.rtl_sso) {
|
||||
if (!this.common.rtl_cookie_path || this.common.rtl_cookie_path.trim() === '') {
|
||||
if (+config.SSO.rtlSso) {
|
||||
if (!config.SSO.rtlCookiePath || config.SSO.rtlCookiePath.trim() === '') {
|
||||
this.errMsg = 'Please set rtlCookiePath value for single sign on option!';
|
||||
} else {
|
||||
this.common.readCookie();
|
||||
|
|
@ -325,25 +328,47 @@ export class ConfigService {
|
|||
|
||||
private setSelectedNode = (config) => {
|
||||
if (config.defaultNodeIndex) {
|
||||
this.common.initSelectedNode = this.common.findNode(config.defaultNodeIndex) || {};
|
||||
this.common.selectedNode = this.common.findNode(config.defaultNodeIndex) || {};
|
||||
} else {
|
||||
this.common.initSelectedNode = this.common.findNode(this.common.nodes[0].index) || {};
|
||||
this.common.selectedNode = this.common.findNode(this.common.nodes[0].index) || {};
|
||||
}
|
||||
};
|
||||
|
||||
private updateConfig = (confFileFullPath, config) => {
|
||||
// Update Config file to change Settings to settings and Authentication to authentication
|
||||
// Added in v0.15.1, remove in a year?
|
||||
if (!config.nodes) { return; }
|
||||
config.nodes.map((node) => {
|
||||
if (node.Authentication) {
|
||||
node.authentication = JSON.parse(JSON.stringify(node.Authentication));
|
||||
delete node.Authentication;
|
||||
}
|
||||
if (node.Settings) {
|
||||
node.settings = JSON.parse(JSON.stringify(node.Settings));
|
||||
delete node.Settings;
|
||||
}
|
||||
return node;
|
||||
});
|
||||
fs.writeFileSync(confFileFullPath, JSON.stringify(config, null, 2), 'utf-8');
|
||||
};
|
||||
|
||||
public setServerConfiguration = () => {
|
||||
const rtlConfFilePath = (process?.env?.RTL_CONFIG_PATH) ? process?.env?.RTL_CONFIG_PATH : join(this.directoryName, '../..');
|
||||
const confFileFullPath = rtlConfFilePath + sep + 'RTL-Config.json';
|
||||
try {
|
||||
this.common.rtl_conf_file_path = (process?.env?.RTL_CONFIG_PATH) ? process?.env?.RTL_CONFIG_PATH : join(this.directoryName, '../..');
|
||||
const confFileFullPath = this.common.rtl_conf_file_path + sep + 'RTL-Config.json';
|
||||
if (!fs.existsSync(confFileFullPath)) {
|
||||
fs.writeFileSync(confFileFullPath, JSON.stringify(this.setDefaultConfig()));
|
||||
fs.writeFileSync(confFileFullPath, JSON.stringify(this.setDefaultConfig(), null, 2), 'utf-8');
|
||||
}
|
||||
const config = JSON.parse(fs.readFileSync(confFileFullPath, 'utf-8'));
|
||||
this.updateConfig(confFileFullPath, config);
|
||||
config.rtlConfFilePath = rtlConfFilePath;
|
||||
this.updateLogByLevel();
|
||||
this.validateNodeConfig(config);
|
||||
this.setSelectedNode(config);
|
||||
this.common.appConfig = config;
|
||||
} catch (err: any) {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'ERROR', fileName: 'Config', msg: 'Something went wrong while configuring the node server: \n' + err });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'Config', msg: 'Config file path: ' + confFileFullPath });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'ERROR', fileName: 'Config', msg: 'Something went wrong while configuring the node server: \n' + err });
|
||||
throw new Error(err);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class CORS {
|
|||
public common: CommonService = Common;
|
||||
|
||||
public mount(app: Application): Application {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'CORS', msg: 'Setting up CORS..' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'CORS', msg: 'Setting up CORS..' });
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, filePath');
|
||||
|
|
@ -19,7 +19,7 @@ class CORS {
|
|||
}
|
||||
next();
|
||||
});
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'CORS', msg: 'CORS Set' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'CORS', msg: 'CORS Set' });
|
||||
return app;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ class CSRF {
|
|||
public common: CommonService = Common;
|
||||
|
||||
public mount(app: Application): Application {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'CSRF', msg: 'Setting up CSRF..' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'CSRF', msg: 'Setting up CSRF..' });
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
app.use((req, res, next) => this.csrfProtection(req, res, next));
|
||||
}
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'CSRF', msg: 'CSRF Set' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'CSRF', msg: 'CSRF Set' });
|
||||
return app;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,20 +3,20 @@ import { join, sep } from 'path';
|
|||
import { Common, CommonService } from '../utils/common.js';
|
||||
import { Logger, LoggerService } from '../utils/logger.js';
|
||||
import { Collections, CollectionsEnum, validateDocument, LNDCollection, ECLCollection, CLNCollection, ECL_UPDATED_DB } from '../models/database.model.js';
|
||||
import { CommonSelectedNode } from '../models/config.model.js';
|
||||
import { SelectedNode } from '../models/config.model.js';
|
||||
|
||||
export class DatabaseService {
|
||||
|
||||
public common: CommonService = Common;
|
||||
public logger: LoggerService = Logger;
|
||||
public dbDirectory = join(this.common.db_directory_path, 'database');
|
||||
public dbDirectory = join(this.common.appConfig.dbDirectoryPath, 'database');
|
||||
public nodeDatabase: { id?: { adapter: DatabaseAdapter, data: Collections } } = {};
|
||||
|
||||
constructor() { }
|
||||
|
||||
migrateDatabase() {
|
||||
this.common.nodes?.map((node: any) => {
|
||||
if (node.ln_implementation === 'ECL') {
|
||||
if (node.lnImplementation === 'ECL') {
|
||||
this.nodeDatabase[node.index] = { adapter: null, data: {} };
|
||||
this.nodeDatabase[node.index].adapter = new DatabaseAdapter(this.dbDirectory, node);
|
||||
this.fetchNodeData(node);
|
||||
|
|
@ -82,8 +82,8 @@ export class DatabaseService {
|
|||
}
|
||||
}
|
||||
|
||||
fetchNodeData(selectedNode: CommonSelectedNode) {
|
||||
switch (selectedNode.ln_implementation) {
|
||||
fetchNodeData(selectedNode: SelectedNode) {
|
||||
switch (selectedNode.lnImplementation) {
|
||||
case 'CLN':
|
||||
for (const collectionName in CLNCollection) {
|
||||
if (CLNCollection.hasOwnProperty(collectionName)) {
|
||||
|
|
@ -121,7 +121,7 @@ export class DatabaseService {
|
|||
});
|
||||
}
|
||||
|
||||
insert(selectedNode: CommonSelectedNode, collectionName: CollectionsEnum, newCollection: any) {
|
||||
insert(selectedNode: SelectedNode, collectionName: CollectionsEnum, newCollection: any) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (!selectedNode || !selectedNode.index) {
|
||||
|
|
@ -136,7 +136,7 @@ export class DatabaseService {
|
|||
});
|
||||
}
|
||||
|
||||
update(selectedNode: CommonSelectedNode, collectionName: CollectionsEnum, updatedDocument: any, documentFieldName: string, documentFieldValue: string) {
|
||||
update(selectedNode: SelectedNode, collectionName: CollectionsEnum, updatedDocument: any, documentFieldName: string, documentFieldValue: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (!selectedNode || !selectedNode.index) {
|
||||
|
|
@ -172,7 +172,7 @@ export class DatabaseService {
|
|||
});
|
||||
}
|
||||
|
||||
find(selectedNode: CommonSelectedNode, collectionName: CollectionsEnum, documentFieldName?: string, documentFieldValue?: string) {
|
||||
find(selectedNode: SelectedNode, collectionName: CollectionsEnum, documentFieldName?: string, documentFieldValue?: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (!selectedNode || !selectedNode.index) {
|
||||
|
|
@ -189,7 +189,7 @@ export class DatabaseService {
|
|||
});
|
||||
}
|
||||
|
||||
remove(selectedNode: CommonSelectedNode, collectionName: CollectionsEnum, documentFieldName: string, documentFieldValue: string) {
|
||||
remove(selectedNode: SelectedNode, collectionName: CollectionsEnum, documentFieldName: string, documentFieldValue: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (!selectedNode || !selectedNode.index) {
|
||||
|
|
@ -209,7 +209,7 @@ export class DatabaseService {
|
|||
});
|
||||
}
|
||||
|
||||
saveDatabase(selectedNode: CommonSelectedNode, collectionName: CollectionsEnum) {
|
||||
saveDatabase(selectedNode: SelectedNode, collectionName: CollectionsEnum) {
|
||||
const nodeIndex = +selectedNode.index;
|
||||
try {
|
||||
if (nodeIndex < 1) {
|
||||
|
|
@ -250,17 +250,17 @@ export class DatabaseAdapter {
|
|||
private dbFilePath = '';
|
||||
private userSessions = [];
|
||||
|
||||
constructor(public dbDirectoryPath: string, public selNode: CommonSelectedNode = null, public id: string = '') {
|
||||
constructor(public dbDirectoryPath: string, public selNode: SelectedNode = null, public id: string = '') {
|
||||
this.dbFilePath = dbDirectoryPath + sep + 'node-' + selNode.index;
|
||||
// For backward compatibility Start
|
||||
const oldFilePath = dbDirectoryPath + sep + 'rtldb-node-' + selNode.index + '.json';
|
||||
if (selNode.ln_implementation === 'CLN' && fs.existsSync(oldFilePath)) { this.renameOldDB(oldFilePath, selNode); }
|
||||
if (selNode.lnImplementation === 'CLN' && fs.existsSync(oldFilePath)) { this.renameOldDB(oldFilePath, selNode); }
|
||||
// For backward compatibility End
|
||||
this.insertSession(id);
|
||||
}
|
||||
|
||||
renameOldDB(oldFilePath: string, selNode: CommonSelectedNode = null) {
|
||||
const newFilePath = this.dbFilePath + sep + 'rtldb-' + selNode.ln_implementation + '-Offers.json';
|
||||
renameOldDB(oldFilePath: string, selNode: SelectedNode = null) {
|
||||
const newFilePath = this.dbFilePath + sep + 'rtldb-' + selNode.lnImplementation + '-Offers.json';
|
||||
try {
|
||||
this.common.createDirectory(this.dbFilePath);
|
||||
const oldOffers: any = JSON.parse(fs.readFileSync(oldFilePath, 'utf-8'));
|
||||
|
|
@ -279,7 +279,7 @@ export class DatabaseAdapter {
|
|||
} catch (err) {
|
||||
throw new Error(JSON.stringify(err));
|
||||
}
|
||||
const collectionFilePath = this.dbFilePath + sep + 'rtldb-' + this.selNode.ln_implementation + '-' + collectionName + '.json';
|
||||
const collectionFilePath = this.dbFilePath + sep + 'rtldb-' + this.selNode.lnImplementation + '-' + collectionName + '.json';
|
||||
try {
|
||||
if (!fs.existsSync(collectionFilePath)) {
|
||||
fs.writeFileSync(collectionFilePath, '[]');
|
||||
|
|
@ -291,17 +291,17 @@ export class DatabaseAdapter {
|
|||
const otherFiles = fs.readdirSync(this.dbFilePath);
|
||||
otherFiles.forEach((oFileName) => {
|
||||
let collectionValid = false;
|
||||
switch (this.selNode.ln_implementation) {
|
||||
switch (this.selNode.lnImplementation) {
|
||||
case 'CLN':
|
||||
collectionValid = CLNCollection.reduce((acc, collection) => acc || oFileName === ('rtldb-' + this.selNode.ln_implementation + '-' + collection + '.json'), false);
|
||||
collectionValid = CLNCollection.reduce((acc, collection) => acc || oFileName === ('rtldb-' + this.selNode.lnImplementation + '-' + collection + '.json'), false);
|
||||
break;
|
||||
|
||||
case 'ECL':
|
||||
collectionValid = ECLCollection.reduce((acc, collection) => acc || oFileName === ('rtldb-' + this.selNode.ln_implementation + '-' + collection + '.json'), false);
|
||||
collectionValid = ECLCollection.reduce((acc, collection) => acc || oFileName === ('rtldb-' + this.selNode.lnImplementation + '-' + collection + '.json'), false);
|
||||
break;
|
||||
|
||||
default:
|
||||
collectionValid = LNDCollection.reduce((acc, collection) => acc || oFileName === ('rtldb-' + this.selNode.ln_implementation + '-' + collection + '.json'), false);
|
||||
collectionValid = LNDCollection.reduce((acc, collection) => acc || oFileName === ('rtldb-' + this.selNode.lnImplementation + '-' + collection + '.json'), false);
|
||||
break;
|
||||
}
|
||||
if (oFileName.endsWith('.json') && !collectionValid) {
|
||||
|
|
@ -327,7 +327,7 @@ export class DatabaseAdapter {
|
|||
saveData(collectionName: string, collectionData: any) {
|
||||
try {
|
||||
if (collectionData) {
|
||||
const collectionFilePath = this.dbFilePath + sep + 'rtldb-' + this.selNode.ln_implementation + '-' + collectionName + '.json';
|
||||
const collectionFilePath = this.dbFilePath + sep + 'rtldb-' + this.selNode.lnImplementation + '-' + collectionName + '.json';
|
||||
const tempFile = collectionFilePath + '.tmp';
|
||||
fs.writeFileSync(tempFile, JSON.stringify(collectionData, null, 2));
|
||||
fs.renameSync(tempFile, collectionFilePath);
|
||||
|
|
|
|||
|
|
@ -17,16 +17,16 @@ export class LoggerService {
|
|||
msgStr = msgStr + '.\r\n';
|
||||
}
|
||||
console.error(msgStr);
|
||||
if (msgJSON.selectedNode && msgJSON.selectedNode.log_file) {
|
||||
fs.appendFile(msgJSON.selectedNode.log_file, msgStr, () => { });
|
||||
if (msgJSON.selectedNode && msgJSON.selectedNode.settings.logFile) {
|
||||
fs.appendFile(msgJSON.selectedNode.settings.logFile, msgStr, () => { });
|
||||
}
|
||||
break;
|
||||
|
||||
case 'WARN':
|
||||
msgStr = prepMsgData(msgJSON, msgStr);
|
||||
if (!msgJSON.selectedNode || msgJSON.selectedNode.log_level === 'WARN' || msgJSON.selectedNode.log_level === 'INFO' || msgJSON.selectedNode.log_level === 'DEBUG') {
|
||||
if (msgJSON.selectedNode && msgJSON.selectedNode.log_file) {
|
||||
fs.appendFile(msgJSON.selectedNode.log_file, msgStr, () => { });
|
||||
if (!msgJSON.selectedNode || msgJSON.selectedNode.settings.logLevel === 'WARN' || msgJSON.selectedNode.settings.logLevel === 'INFO' || msgJSON.selectedNode.settings.logLevel === 'DEBUG') {
|
||||
if (msgJSON.selectedNode && msgJSON.selectedNode.settings.logFile) {
|
||||
fs.appendFile(msgJSON.selectedNode.settings.logFile, msgStr, () => { });
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -34,17 +34,17 @@ export class LoggerService {
|
|||
case 'INFO':
|
||||
if (!msgJSON.selectedNode && msgJSON.fileName === 'RTL') {
|
||||
console.log(msgStr + '.\r\n');
|
||||
} else if (msgJSON.selectedNode && msgJSON.selectedNode.log_level === 'INFO') {
|
||||
} else if (msgJSON.selectedNode && msgJSON.selectedNode.settings.logLevel === 'INFO') {
|
||||
msgStr = msgStr + '.\r\n';
|
||||
console.log(msgStr);
|
||||
if (msgJSON.selectedNode.log_file) {
|
||||
fs.appendFile(msgJSON.selectedNode.log_file, msgStr, () => { });
|
||||
if (msgJSON.selectedNode.settings.logFile) {
|
||||
fs.appendFile(msgJSON.selectedNode.settings.logFile, msgStr, () => { });
|
||||
}
|
||||
} else if (msgJSON.selectedNode && msgJSON.selectedNode.log_level === 'DEBUG') {
|
||||
} else if (msgJSON.selectedNode && msgJSON.selectedNode.settings.logLevel === 'DEBUG') {
|
||||
msgStr = prepMsgData(msgJSON, msgStr);
|
||||
console.log(msgStr);
|
||||
if (msgJSON.selectedNode.log_file) {
|
||||
fs.appendFile(msgJSON.selectedNode.log_file, msgStr, () => { });
|
||||
if (msgJSON.selectedNode.settings.logFile) {
|
||||
fs.appendFile(msgJSON.selectedNode.settings.logFile, msgStr, () => { });
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -52,11 +52,11 @@ export class LoggerService {
|
|||
case 'DEBUG':
|
||||
if (!msgJSON.selectedNode) {
|
||||
console.log(msgStr + '.\r\n');
|
||||
} else if (msgJSON.selectedNode && msgJSON.selectedNode.log_level === 'DEBUG') {
|
||||
} else if (msgJSON.selectedNode && msgJSON.selectedNode.settings.logLevel === 'DEBUG') {
|
||||
msgStr = prepMsgData(msgJSON, msgStr);
|
||||
console.log(msgStr);
|
||||
if (msgJSON.selectedNode.log_file) {
|
||||
fs.appendFile(msgJSON.selectedNode.log_file, msgStr, () => { });
|
||||
if (msgJSON.selectedNode.settings.logFile) {
|
||||
fs.appendFile(msgJSON.selectedNode.settings.logFile, msgStr, () => { });
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Logger, LoggerService } from './logger.js';
|
|||
import { Common, CommonService } from './common.js';
|
||||
import { verifyWSUser } from './authCheck.js';
|
||||
import { EventEmitter } from 'events';
|
||||
import { CommonSelectedNode } from '../models/config.model.js';
|
||||
import { SelectedNode } from '../models/config.model.js';
|
||||
|
||||
export class RTLWebSocketServer {
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ export class RTLWebSocketServer {
|
|||
}, 1000 * 60 * 60); // Terminate broken connections every hour
|
||||
|
||||
public mount = (httpServer) => {
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Connecting Websocket Server..' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Connecting Websocket Server..' });
|
||||
this.webSocketServer = new WebSocketServer({ noServer: true, path: this.common.baseHref + '/api/ws', verifyClient: (process.env.NODE_ENV === 'development') ? null : verifyWSUser });
|
||||
httpServer.on('upgrade', (request, socket, head) => {
|
||||
if (request.headers['upgrade'] !== 'websocket') {
|
||||
|
|
@ -48,7 +48,7 @@ export class RTLWebSocketServer {
|
|||
});
|
||||
this.webSocketServer.on('connection', this.mountEventsOnConnection);
|
||||
this.webSocketServer.on('close', () => clearInterval(this.pingInterval));
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Websocket Server Connected' });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Websocket Server Connected' });
|
||||
};
|
||||
|
||||
public upgradeCallback = (websocket, request) => {
|
||||
|
|
@ -62,13 +62,13 @@ export class RTLWebSocketServer {
|
|||
websocket.isAlive = true;
|
||||
websocket.sessionId = cookies && cookies['connect.sid'] ? cookieParser.signedCookie(cookies['connect.sid'], this.common.secret_key) : null;
|
||||
websocket.clientNodeIndex = +protocols[1];
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Connected: ' + websocket.clientId + ', Total WS clients: ' + this.webSocketServer.clients.size });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Connected: ' + websocket.clientId + ', Total WS clients: ' + this.webSocketServer.clients.size });
|
||||
websocket.on('error', this.sendErrorToAllLNClients);
|
||||
websocket.on('message', this.sendEventsToAllLNClients);
|
||||
websocket.on('pong', () => { websocket.isAlive = true; });
|
||||
websocket.on('close', (code, reason) => {
|
||||
this.updateLNWSClientDetails(websocket.sessionId, -1, websocket.clientNodeIndex);
|
||||
this.logger.log({ selectedNode: this.common.initSelectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Disconnected due to ' + code + ' : ' + websocket.clientId + ', Total WS clients: ' + this.webSocketServer.clients.size });
|
||||
this.logger.log({ selectedNode: this.common.selectedNode, level: 'INFO', fileName: 'WebSocketServer', msg: 'Disconnected due to ' + code + ' : ' + websocket.clientId + ', Total WS clients: ' + this.webSocketServer.clients.size });
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ export class RTLWebSocketServer {
|
|||
this.connectToNodeClient(sessionId, currNodeIndex);
|
||||
} else {
|
||||
const selectedNode = this.common.findNode(currNodeIndex);
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.initSelectedNode : selectedNode, level: 'ERROR', fileName: 'WebSocketServer', msg: 'Invalid Node Selection. Previous and current node indices can not be less than zero.' });
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.selectedNode : selectedNode, level: 'ERROR', fileName: 'WebSocketServer', msg: 'Invalid Node Selection. Previous and current node indices can not be less than zero.' });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -102,8 +102,8 @@ export class RTLWebSocketServer {
|
|||
const foundClientIdx = this.clientDetails.findIndex((clientDetail) => clientDetail.index === +prevNodeIndex);
|
||||
this.clientDetails.splice(foundClientIdx, 1);
|
||||
const prevSelectedNode = this.common.findNode(prevNodeIndex);
|
||||
if (prevSelectedNode && prevSelectedNode.ln_implementation) {
|
||||
switch (prevSelectedNode.ln_implementation) {
|
||||
if (prevSelectedNode && prevSelectedNode.lnImplementation) {
|
||||
switch (prevSelectedNode.lnImplementation) {
|
||||
case 'LND':
|
||||
this.eventEmitterLND.emit('DISCONNECT', prevNodeIndex);
|
||||
break;
|
||||
|
|
@ -132,8 +132,8 @@ export class RTLWebSocketServer {
|
|||
const currSelectedNode = this.common.findNode(currNodeIndex);
|
||||
foundClient = { index: currNodeIndex, sessionIds: [sessionId] };
|
||||
this.clientDetails.push(foundClient);
|
||||
if (currSelectedNode && currSelectedNode.ln_implementation) {
|
||||
switch (currSelectedNode.ln_implementation) {
|
||||
if (currSelectedNode && currSelectedNode.lnImplementation) {
|
||||
switch (currSelectedNode.lnImplementation) {
|
||||
case 'LND':
|
||||
this.eventEmitterLND.emit('CONNECT', currNodeIndex);
|
||||
break;
|
||||
|
|
@ -150,29 +150,29 @@ export class RTLWebSocketServer {
|
|||
}
|
||||
};
|
||||
|
||||
public sendErrorToAllLNClients = (serverError, selectedNode: CommonSelectedNode) => {
|
||||
public sendErrorToAllLNClients = (serverError, selectedNode: SelectedNode) => {
|
||||
try {
|
||||
this.webSocketServer.clients.forEach((client) => {
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.initSelectedNode : selectedNode, level: 'ERROR', fileName: 'WebSocketServer', msg: 'Broadcasting error to clients...: ' + serverError });
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.selectedNode : selectedNode, level: 'ERROR', fileName: 'WebSocketServer', msg: 'Broadcasting error to clients...: ' + serverError });
|
||||
if (+client.clientNodeIndex === +selectedNode.index) {
|
||||
client.send(serverError);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.initSelectedNode : selectedNode, level: 'ERROR', fileName: 'WebSocketServer', msg: 'Error while broadcasting message: ' + JSON.stringify(err) });
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.selectedNode : selectedNode, level: 'ERROR', fileName: 'WebSocketServer', msg: 'Error while broadcasting message: ' + JSON.stringify(err) });
|
||||
}
|
||||
};
|
||||
|
||||
public sendEventsToAllLNClients = (newMessage, selectedNode: CommonSelectedNode) => {
|
||||
public sendEventsToAllLNClients = (newMessage, selectedNode: SelectedNode) => {
|
||||
try {
|
||||
this.webSocketServer.clients.forEach((client) => {
|
||||
if (+client.clientNodeIndex === +selectedNode.index) {
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.initSelectedNode : selectedNode, level: 'DEBUG', fileName: 'WebSocketServer', msg: 'Broadcasting message to client...: ' + client.clientId + ', Message: ' + newMessage });
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.selectedNode : selectedNode, level: 'DEBUG', fileName: 'WebSocketServer', msg: 'Broadcasting message to client...: ' + client.clientId + ', Message: ' + newMessage });
|
||||
client.send(newMessage);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.initSelectedNode : selectedNode, level: 'ERROR', fileName: 'WebSocketServer', msg: 'Error while broadcasting message: ' + JSON.stringify(err) });
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.selectedNode : selectedNode, level: 'ERROR', fileName: 'WebSocketServer', msg: 'Error while broadcasting message: ' + JSON.stringify(err) });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue