mirror of
https://github.com/Ride-The-Lightning/RTL.git
synced 2026-08-13 12:33:07 +02:00
parent
d083be1196
commit
475b47b7ea
160 changed files with 5377 additions and 4750 deletions
|
|
@ -1,30 +0,0 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
let options = null;
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
export const getBalance = (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/getBalance';
|
||||
request(options).then((body) => {
|
||||
if (!body.totalBalance) {
|
||||
body.totalBalance = 0;
|
||||
}
|
||||
if (!body.confBalance) {
|
||||
body.confBalance = 0;
|
||||
}
|
||||
if (!body.unconfBalance) {
|
||||
body.unconfBalance = 0;
|
||||
}
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Balance', msg: 'Balance Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Balance', 'Get Balance Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
import { getAlias } from './network.js';
|
||||
let options = null;
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
|
|
@ -10,59 +11,29 @@ export const listPeerChannels = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listPeerChannels';
|
||||
request(options).then((body) => {
|
||||
body?.map((channel) => {
|
||||
if (!channel.alias || channel.alias === '') {
|
||||
channel.alias = channel.peer_id.substring(0, 20);
|
||||
}
|
||||
const local = channel.to_us_msat || 0;
|
||||
const remote = (channel.total_msat - local) || 0;
|
||||
const total = channel.total_msat || 0;
|
||||
channel.to_them_msat = remote;
|
||||
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3);
|
||||
return channel;
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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) => {
|
||||
channel.to_them_msat = channel.total_msat - channel.to_us_msat;
|
||||
channel.balancedness = (channel.total_msat === 0) ? 1 : (1 - Math.abs((channel.to_us_msat - (channel.total_msat - channel.to_us_msat)) / channel.total_msat)).toFixed(3);
|
||||
return getAlias(req.session.selectedNode, channel, 'peer_id');
|
||||
})).then((values) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List With Aliases Received', data: body.channels });
|
||||
return res.status(200).json(body.channels || []);
|
||||
});
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'List Peer Channels Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const listChannels = (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/channel/listPeerChannels';
|
||||
request(options).then((body) => {
|
||||
body?.map((channel) => {
|
||||
if (!channel.alias || channel.alias === '') {
|
||||
channel.alias = channel.channel_id.substring(0, 20);
|
||||
}
|
||||
const local = channel.to_us_msat || 0;
|
||||
const remote = (channel.total_msat - local) || 0;
|
||||
const total = channel.total_msat || 0;
|
||||
channel.to_them_msat = remote;
|
||||
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3);
|
||||
return channel;
|
||||
});
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Channels List Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'List Channels Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
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/channel/openChannel';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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) => {
|
||||
|
|
@ -79,7 +50,7 @@ export const setChannelFee = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/setChannelFee';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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) => {
|
||||
|
|
@ -97,10 +68,10 @@ export const closeChannel = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
const unilateralTimeoutQuery = req.query.force ? '?unilateralTimeout=1' : '';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/closeChannel/' + req.params.channelId + unilateralTimeoutQuery;
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/close';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Closing Channel', data: options.url });
|
||||
request.delete(options).then((body) => {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Channel Closed', data: body });
|
||||
res.status(204).json(body);
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -108,37 +79,18 @@ export const closeChannel = (req, res, next) => {
|
|||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const getLocalRemoteBalance = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Local & Remote Balances..' });
|
||||
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/channel/localremotebal';
|
||||
request(options).then((body) => {
|
||||
if (!body.localBalance) {
|
||||
body.localBalance = 0;
|
||||
}
|
||||
if (!body.remoteBalance) {
|
||||
body.remoteBalance = 0;
|
||||
}
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Local Remote Balance Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'Local Remote Balance Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const listForwards = (req, res, next) => {
|
||||
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/channel/listForwards?status=' + (req.query.status ? req.query.status : 'settled');
|
||||
request.get(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Forwarding History Received For Status ' + req.query.status, data: body });
|
||||
res.status(200).json(body);
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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();
|
||||
res.status(200).json(body.forwards);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'Forwarding History Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
|
|
@ -150,38 +102,14 @@ export const funderUpdatePolicy = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/funderUpdate';
|
||||
if (req.body && req.body.policy) {
|
||||
options.body = req.body;
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Funder Policy Received', data: body });
|
||||
body.channel_fee_max_base_msat = (body.channel_fee_max_base_msat && typeof body.channel_fee_max_base_msat === 'string' && body.channel_fee_max_base_msat.includes('msat')) ? +body.channel_fee_max_base_msat?.replace('msat', '') : body.channel_fee_max_base_msat;
|
||||
body.lease_fee_base_msat = (body.lease_fee_base_msat && typeof body.lease_fee_base_msat === 'string' && body.lease_fee_base_msat.includes('msat')) ? +body.lease_fee_base_msat?.replace('msat', '') : body.channel_fee_max_base_msat;
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'Funder Policy Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const listForwardsPaginated = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Paginated List Forwards..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
const { status, maxLen, offset } = req.query;
|
||||
let queryStr = '?status=' + (status ? status : 'settled');
|
||||
queryStr = queryStr + '&maxLen=' + (maxLen ? maxLen : '10');
|
||||
queryStr = queryStr + '&offset=' + (offset ? offset : '0');
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/listForwardsPaginated' + queryStr;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Paginated Forwarding History url' + options.url });
|
||||
request.get(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Paginated Forwarding History Received For Status ' + req.query.status, data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'Paginated Forwarding History Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,13 +10,12 @@ export const getFees = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/getFees';
|
||||
request(options).then((body) => {
|
||||
if (!body.feeCollected) {
|
||||
body.feeCollected = 0;
|
||||
}
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Fee Received', data: body });
|
||||
res.status(200).json(body);
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/getinfo';
|
||||
request.post(options).then((body) => {
|
||||
const versionCompatible = common.isVersionCompatible(req.session.selectedNode.ln_version, '23.02');
|
||||
const feeData = { feeCollected: ((versionCompatible ? body.fees_collected_msat : body.msatoshi_fees_collected) || 0) };
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Fee Received', data: feeData });
|
||||
res.status(200).json(feeData);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Fees', 'Get Fees Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
|
|
|
|||
|
|
@ -19,52 +19,41 @@ export const getInfo = (req, res, next) => {
|
|||
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 });
|
||||
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.macaroon) {
|
||||
const errMsg = 'Core lightning get info failed due to bad or missing macaroon!';
|
||||
const err = common.handleError({ statusCode: 502, message: 'Bad Macaroon', error: errMsg }, 'GetInfo', errMsg, req.session.selectedNode);
|
||||
if (!options.headers || !options.headers.rune) {
|
||||
const errMsg = 'Core lightning get info failed due to missing rune!';
|
||||
const err = common.handleError({ statusCode: 502, message: 'Bad rune', error: errMsg }, 'GetInfo', errMsg, req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
}
|
||||
else {
|
||||
return request(options).then((body) => {
|
||||
const body_str = (!body) ? '' : JSON.stringify(body);
|
||||
const search_idx = (!body) ? -1 : body_str.search('Not Found');
|
||||
if (!body || search_idx > -1 || body.error) {
|
||||
if (body && !body.error) {
|
||||
body.error = 'Error From Server!';
|
||||
}
|
||||
const err = common.handleError(body, 'GetInfo', 'Get Info Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
return request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'GetInfo', msg: 'Node Information Before Update', data: body });
|
||||
body.lnImplementation = 'Core Lightning';
|
||||
const chainObj = { chain: '', network: '' };
|
||||
if (body.network.includes('litecoin') || body.network.includes('feathercoin')) {
|
||||
chainObj.chain = '';
|
||||
chainObj.network = '';
|
||||
}
|
||||
else if (body.network.includes('liquid')) {
|
||||
chainObj.chain = 'Liquid';
|
||||
chainObj.network = common.titleCase(body.network);
|
||||
}
|
||||
else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'GetInfo', msg: 'Node Information Before Update', data: body });
|
||||
body.lnImplementation = 'Core Lightning';
|
||||
const chainObj = { chain: '', network: '' };
|
||||
if (body.network.includes('litecoin') || body.network.includes('feathercoin')) {
|
||||
chainObj.chain = '';
|
||||
chainObj.network = '';
|
||||
}
|
||||
else if (body.network.includes('liquid')) {
|
||||
chainObj.chain = 'Liquid';
|
||||
chainObj.network = common.titleCase(body.network);
|
||||
}
|
||||
else {
|
||||
chainObj.chain = 'Bitcoin';
|
||||
chainObj.network = common.titleCase(body.network);
|
||||
}
|
||||
body.chains = [chainObj];
|
||||
body.uris = [];
|
||||
if (body.address && body.address.length > 0) {
|
||||
body.address.forEach((addr) => {
|
||||
body.uris.push(body.id + '@' + addr.address + ':' + addr.port);
|
||||
});
|
||||
}
|
||||
req.session.selectedNode.api_version = body.api_version || '';
|
||||
req.session.selectedNode.ln_version = body.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);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Node Information Received', data: body });
|
||||
return res.status(200).json(body);
|
||||
chainObj.chain = 'Bitcoin';
|
||||
chainObj.network = common.titleCase(body.network);
|
||||
}
|
||||
body.chains = [chainObj];
|
||||
body.uris = [];
|
||||
if (body.address && body.address.length > 0) {
|
||||
body.address.forEach((addr) => {
|
||||
body.uris.push(body.id + '@' + addr.address + ':' + addr.port);
|
||||
});
|
||||
}
|
||||
req.session.selectedNode.ln_version = 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);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Node Information Received', data: body });
|
||||
return res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'GetInfo', 'Get Info Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ export const deleteExpiredInvoice = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
const queryStr = req.query.maxExpiry ? '?maxexpiry=' + req.query.maxExpiry : '';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/invoice/delExpiredInvoice' + queryStr;
|
||||
request.delete(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(204).json({ status: 'Invoice Deleted Successfully' });
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -26,10 +26,10 @@ export const listInvoices = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
const labelQuery = req.query.label ? '?label=' + req.query.label : '';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/invoice/listInvoices' + labelQuery;
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listinvoices';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Invoice', msg: 'Invoices List URL', data: options.url });
|
||||
request(options).then((body) => {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Invoice', msg: 'Invoices List Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -43,7 +43,7 @@ export const addInvoice = (req, res, next) => {
|
|||
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/genInvoice';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
|
|
|
|||
|
|
@ -10,38 +10,28 @@ export const getRoute = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/network/getRoute/' + req.params.destPubkey + '/' + req.params.amount;
|
||||
request(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(200).json({ routes: body });
|
||||
return Promise.all(body.route?.map((rt) => getAlias(req.session.selectedNode, rt, 'id'))).then((values) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Network Routes with Alias Received', data: body });
|
||||
res.status(200).json(body || []);
|
||||
});
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Network', 'Query Routes Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const listNode = (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 + '/v1/network/listNode/' + req.params.id;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Node Lookup Finished', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Network', 'Node Lookup Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const listChannel = (req, res, next) => {
|
||||
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/network/listChannel/' + req.params.channelShortId;
|
||||
request(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -55,9 +45,10 @@ export const feeRates = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/network/feeRates/' + req.params.feeRateStyle;
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Network Fee Rates Received for ' + req.params.feeRateStyle, data: body });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Network', 'Fee Rates Error', req.session.selectedNode);
|
||||
|
|
@ -70,23 +61,38 @@ export const listNodes = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
const queryStr = req.query.liquidity_ads ? '?liquidity_ads=' + req.query.liquidity_ads : '';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/network/listNodes' + queryStr;
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listnodes';
|
||||
const filter_liquidity_ads = !!req.body.liquidity_ads;
|
||||
delete req.body.liquidity_ads;
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Network', msg: 'List Nodes URL' + options.url });
|
||||
request(options).then((body) => {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'List Nodes Finished', data: body });
|
||||
body.forEach((node) => {
|
||||
if (node.option_will_fund) {
|
||||
node.option_will_fund.lease_fee_base_msat = (node.option_will_fund.lease_fee_base_msat && typeof node.option_will_fund.lease_fee_base_msat === 'string' &&
|
||||
node.option_will_fund.lease_fee_base_msat.includes('msat')) ? node.option_will_fund.lease_fee_base_msat?.replace('msat', '') : node.option_will_fund.lease_fee_base_msat;
|
||||
node.option_will_fund.channel_fee_max_base_msat = (node.option_will_fund.channel_fee_max_base_msat && typeof node.option_will_fund.channel_fee_max_base_msat === 'string' &&
|
||||
node.option_will_fund.channel_fee_max_base_msat.includes('msat')) ? node.option_will_fund.channel_fee_max_base_msat?.replace('msat', '') : node.option_will_fund.channel_fee_max_base_msat;
|
||||
}
|
||||
return node;
|
||||
});
|
||||
res.status(200).json(body);
|
||||
let response = body.nodes;
|
||||
if (filter_liquidity_ads) {
|
||||
response = body.nodes.filter((node) => ((node.option_will_fund) ? node : null));
|
||||
}
|
||||
res.status(200).json(response);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Network', 'Node Lookup Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const getAlias = (selNode, peer, id) => {
|
||||
options.url = selNode.ln_server_url + '/v1/listnodes';
|
||||
if (!peer[id]) {
|
||||
logger.log({ selectedNode: selNode, level: 'ERROR', fileName: 'Network', msg: 'Empty Peer ID' });
|
||||
peer.alias = '';
|
||||
return peer;
|
||||
}
|
||||
options.body = { id: peer[id] };
|
||||
return request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Network', msg: 'Peer Alias Finished', data: body });
|
||||
peer.alias = body.nodes[0] && body.nodes[0].alias ? body.nodes[0].alias : peer[id].substring(0, 20);
|
||||
return peer;
|
||||
}).catch((errRes) => {
|
||||
common.handleError(errRes, 'Network', 'Peer Alias Error', selNode);
|
||||
peer.alias = peer[id].substring(0, 20);
|
||||
return peer;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ export const listOfferBookmarks = (req, res, next) => {
|
|||
};
|
||||
export const deleteOfferBookmark = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Deleting Offer Bookmark..' });
|
||||
databaseService.remove(req.session.selectedNode, CollectionsEnum.OFFERS, CollectionFieldsEnum.BOLT12, req.params.offerStr).then((deleteRes) => {
|
||||
databaseService.remove(req.session.selectedNode, CollectionsEnum.OFFERS, CollectionFieldsEnum.BOLT12, req.body.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.params.offerStr);
|
||||
res.status(204).json(req.body.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 });
|
||||
|
|
@ -33,15 +33,9 @@ export const listOffers = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/offers/listoffers';
|
||||
if (req.query.offer_id) {
|
||||
options.url = options.url + '?offer_id=' + req.query.offer_id;
|
||||
}
|
||||
if (req.query.active_only) {
|
||||
options.url = options.url + '?active_only=' + req.query.active_only;
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listoffers';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Offers', msg: 'Offers List URL', data: options.url });
|
||||
request(options).then((body) => {
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offers List Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -55,7 +49,7 @@ export const createOffer = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/offers/offer';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
|
|
@ -71,7 +65,7 @@ export const fetchOfferInvoice = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/offers/fetchInvoice';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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) => {
|
||||
|
|
@ -88,8 +82,9 @@ export const disableOffer = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/offers/disableOffer/' + req.params.offerID;
|
||||
request.delete(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(202).json(body);
|
||||
}).catch((errRes) => {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ export const getNewAddress = (req, res, next) => {
|
|||
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?addrType=' + req.query.type;
|
||||
request(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -42,10 +43,47 @@ export const getUTXOs = (req, res, next) => {
|
|||
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';
|
||||
request(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listfunds';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Funds List Received', data: body });
|
||||
res.status(200).json(body);
|
||||
// Local Remote Balance Calculation
|
||||
let lrBalance = { localBalance: 0, remoteBalance: 0, inactiveBalance: 0, pendingBalance: 0 };
|
||||
body.channels.forEach((channel) => {
|
||||
if ((channel.state === 'CHANNELD_NORMAL') && channel.connected === true) {
|
||||
lrBalance.localBalance = lrBalance.localBalance + channel.our_amount_msat;
|
||||
lrBalance.remoteBalance = lrBalance.remoteBalance + (channel.amount_msat - channel.our_amount_msat);
|
||||
}
|
||||
else if ((channel.state === 'CHANNELD_NORMAL') && channel.connected === false) {
|
||||
lrBalance.inactiveBalance = lrBalance.inactiveBalance + channel.our_amount_msat;
|
||||
}
|
||||
else if (channel.state === 'CHANNELD_AWAITING_LOCKIN' || channel.state === 'DUALOPEND_AWAITING_LOCKIN') {
|
||||
lrBalance.pendingBalance = lrBalance.pendingBalance + channel.our_amount_msat;
|
||||
}
|
||||
});
|
||||
lrBalance = {
|
||||
localBalance: lrBalance.localBalance / 1000,
|
||||
remoteBalance: lrBalance.remoteBalance / 1000,
|
||||
inactiveBalance: lrBalance.inactiveBalance / 1000,
|
||||
pendingBalance: lrBalance.pendingBalance / 1000
|
||||
};
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Onchain', msg: 'Local Remote Balance', data: lrBalance });
|
||||
// Onchain Balance Calculation
|
||||
let onchainBalance = { totalBalance: 0, confBalance: 0, unconfBalance: 0 };
|
||||
body.outputs.forEach((output) => {
|
||||
if (output.status === 'confirmed') {
|
||||
onchainBalance.confBalance = onchainBalance.confBalance + output.amount_msat;
|
||||
}
|
||||
else if (output.status === 'unconfirmed') {
|
||||
onchainBalance.unconfBalance = onchainBalance.unconfBalance + output.amount_msat;
|
||||
}
|
||||
});
|
||||
onchainBalance = {
|
||||
totalBalance: onchainBalance.confBalance / 1000,
|
||||
confBalance: (onchainBalance.confBalance - onchainBalance.unconfBalance) / 1000,
|
||||
unconfBalance: onchainBalance.unconfBalance / 1000
|
||||
};
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Onchain', msg: 'Onchain Balance Received', data: onchainBalance });
|
||||
res.status(200).json({ utxos: body.outputs || [], balance: onchainBalance, localRemoteBalance: lrBalance });
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'OnChain', 'List Funds Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
|
|
|
|||
|
|
@ -7,6 +7,18 @@ let options = null;
|
|||
const logger = Logger;
|
||||
const common = Common;
|
||||
const databaseService = Database;
|
||||
export const getMemo = (selNode, payment) => {
|
||||
options.url = selNode.ln_server_url + '/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 });
|
||||
payment.memo = res.description || '';
|
||||
return payment;
|
||||
}).catch((err) => {
|
||||
payment.memo = '';
|
||||
return payment;
|
||||
});
|
||||
};
|
||||
function paymentReducer(accumulator, currentPayment) {
|
||||
const currPayHash = currentPayment.payment_hash;
|
||||
if (!currentPayment.partid) {
|
||||
|
|
@ -69,10 +81,14 @@ export const listPayments = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/pay/listPayments';
|
||||
request(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listsendpays';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment List Received', data: body.payments });
|
||||
res.status(200).json(groupBy(body.payments));
|
||||
body.payments = body.payments && body.payments.length && body.payments.length > 0 ? groupBy(body.payments) : [];
|
||||
return Promise.all(body.payments?.map((payment) => ((payment.bolt11) ? getMemo(req.session.selectedNode, payment) : (payment.memo = '')))).then((values) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payments List with Memo Received', data: body.payments });
|
||||
res.status(200).json(body.payments);
|
||||
});
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Payments', 'List Payments Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
|
|
@ -83,27 +99,57 @@ export const postPayment = (req, res, next) => {
|
|||
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') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Keysend Payment..' });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/pay/keysend';
|
||||
options.body = req.body;
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/keysend';
|
||||
delete options_body.uiMessage;
|
||||
delete options_body.fromDialog;
|
||||
delete options_body.paymentType;
|
||||
delete options_body.title;
|
||||
delete options_body.issuer;
|
||||
delete options_body.bolt11;
|
||||
delete options_body.description;
|
||||
delete options_body.bolt12;
|
||||
delete options_body.zeroAmtOffer;
|
||||
delete options_body.pubkey;
|
||||
delete options_body.riskfactor;
|
||||
delete options_body.localinvreqid;
|
||||
delete options_body.exclude;
|
||||
delete options_body.maxfee;
|
||||
delete options_body.saveToDB;
|
||||
options.body = options_body;
|
||||
}
|
||||
else {
|
||||
if (req.body.paymentType === 'OFFER') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Sending Offer Payment..' });
|
||||
options.body = { invoice: req.body.invoice };
|
||||
}
|
||||
else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Sending Invoice Payment..' });
|
||||
options.body = req.body;
|
||||
}
|
||||
if (req.body.paymentType === 'OFFER') {
|
||||
// delete amount for zero amt offer also as fetchinvoice already has amount information
|
||||
delete options_body.amount_msat;
|
||||
}
|
||||
delete options_body.uiMessage;
|
||||
delete options_body.fromDialog;
|
||||
delete options_body.paymentType;
|
||||
delete options_body.destination;
|
||||
delete options_body.extratlvs;
|
||||
delete options_body.title;
|
||||
delete options_body.issuer;
|
||||
delete options_body.bolt12;
|
||||
delete options_body.zeroAmtOffer;
|
||||
delete options_body.pubkey;
|
||||
delete options_body.saveToDB;
|
||||
options.body = options_body;
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 = { bolt12: req.body.bolt12, amountMSat: (req.body.zeroAmtOffer ? 0 : req.body.amount), title: req.body.title, lastUpdatedAt: new Date(Date.now()).getTime() };
|
||||
const offerToUpdate = { 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import request from 'request-promise';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
import { getAlias } from './network.js';
|
||||
let options = null;
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
|
|
@ -10,15 +11,14 @@ export const getPeers = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/peer/listPeers';
|
||||
request(options).then((body) => {
|
||||
body.forEach((peer) => {
|
||||
if (!peer.alias || peer.alias === '') {
|
||||
peer.alias = peer.id.substring(0, 20);
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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;
|
||||
return Promise.all(peers?.map((peer) => getAlias(req.session.selectedNode, peer, 'id'))).then((values) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Sorted Peers List Received', data: body.peers });
|
||||
res.status(200).json(body.peers || []);
|
||||
});
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peers with Alias Received', data: body });
|
||||
res.status(200).json(body || []);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Peers', 'List Peers Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
|
|
@ -30,13 +30,14 @@ export const postPeer = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/peer/connect';
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/peer/listPeers';
|
||||
request(options).then((listPeersRes) => {
|
||||
const peers = listPeersRes ? common.newestOnTop(listPeersRes, 'id', req.body.id) : [];
|
||||
const listOptions = common.getOptions(req);
|
||||
listOptions.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(201).json(peers);
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -54,8 +55,9 @@ export const deletePeer = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/peer/disconnect/' + req.params.peerId + '?force=' + req.query.force;
|
||||
request.delete(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(204).json({});
|
||||
}).catch((errRes) => {
|
||||
|
|
|
|||
|
|
@ -4,44 +4,15 @@ import { Common } from '../../utils/common.js';
|
|||
let options = null;
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
export const decodePaymentFromPaymentRequest = (selNode, payment) => {
|
||||
options.url = selNode.ln_server_url + '/v1/utility/decode/' + payment;
|
||||
return request(options).then((res) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment Decode Received', data: res });
|
||||
return res;
|
||||
}).catch((err) => { });
|
||||
};
|
||||
export const decodePayments = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', 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(',');
|
||||
return Promise.all(paymentsArr?.map((payment) => decodePaymentFromPaymentRequest(req.session.selectedNode, payment))).
|
||||
then((values) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment List Decoded', data: values });
|
||||
res.status(200).json(values);
|
||||
}).
|
||||
catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Payments', 'Decode Payments Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
}
|
||||
else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Empty Payment List Decoded' });
|
||||
return res.status(200).json([]);
|
||||
}
|
||||
};
|
||||
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/utility/decode/' + req.params.payReq;
|
||||
request(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -55,8 +26,8 @@ export const signMessage = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/utility/signMessage';
|
||||
options.form = { message: req.body.message };
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(201).json(body);
|
||||
|
|
@ -71,8 +42,9 @@ export const verifyMessage = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/utility/checkMessage/' + req.body.message + '/' + req.body.signature;
|
||||
request.get(options, (error, response, body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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 });
|
||||
res.status(201).json(body);
|
||||
}).catch((errRes) => {
|
||||
|
|
@ -86,8 +58,8 @@ export const listConfigs = (req, res, next) => {
|
|||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/utility/listConfigs';
|
||||
request(options).then((body) => {
|
||||
options.url = req.session.selectedNode.ln_server_url + '/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);
|
||||
}).catch((errRes) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import * as fs from 'fs';
|
||||
import { join } from 'path';
|
||||
import WebSocket from 'ws';
|
||||
import socketIOClient from 'socket.io-client';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
import { WSServer } from '../../utils/webSocketServer.js';
|
||||
|
|
@ -12,7 +10,7 @@ export class CLWebSocketClient {
|
|||
this.webSocketClients = [];
|
||||
this.reconnectTimeOut = null;
|
||||
this.waitTime = 0.5;
|
||||
this.reconnet = (clWsClt) => {
|
||||
this.reconnect = (clWsClt) => {
|
||||
if (this.reconnectTimeOut) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -36,7 +34,7 @@ export class CLWebSocketClient {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if ((!clientExists.webSocketClient || clientExists.webSocketClient.readyState !== WebSocket.OPEN) && selectedNode.ln_server_url) {
|
||||
if ((!clientExists.webSocketClient || !clientExists.webSocketClient.connected) && selectedNode.ln_server_url) {
|
||||
clientExists.reConnect = true;
|
||||
this.connectWithClient(clientExists);
|
||||
}
|
||||
|
|
@ -48,42 +46,50 @@ export class CLWebSocketClient {
|
|||
};
|
||||
this.connectWithClient = (clWsClt) => {
|
||||
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Connecting to the Core Lightning\'s Websocket Server..' });
|
||||
const WS_LINK = (clWsClt.selectedNode.ln_server_url)?.replace(/^http/, 'ws') + '/v1/ws';
|
||||
const mcrnHexEncoded = Buffer.from(fs.readFileSync(join(clWsClt.selectedNode.macaroon_path, 'access.macaroon'))).toString('hex');
|
||||
clWsClt.webSocketClient = new WebSocket(WS_LINK, [mcrnHexEncoded, 'hex'], { rejectUnauthorized: false });
|
||||
clWsClt.webSocketClient.onopen = () => {
|
||||
try {
|
||||
if (!clWsClt.selectedNode.rune_value) {
|
||||
clWsClt.selectedNode.rune_value = this.common.getRuneValue(clWsClt.selectedNode.rune_path);
|
||||
}
|
||||
clWsClt.webSocketClient = socketIOClient(clWsClt.selectedNode.ln_server_url, {
|
||||
extraHeaders: { rune: clWsClt.selectedNode.rune_value },
|
||||
transports: ['websocket'],
|
||||
secure: true,
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
clWsClt.webSocketClient.on('connect', () => {
|
||||
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Connected to the Core Lightning\'s Websocket Server..' });
|
||||
this.waitTime = 0.5;
|
||||
};
|
||||
clWsClt.webSocketClient.onclose = (e) => {
|
||||
});
|
||||
clWsClt.webSocketClient.on('disconnect', (reason) => {
|
||||
if (clWsClt && clWsClt.selectedNode && clWsClt.selectedNode.ln_implementation === 'CLN') {
|
||||
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Web socket disconnected, will reconnect again...' });
|
||||
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.reconnet(clWsClt);
|
||||
this.reconnect(clWsClt);
|
||||
}
|
||||
}
|
||||
};
|
||||
clWsClt.webSocketClient.onmessage = (msg) => {
|
||||
});
|
||||
clWsClt.webSocketClient.on('message', (msg) => {
|
||||
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'DEBUG', fileName: 'CLWebSocket', msg: 'Received message from the server..', data: msg.data });
|
||||
msg = (typeof msg.data === 'string') ? JSON.parse(msg.data) : msg.data;
|
||||
msg['source'] = 'CLN';
|
||||
const msgStr = JSON.stringify(msg);
|
||||
this.wsServer.sendEventsToAllLNClients(msgStr, clWsClt.selectedNode);
|
||||
};
|
||||
clWsClt.webSocketClient.onerror = (err) => {
|
||||
this.wsServer.sendEventsToAllLNClients(JSON.stringify({ source: 'CLN', data: msg }), clWsClt.selectedNode);
|
||||
});
|
||||
clWsClt.webSocketClient.on('error', (err) => {
|
||||
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'ERROR', fileName: 'CLWebSocket', 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, clWsClt.selectedNode);
|
||||
clWsClt.webSocketClient.close();
|
||||
if (clWsClt.reConnect) {
|
||||
this.reconnet(clWsClt);
|
||||
this.reconnect(clWsClt);
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
this.disconnect = (selectedNode) => {
|
||||
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
|
||||
if (clientExists && clientExists.webSocketClient && clientExists.webSocketClient.readyState === WebSocket.OPEN) {
|
||||
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..' });
|
||||
clientExists.reConnect = false;
|
||||
clientExists.webSocketClient.close();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
export class CommonSelectedNode {
|
||||
constructor(options, ln_server_url, macaroon_path, ln_api_password, swap_server_url, boltz_server_url, config_path, rtl_conf_file_path, swap_macaroon_path, boltz_macaroon_path, bitcoind_config_path, channel_backup_path, log_level, log_file, index, ln_node, ln_implementation, user_persona, theme_mode, theme_color, unannounced_channels, fiat_conversion, currency_unit, ln_version, api_version, enable_offers, enable_peerswap) {
|
||||
constructor(options, ln_server_url, macaroon_path, macaroon_value, rune_path, rune_value, ln_api_password, swap_server_url, boltz_server_url, config_path, rtl_conf_file_path, swap_macaroon_path, boltz_macaroon_path, bitcoind_config_path, channel_backup_path, log_level, log_file, index, ln_node, ln_implementation, user_persona, theme_mode, theme_color, unannounced_channels, fiat_conversion, currency_unit, ln_version, api_version, enable_offers, enable_peerswap) {
|
||||
this.options = options;
|
||||
this.ln_server_url = ln_server_url;
|
||||
this.macaroon_path = macaroon_path;
|
||||
this.macaroon_value = macaroon_value;
|
||||
this.rune_path = rune_path;
|
||||
this.rune_value = rune_value;
|
||||
this.ln_api_password = ln_api_password;
|
||||
this.swap_server_url = swap_server_url;
|
||||
this.boltz_server_url = boltz_server_url;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { listChannels, listPeerChannels, openChannel, setChannelFee, closeChannel, getLocalRemoteBalance, listForwards, funderUpdatePolicy, listForwardsPaginated } from '../../controllers/cln/channels.js';
|
||||
import { listPeerChannels, openChannel, setChannelFee, closeChannel, listForwards, funderUpdatePolicy } from '../../controllers/cln/channels.js';
|
||||
const router = Router();
|
||||
router.get('/listChannels', isAuthenticated, listChannels);
|
||||
router.get('/listPeerChannels', isAuthenticated, listPeerChannels);
|
||||
router.post('/', isAuthenticated, openChannel);
|
||||
router.post('/setChannelFee', isAuthenticated, setChannelFee);
|
||||
router.delete('/:channelId', isAuthenticated, closeChannel);
|
||||
router.get('/localRemoteBalance', isAuthenticated, getLocalRemoteBalance);
|
||||
router.get('/listForwards', isAuthenticated, listForwards);
|
||||
router.get('/listForwardsPaginated', isAuthenticated, listForwardsPaginated);
|
||||
router.post('/close/', isAuthenticated, closeChannel);
|
||||
router.post('/listForwards', isAuthenticated, listForwards);
|
||||
router.post('/funderUpdate', isAuthenticated, funderUpdatePolicy);
|
||||
export default router;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import infoCLRoutes from './getInfo.js';
|
||||
import feesCLRoutes from './fees.js';
|
||||
import balanceCLRoutes from './balance.js';
|
||||
import channelsCLRoutes from './channels.js';
|
||||
import invoicesCLRoutes from './invoices.js';
|
||||
import onChainCLRoutes from './onchain.js';
|
||||
|
|
@ -14,8 +12,6 @@ import utilityCLRoutes from './utility.js';
|
|||
const router = Router();
|
||||
const clRoutes = [
|
||||
{ path: '/getinfo', route: infoCLRoutes },
|
||||
{ path: '/fees', route: feesCLRoutes },
|
||||
{ path: '/balance', route: balanceCLRoutes },
|
||||
{ path: '/channels', route: channelsCLRoutes },
|
||||
{ path: '/invoices', route: invoicesCLRoutes },
|
||||
{ path: '/onchain', route: onChainCLRoutes },
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ const { Router } = exprs;
|
|||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { listInvoices, addInvoice, deleteExpiredInvoice } from '../../controllers/cln/invoices.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, listInvoices);
|
||||
router.post('/lookup/', isAuthenticated, listInvoices);
|
||||
router.post('/', isAuthenticated, addInvoice);
|
||||
router.delete('/', isAuthenticated, deleteExpiredInvoice);
|
||||
router.post('/delete/', isAuthenticated, deleteExpiredInvoice);
|
||||
export default router;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getRoute, listNode, listChannel, feeRates, listNodes } from '../../controllers/cln/network.js';
|
||||
import { getRoute, listChannels, feeRates, listNodes } from '../../controllers/cln/network.js';
|
||||
const router = Router();
|
||||
router.get('/getRoute/:destPubkey/:amount', isAuthenticated, getRoute);
|
||||
router.get('/listNode/:id', isAuthenticated, listNode);
|
||||
router.get('/listChannel/:channelShortId', isAuthenticated, listChannel);
|
||||
router.get('/feeRates/:feeRateStyle', isAuthenticated, feeRates);
|
||||
router.get('/listNodes', isAuthenticated, listNodes);
|
||||
router.post('/listNodes', isAuthenticated, listNodes);
|
||||
router.post('/getRoute', isAuthenticated, getRoute);
|
||||
router.post('/feeRates', isAuthenticated, feeRates);
|
||||
router.post('/listChannels', isAuthenticated, listChannels);
|
||||
export default router;
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import { isAuthenticated } from '../../utils/authCheck.js';
|
|||
import { listOfferBookmarks, deleteOfferBookmark, listOffers, disableOffer, createOffer, fetchOfferInvoice } from '../../controllers/cln/offers.js';
|
||||
const router = Router();
|
||||
router.get('/offerbookmarks', isAuthenticated, listOfferBookmarks);
|
||||
router.delete('/offerbookmark/:offerStr', isAuthenticated, deleteOfferBookmark);
|
||||
router.post('/offerbookmark/delete', isAuthenticated, deleteOfferBookmark);
|
||||
router.get('/', isAuthenticated, listOffers);
|
||||
router.post('/', isAuthenticated, createOffer);
|
||||
router.post('/fetchOfferInvoice', isAuthenticated, fetchOfferInvoice);
|
||||
router.delete('/:offerID', isAuthenticated, disableOffer);
|
||||
router.post('/disableOffer', isAuthenticated, disableOffer);
|
||||
export default router;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ const { Router } = exprs;
|
|||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getNewAddress, onChainWithdraw, getUTXOs } from '../../controllers/cln/onchain.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, getNewAddress);
|
||||
router.post('/', isAuthenticated, onChainWithdraw);
|
||||
router.post('/newaddr', isAuthenticated, getNewAddress);
|
||||
router.get('/utxos/', isAuthenticated, getUTXOs);
|
||||
export default router;
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ import { getPeers, postPeer, deletePeer } from '../../controllers/cln/peers.js';
|
|||
const router = Router();
|
||||
router.get('/', isAuthenticated, getPeers);
|
||||
router.post('/', isAuthenticated, postPeer);
|
||||
router.delete('/:peerId', isAuthenticated, deletePeer);
|
||||
router.post('/disconnect/', isAuthenticated, deletePeer);
|
||||
export default router;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { decodePayments, decodePayment, signMessage, verifyMessage, listConfigs } from '../../controllers/cln/utility.js';
|
||||
import { decodePayment, signMessage, verifyMessage, listConfigs } from '../../controllers/cln/utility.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, decodePayments);
|
||||
router.get('/decode/:payReq', isAuthenticated, decodePayment);
|
||||
router.post('/decode', isAuthenticated, decodePayment);
|
||||
router.post('/sign', isAuthenticated, signMessage);
|
||||
router.post('/verify', isAuthenticated, verifyMessage);
|
||||
router.get('/listConfigs', isAuthenticated, listConfigs);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import eclRoutes from '../routes/eclair/index.js';
|
|||
import { Database } from './database.js';
|
||||
import { Common } from './common.js';
|
||||
import { Logger } from './logger.js';
|
||||
import { CLWSClient } from '../controllers/cln/webSocketClient.js';
|
||||
import { ECLWSClient } from '../controllers/eclair/webSocketClient.js';
|
||||
import { LNDWSClient } from '../controllers/lnd/webSocketClient.js';
|
||||
const ONE_DAY = 1000 * 60 * 60 * 24;
|
||||
|
|
@ -23,7 +22,7 @@ export class ExpressApplication {
|
|||
this.logger = Logger;
|
||||
this.common = Common;
|
||||
this.eclWsClient = ECLWSClient;
|
||||
this.clWsClient = CLWSClient;
|
||||
// public clWsClient: CLWebSocketClient = CLWSClient;
|
||||
this.lndWsClient = LNDWSClient;
|
||||
this.databaseService = Database;
|
||||
this.directoryName = dirname(fileURLToPath(import.meta.url));
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export class CommonService {
|
|||
this.rtl_cookie_path = '';
|
||||
this.logout_redirect_link = '';
|
||||
this.cookie_value = '';
|
||||
this.ln_version = '';
|
||||
this.api_version = '';
|
||||
this.secret_key = crypto.randomBytes(64).toString('hex');
|
||||
this.read_dummy_data = false;
|
||||
|
|
@ -68,8 +69,9 @@ export class CommonService {
|
|||
};
|
||||
this.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() !== 'ECL') ? 'GET' : 'POST';
|
||||
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;
|
||||
}
|
||||
|
|
@ -89,7 +91,15 @@ export class CommonService {
|
|||
if (req.session.selectedNode && req.session.selectedNode.ln_implementation) {
|
||||
switch (req.session.selectedNode.ln_implementation.toUpperCase()) {
|
||||
case 'CLN':
|
||||
req.session.selectedNode.options.headers = { macaroon: Buffer.from(fs.readFileSync(join(req.session.selectedNode.macaroon_path, 'access.macaroon'))).toString('base64') };
|
||||
try {
|
||||
if (!req.session.selectedNode.rune_value) {
|
||||
req.session.selectedNode.rune_value = this.getRuneValue(req.session.selectedNode.rune_path);
|
||||
}
|
||||
req.session.selectedNode.options.headers = { rune: req.session.selectedNode.rune_value };
|
||||
}
|
||||
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') };
|
||||
|
|
@ -115,6 +125,17 @@ export class CommonService {
|
|||
return { status: 502, message: err };
|
||||
}
|
||||
};
|
||||
this.getRuneValue = (rune_path) => {
|
||||
const data = fs.readFileSync(rune_path, 'utf8');
|
||||
const pattern = /LIGHTNING_RUNE="(?<runeValue>[^"]+)"/;
|
||||
const match = data.match(pattern);
|
||||
if (match.groups.runeValue) {
|
||||
return match.groups.runeValue;
|
||||
}
|
||||
else {
|
||||
throw new Error('Rune not found in the file.');
|
||||
}
|
||||
};
|
||||
this.setOptions = (req) => {
|
||||
if (this.nodes[0].options && this.nodes[0].options.headers) {
|
||||
return;
|
||||
|
|
@ -131,7 +152,15 @@ export class CommonService {
|
|||
if (node.ln_implementation) {
|
||||
switch (node.ln_implementation.toUpperCase()) {
|
||||
case 'CLN':
|
||||
node.options.headers = { macaroon: Buffer.from(fs.readFileSync(join(node.macaroon_path, 'access.macaroon'))).toString('base64') };
|
||||
try {
|
||||
if (!node.rune_value) {
|
||||
node.rune_value = this.getRuneValue(node.rune_path);
|
||||
}
|
||||
node.options.headers = { rune: node.rune_value };
|
||||
}
|
||||
catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
break;
|
||||
case 'ECL':
|
||||
node.options.headers = { authorization: 'Basic ' + Buffer.from(':' + node.ln_api_password).toString('base64') };
|
||||
|
|
@ -424,12 +453,25 @@ export class CommonService {
|
|||
});
|
||||
};
|
||||
this.isVersionCompatible = (currentVersion, checkVersion) => {
|
||||
if (currentVersion) {
|
||||
const versionsArr = currentVersion.trim()?.replace('v', '').split('-')[0].split('.') || [];
|
||||
const checkVersionsArr = checkVersion.split('.');
|
||||
return (+versionsArr[0] > +checkVersionsArr[0]) ||
|
||||
(+versionsArr[0] === +checkVersionsArr[0] && +versionsArr[1] > +checkVersionsArr[1]) ||
|
||||
(+versionsArr[0] === +checkVersionsArr[0] && +versionsArr[1] === +checkVersionsArr[1] && +versionsArr[2] >= +checkVersionsArr[2]);
|
||||
if (currentVersion && currentVersion !== '') {
|
||||
// eslint-disable-next-line prefer-named-capture-group
|
||||
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 });
|
||||
const currentVersionArr = match[1].split('.') || [];
|
||||
currentVersionArr[1] = currentVersionArr[1].substring(0, 2);
|
||||
const checkVersionsArr = checkVersion.split('.');
|
||||
checkVersionsArr[1] = checkVersionsArr[1].substring(0, 2);
|
||||
return (+currentVersionArr[0] > +checkVersionsArr[0]) ||
|
||||
(+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 });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -148,25 +148,40 @@ export class ConfigService {
|
|||
if (this.common.nodes[idx].ln_implementation === 'CLT') {
|
||||
this.common.nodes[idx].ln_implementation = 'CLN';
|
||||
}
|
||||
if (this.common.nodes[idx].ln_implementation !== 'ECL' && process?.env?.MACAROON_PATH && process?.env?.MACAROON_PATH.trim() !== '') {
|
||||
this.common.nodes[idx].macaroon_path = process?.env?.MACAROON_PATH;
|
||||
}
|
||||
else if (this.common.nodes[idx].ln_implementation !== 'ECL' && node.Authentication && node.Authentication.macaroonPath && node.Authentication.macaroonPath.trim() !== '') {
|
||||
this.common.nodes[idx].macaroon_path = node.Authentication.macaroonPath;
|
||||
}
|
||||
else if (this.common.nodes[idx].ln_implementation !== 'ECL') {
|
||||
this.errMsg = 'Please set macaroon path for node index ' + node.index + ' in RTL-Config.json!';
|
||||
}
|
||||
if (this.common.nodes[idx].ln_implementation === '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;
|
||||
}
|
||||
else {
|
||||
this.common.nodes[idx].ln_api_password = '';
|
||||
}
|
||||
switch (this.common.nodes[idx].ln_implementation) {
|
||||
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;
|
||||
}
|
||||
else {
|
||||
this.errMsg = 'Please set rune path for node index ' + node.index + ' in RTL-Config.json!';
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
else {
|
||||
this.common.nodes[idx].ln_api_password = '';
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ export class RTLWebSocketServer {
|
|||
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 });
|
||||
this.logger.log({ selectedNode: !selectedNode ? this.common.initSelectedNode : selectedNode, level: 'DEBUG', fileName: 'WebSocketServer', msg: 'Broadcasting message to client...: ' + client.clientId + ', Message: ' + newMessage });
|
||||
client.send(newMessage);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue