mirror of
https://github.com/Ride-The-Lightning/RTL.git
synced 2024-11-19 09:50:36 +01:00
Backend controllers
This commit is contained in:
parent
2ea645152c
commit
d361df0cff
@ -10,19 +10,24 @@ export const getBalance = (req, res, next) => {
|
|||||||
if (options.error) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||||
}
|
}
|
||||||
options.url = req.session.selectedNode.ln_server_url + '/v1/getBalance';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/listfunds';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
if (!body.totalBalance) {
|
let confBalance = 0;
|
||||||
body.totalBalance = 0;
|
let unconfBalance = 0;
|
||||||
}
|
let totalBalance = 0;
|
||||||
if (!body.confBalance) {
|
const versionCompatible = common.isVersionCompatible('23.02');
|
||||||
body.confBalance = 0;
|
body.outputs.forEach((output) => {
|
||||||
}
|
if (output.status === 'confirmed') {
|
||||||
if (!body.unconfBalance) {
|
confBalance = confBalance + (versionCompatible ? (output.amount_msat / 1000) : output.value);
|
||||||
body.unconfBalance = 0;
|
}
|
||||||
}
|
else if (output.status === 'unconfirmed') {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Balance', msg: 'Balance Received', data: body });
|
unconfBalance = unconfBalance + (versionCompatible ? (output.amount_msat / 1000) : output.value);
|
||||||
res.status(200).json(body);
|
}
|
||||||
|
});
|
||||||
|
totalBalance = confBalance + unconfBalance;
|
||||||
|
const walBalance = { totalBalance: totalBalance || 0, confBalance: confBalance || 0, unconfBalance: unconfBalance || 0 };
|
||||||
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Balance', msg: 'Balance Received', data: walBalance });
|
||||||
|
res.status(200).json(walBalance);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Balance', 'Get Balance Error', req.session.selectedNode);
|
const err = common.handleError(errRes, 'Balance', 'Get Balance Error', req.session.selectedNode);
|
||||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||||
|
@ -10,59 +10,55 @@ export const listPeerChannels = (req, res, next) => {
|
|||||||
if (options.error) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: 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';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/listpeerchannels';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
body?.map((channel) => {
|
body.channels.map((channel) => {
|
||||||
if (!channel.alias || channel.alias === '') {
|
|
||||||
channel.alias = channel.peer_id.substring(0, 20);
|
|
||||||
}
|
|
||||||
const local = channel.to_us_msat || 0;
|
const local = channel.to_us_msat || 0;
|
||||||
const remote = (channel.total_msat - local) || 0;
|
const remote = (channel.total_msat - local) || 0;
|
||||||
const total = channel.total_msat || 0;
|
const total = channel.total_msat || 0;
|
||||||
channel.to_them_msat = remote;
|
// return getAliasForChannel(channel).then(channelAlias => {
|
||||||
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3);
|
return {
|
||||||
return channel;
|
peer_id: channel.peer_id,
|
||||||
|
peer_connected: channel.peer_connected,
|
||||||
|
opener: channel.opener,
|
||||||
|
owner: channel.owner,
|
||||||
|
short_channel_id: channel.short_channel_id,
|
||||||
|
channel_id: channel.channel_id,
|
||||||
|
funding_txid: channel.funding_txid,
|
||||||
|
private: channel.private,
|
||||||
|
to_us_msat: channel.to_us_msat,
|
||||||
|
total_msat: channel.total_msat,
|
||||||
|
their_reserve_msat: channel.their_reserve_msat,
|
||||||
|
our_reserve_msat: channel.our_reserve_msat,
|
||||||
|
spendable_msat: channel.spendable_msat,
|
||||||
|
receivable_msat: channel.receivable_msat,
|
||||||
|
funding: channel.funding,
|
||||||
|
state: channel.state,
|
||||||
|
fee_base_msat: channel.fee_base_msat,
|
||||||
|
fee_proportional_millionths: channel.fee_proportional_millionths,
|
||||||
|
dust_limit_msat: channel.dust_limit_msat,
|
||||||
|
htlcs: channel.htlcs,
|
||||||
|
features: channel.features,
|
||||||
|
alias: channel.peer_id.substring(0, 20),
|
||||||
|
to_them_msat: remote,
|
||||||
|
balancedness: (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3)
|
||||||
|
};
|
||||||
});
|
});
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: body });
|
}).then((listPeerChannels) => {
|
||||||
res.status(200).json(body);
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: listPeerChannels });
|
||||||
|
res.status(200).json(listPeerChannels);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Channels', 'List Peer Channels Error', req.session.selectedNode);
|
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 });
|
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.post(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) => {
|
export const openChannel = (req, res, next) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Opening Channel..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Opening Channel..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: 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;
|
options.body = req.body;
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Open Channel Options', data: options.body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Open Channel Options', data: options.body });
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
@ -79,7 +75,7 @@ export const setChannelFee = (req, res, next) => {
|
|||||||
if (options.error) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: 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;
|
options.body = req.body;
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Update Channel Policy Options', data: options.body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Update Channel Policy Options', data: options.body });
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
@ -97,10 +93,10 @@ export const closeChannel = (req, res, next) => {
|
|||||||
if (options.error) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: 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/close';
|
||||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/closeChannel/' + req.params.channelId + unilateralTimeoutQuery;
|
options.body = { channelId: req.params.channelId, unilaterlaltimeout: req.query.force ? 1 : null };
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Closing Channel', data: options.url });
|
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 });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Channel Closed', data: body });
|
||||||
res.status(204).json(body);
|
res.status(204).json(body);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
@ -114,16 +110,33 @@ export const getLocalRemoteBalance = (req, res, next) => {
|
|||||||
if (options.error) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: 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';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/listfunds';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
if (!body.localBalance) {
|
const versionCompatible = common.isVersionCompatible('23.02');
|
||||||
body.localBalance = 0;
|
let localBalance = 0;
|
||||||
}
|
let remoteBalance = 0;
|
||||||
if (!body.remoteBalance) {
|
let pendingBalance = 0;
|
||||||
body.remoteBalance = 0;
|
let inactiveBalance = 0;
|
||||||
|
body.channels.forEach((channel) => {
|
||||||
|
if ((channel.state === 'CHANNELD_NORMAL') && channel.connected === true) {
|
||||||
|
localBalance = localBalance + (versionCompatible ? (channel.our_amount_msat) : channel.channel_sat);
|
||||||
|
remoteBalance = remoteBalance + (versionCompatible ? (channel.amount_msat - channel.our_amount_msat) : (channel.channel_total_sat - channel.channel_sat));
|
||||||
|
}
|
||||||
|
else if ((channel.state === 'CHANNELD_NORMAL') && channel.connected === false) {
|
||||||
|
inactiveBalance = inactiveBalance + (versionCompatible ? (channel.our_amount_msat) : channel.channel_sat);
|
||||||
|
}
|
||||||
|
else if (channel.state === 'CHANNELD_AWAITING_LOCKIN' || channel.state === 'DUALOPEND_AWAITING_LOCKIN') {
|
||||||
|
pendingBalance = pendingBalance + (versionCompatible ? (channel.our_amount_msat) : channel.channel_sat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (versionCompatible) {
|
||||||
|
localBalance = localBalance / 1000;
|
||||||
|
remoteBalance = remoteBalance / 1000;
|
||||||
|
inactiveBalance = inactiveBalance / 1000;
|
||||||
|
pendingBalance = pendingBalance / 1000;
|
||||||
}
|
}
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Local Remote Balance Received', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Local Remote Balance Received', data: body });
|
||||||
res.status(200).json(body);
|
res.status(200).json({ localBalance: localBalance || 0, remoteBalance: remoteBalance || 0, inactiveBalance: inactiveBalance || 0, pendingBalance: pendingBalance || 0 });
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Channels', 'Local Remote Balance Error', req.session.selectedNode);
|
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 });
|
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||||
@ -135,10 +148,11 @@ export const listForwards = (req, res, next) => {
|
|||||||
if (options.error) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: 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');
|
options.url = req.session.selectedNode.ln_server_url + '/v1/listforwards';
|
||||||
|
options.body = { status: req.query.status || 'settled' };
|
||||||
request.get(options).then((body) => {
|
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 });
|
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);
|
res.status(200).json(!body.forwards ? [] : (req.query.status === 'failed' || req.query.status === 'local_failed') ? body.forwards.slice(Math.max(0, body.forwards.length - 1000), Math.max(1000, body.forwards.length)).reverse() : body.forwards.reverse());
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Channels', 'Forwarding History Error', req.session.selectedNode);
|
const err = common.handleError(errRes, 'Channels', 'Forwarding History Error', req.session.selectedNode);
|
||||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||||
@ -150,10 +164,10 @@ export const funderUpdatePolicy = (req, res, next) => {
|
|||||||
if (options.error) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: 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';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/funderupdate';
|
||||||
if (req.body && req.body.policy) {
|
// if (req.body && req.body.policy) {
|
||||||
options.body = req.body;
|
// options.body = req.body;
|
||||||
}
|
// }
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Funder Update Body', data: options.body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Funder Update Body', data: options.body });
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Funder Policy Received', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Funder Policy Received', data: body });
|
||||||
@ -165,23 +179,3 @@ export const funderUpdatePolicy = (req, res, next) => {
|
|||||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
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) {
|
if (options.error) {
|
||||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||||
}
|
}
|
||||||
options.url = req.session.selectedNode.ln_server_url + '/v1/getFees';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/getinfo';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
if (!body.feeCollected) {
|
const versionCompatible = common.isVersionCompatible('23.02');
|
||||||
body.feeCollected = 0;
|
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 });
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Fee Received', data: body });
|
res.status(200).json(feeData);
|
||||||
res.status(200).json(body);
|
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Fees', 'Get Fees Error', req.session.selectedNode);
|
const err = common.handleError(errRes, 'Fees', 'Get Fees Error', req.session.selectedNode);
|
||||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||||
|
@ -48,8 +48,9 @@ export const getInfo = (req, res, next) => {
|
|||||||
body.uris.push(body.id + '@' + addr.address + ':' + addr.port);
|
body.uris.push(body.id + '@' + addr.address + ':' + addr.port);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
req.session.selectedNode.api_version = body.api_version || '';
|
common.setVersion(body.version || '');
|
||||||
req.session.selectedNode.ln_version = body.version || '';
|
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.' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Connecting to the Core Lightning\'s Websocket Server.' });
|
||||||
clWsClient.updateSelectedNode(req.session.selectedNode);
|
clWsClient.updateSelectedNode(req.session.selectedNode);
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Node Information Received', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Node Information Received', data: body });
|
||||||
|
@ -12,7 +12,7 @@ export const deleteExpiredInvoice = (req, res, next) => {
|
|||||||
}
|
}
|
||||||
const queryStr = req.query.maxExpiry ? '?maxexpiry=' + req.query.maxExpiry : '';
|
const queryStr = req.query.maxExpiry ? '?maxexpiry=' + req.query.maxExpiry : '';
|
||||||
options.url = req.session.selectedNode.ln_server_url + '/v1/invoice/delExpiredInvoice' + queryStr;
|
options.url = req.session.selectedNode.ln_server_url + '/v1/invoice/delExpiredInvoice' + queryStr;
|
||||||
request.delete(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Invoices Deleted', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Invoices Deleted', data: body });
|
||||||
res.status(204).json({ status: 'Invoice Deleted Successfully' });
|
res.status(204).json({ status: 'Invoice Deleted Successfully' });
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
|
@ -89,7 +89,7 @@ export const disableOffer = (req, res, next) => {
|
|||||||
return res.status(options.statusCode).json({ message: options.message, error: 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;
|
options.url = req.session.selectedNode.ln_server_url + '/v1/offers/disableOffer/' + req.params.offerID;
|
||||||
request.delete(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offer Disabled', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offer Disabled', data: body });
|
||||||
res.status(202).json(body);
|
res.status(202).json(body);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
|
@ -55,7 +55,7 @@ export const deletePeer = (req, res, next) => {
|
|||||||
return res.status(options.statusCode).json({ message: options.message, error: 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;
|
options.url = req.session.selectedNode.ln_server_url + '/v1/peer/disconnect/' + req.params.peerId + '?force=' + req.query.force;
|
||||||
request.delete(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peer Disconnected', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peer Disconnected', data: body });
|
||||||
res.status(204).json({});
|
res.status(204).json({});
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
|
@ -72,7 +72,7 @@ export const verifyMessage = (req, res, next) => {
|
|||||||
return res.status(options.statusCode).json({ message: options.message, error: 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;
|
options.url = req.session.selectedNode.ln_server_url + '/v1/utility/checkMessage/' + req.body.message + '/' + req.body.signature;
|
||||||
request.get(options, (error, response, body) => {
|
request.post(options, (error, response, body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body });
|
||||||
res.status(201).json(body);
|
res.status(201).json(body);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
import exprs from 'express';
|
import exprs from 'express';
|
||||||
const { Router } = exprs;
|
const { Router } = exprs;
|
||||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
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, getLocalRemoteBalance, listForwards, funderUpdatePolicy } from '../../controllers/cln/channels.js';
|
||||||
const router = Router();
|
const router = Router();
|
||||||
router.get('/listChannels', isAuthenticated, listChannels);
|
|
||||||
router.get('/listPeerChannels', isAuthenticated, listPeerChannels);
|
router.get('/listPeerChannels', isAuthenticated, listPeerChannels);
|
||||||
router.post('/', isAuthenticated, openChannel);
|
router.post('/', isAuthenticated, openChannel);
|
||||||
router.post('/setChannelFee', isAuthenticated, setChannelFee);
|
router.post('/setChannelFee', isAuthenticated, setChannelFee);
|
||||||
router.delete('/:channelId', isAuthenticated, closeChannel);
|
router.delete('/:channelId', isAuthenticated, closeChannel);
|
||||||
router.get('/localRemoteBalance', isAuthenticated, getLocalRemoteBalance);
|
router.get('/localRemoteBalance', isAuthenticated, getLocalRemoteBalance);
|
||||||
router.get('/listForwards', isAuthenticated, listForwards);
|
router.get('/listForwards', isAuthenticated, listForwards);
|
||||||
router.get('/listForwardsPaginated', isAuthenticated, listForwardsPaginated);
|
|
||||||
router.post('/funderUpdate', isAuthenticated, funderUpdatePolicy);
|
router.post('/funderUpdate', isAuthenticated, funderUpdatePolicy);
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -20,6 +20,7 @@ export class CommonService {
|
|||||||
this.rtl_cookie_path = '';
|
this.rtl_cookie_path = '';
|
||||||
this.logout_redirect_link = '';
|
this.logout_redirect_link = '';
|
||||||
this.cookie_value = '';
|
this.cookie_value = '';
|
||||||
|
this.ln_version = '';
|
||||||
this.api_version = '';
|
this.api_version = '';
|
||||||
this.secret_key = crypto.randomBytes(64).toString('hex');
|
this.secret_key = crypto.randomBytes(64).toString('hex');
|
||||||
this.read_dummy_data = false;
|
this.read_dummy_data = false;
|
||||||
@ -423,13 +424,29 @@ export class CommonService {
|
|||||||
fs.writeFile(channel_backup_file, '', () => { });
|
fs.writeFile(channel_backup_file, '', () => { });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
this.isVersionCompatible = (currentVersion, checkVersion) => {
|
this.setVersion = (version) => {
|
||||||
if (currentVersion) {
|
this.ln_version = version;
|
||||||
const versionsArr = currentVersion.trim()?.replace('v', '').split('-')[0].split('.') || [];
|
};
|
||||||
const checkVersionsArr = checkVersion.split('.');
|
this.isVersionCompatible = (checkVersion) => {
|
||||||
return (+versionsArr[0] > +checkVersionsArr[0]) ||
|
if (this.ln_version && this.ln_version !== '') {
|
||||||
(+versionsArr[0] === +checkVersionsArr[0] && +versionsArr[1] > +checkVersionsArr[1]) ||
|
// eslint-disable-next-line prefer-named-capture-group
|
||||||
(+versionsArr[0] === +checkVersionsArr[0] && +versionsArr[1] === +checkVersionsArr[1] && +versionsArr[2] >= +checkVersionsArr[2]);
|
const pattern = /v?(\d+(\.\d+)*)/;
|
||||||
|
const match = this.ln_version.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 ' + this.ln_version });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -9,13 +9,23 @@ export const getBalance = (req, res, next) => {
|
|||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Balance', msg: 'Getting Balance..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Balance', msg: 'Getting Balance..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/listfunds';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
if (!body.totalBalance) { body.totalBalance = 0; }
|
let confBalance = 0;
|
||||||
if (!body.confBalance) { body.confBalance = 0; }
|
let unconfBalance = 0;
|
||||||
if (!body.unconfBalance) { body.unconfBalance = 0; }
|
let totalBalance = 0;
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Balance', msg: 'Balance Received', data: body });
|
const versionCompatible = common.isVersionCompatible('23.02');
|
||||||
res.status(200).json(body);
|
body.outputs.forEach((output) => {
|
||||||
|
if (output.status === 'confirmed') {
|
||||||
|
confBalance = confBalance + (versionCompatible ? (output.amount_msat / 1000) : output.value);
|
||||||
|
} else if (output.status === 'unconfirmed') {
|
||||||
|
unconfBalance = unconfBalance + (versionCompatible ? (output.amount_msat / 1000) : output.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
totalBalance = confBalance + unconfBalance;
|
||||||
|
const walBalance = { totalBalance: totalBalance || 0, confBalance: confBalance || 0, unconfBalance: unconfBalance || 0 };
|
||||||
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Balance', msg: 'Balance Received', data: walBalance });
|
||||||
|
res.status(200).json(walBalance);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Balance', 'Get Balance Error', req.session.selectedNode);
|
const err = common.handleError(errRes, 'Balance', 'Get Balance Error', req.session.selectedNode);
|
||||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||||
|
@ -9,53 +9,54 @@ export const listPeerChannels = (req, res, next) => {
|
|||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Peer Channels..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Peer Channels..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/listpeerchannels';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
body?.map((channel) => {
|
body.channels.map((channel) => {
|
||||||
if (!channel.alias || channel.alias === '') { channel.alias = channel.peer_id.substring(0, 20); }
|
|
||||||
const local = channel.to_us_msat || 0;
|
const local = channel.to_us_msat || 0;
|
||||||
const remote = (channel.total_msat - local) || 0;
|
const remote = (channel.total_msat - local) || 0;
|
||||||
const total = channel.total_msat || 0;
|
const total = channel.total_msat || 0;
|
||||||
channel.to_them_msat = remote;
|
// return getAliasForChannel(channel).then(channelAlias => {
|
||||||
channel.balancedness = (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3);
|
return {
|
||||||
return channel;
|
peer_id: channel.peer_id,
|
||||||
|
peer_connected: channel.peer_connected,
|
||||||
|
opener: channel.opener,
|
||||||
|
owner: channel.owner,
|
||||||
|
short_channel_id: channel.short_channel_id,
|
||||||
|
channel_id: channel.channel_id,
|
||||||
|
funding_txid: channel.funding_txid,
|
||||||
|
private: channel.private,
|
||||||
|
to_us_msat: channel.to_us_msat,
|
||||||
|
total_msat: channel.total_msat,
|
||||||
|
their_reserve_msat: channel.their_reserve_msat,
|
||||||
|
our_reserve_msat: channel.our_reserve_msat,
|
||||||
|
spendable_msat: channel.spendable_msat,
|
||||||
|
receivable_msat: channel.receivable_msat,
|
||||||
|
funding: channel.funding,
|
||||||
|
state: channel.state,
|
||||||
|
fee_base_msat: channel.fee_base_msat,
|
||||||
|
fee_proportional_millionths: channel.fee_proportional_millionths,
|
||||||
|
dust_limit_msat: channel.dust_limit_msat,
|
||||||
|
htlcs: channel.htlcs,
|
||||||
|
features: channel.features,
|
||||||
|
alias: channel.peer_id.substring(0, 20),
|
||||||
|
to_them_msat: remote,
|
||||||
|
balancedness: (total === 0) ? 1 : (1 - Math.abs((local - remote) / total)).toFixed(3)
|
||||||
|
};
|
||||||
});
|
});
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: body });
|
}).then((listPeerChannels) => {
|
||||||
res.status(200).json(body);
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: listPeerChannels });
|
||||||
|
res.status(200).json(listPeerChannels);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Channels', 'List Peer Channels Error', req.session.selectedNode);
|
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 });
|
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.post(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) => {
|
export const openChannel = (req, res, next) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Opening Channel..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Opening Channel..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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;
|
options.body = req.body;
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Open Channel Options', data: options.body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Open Channel Options', data: options.body });
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
@ -71,7 +72,7 @@ export const setChannelFee = (req, res, next) => {
|
|||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Setting Channel Fee..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Setting Channel Fee..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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;
|
options.body = req.body;
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Update Channel Policy Options', data: options.body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Update Channel Policy Options', data: options.body });
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
@ -88,10 +89,10 @@ export const closeChannel = (req, res, next) => {
|
|||||||
req.setTimeout(60000 * 10); // timeout 10 mins
|
req.setTimeout(60000 * 10); // timeout 10 mins
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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/close';
|
||||||
options.url = req.session.selectedNode.ln_server_url + '/v1/channel/closeChannel/' + req.params.channelId + unilateralTimeoutQuery;
|
options.body = { channelId: req.params.channelId, unilaterlaltimeout: req.query.force ? 1 : null };
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Closing Channel', data: options.url });
|
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 });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Channel Closed', data: body });
|
||||||
res.status(204).json(body);
|
res.status(204).json(body);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
@ -104,12 +105,31 @@ export const getLocalRemoteBalance = (req, res, next) => {
|
|||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Local & Remote Balances..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Local & Remote Balances..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/listfunds';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
if (!body.localBalance) { body.localBalance = 0; }
|
const versionCompatible = common.isVersionCompatible('23.02');
|
||||||
if (!body.remoteBalance) { body.remoteBalance = 0; }
|
let localBalance = 0;
|
||||||
|
let remoteBalance = 0;
|
||||||
|
let pendingBalance = 0;
|
||||||
|
let inactiveBalance = 0;
|
||||||
|
body.channels.forEach((channel) => {
|
||||||
|
if ((channel.state === 'CHANNELD_NORMAL') && channel.connected === true) {
|
||||||
|
localBalance = localBalance + (versionCompatible ? (channel.our_amount_msat) : channel.channel_sat);
|
||||||
|
remoteBalance = remoteBalance + (versionCompatible ? (channel.amount_msat - channel.our_amount_msat) : (channel.channel_total_sat - channel.channel_sat));
|
||||||
|
} else if ((channel.state === 'CHANNELD_NORMAL') && channel.connected === false) {
|
||||||
|
inactiveBalance = inactiveBalance + (versionCompatible ? (channel.our_amount_msat) : channel.channel_sat);
|
||||||
|
} else if (channel.state === 'CHANNELD_AWAITING_LOCKIN' || channel.state === 'DUALOPEND_AWAITING_LOCKIN') {
|
||||||
|
pendingBalance = pendingBalance + (versionCompatible ? (channel.our_amount_msat) : channel.channel_sat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (versionCompatible) {
|
||||||
|
localBalance = localBalance / 1000;
|
||||||
|
remoteBalance = remoteBalance / 1000;
|
||||||
|
inactiveBalance = inactiveBalance / 1000;
|
||||||
|
pendingBalance = pendingBalance / 1000;
|
||||||
|
}
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Local Remote Balance Received', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Local Remote Balance Received', data: body });
|
||||||
res.status(200).json(body);
|
res.status(200).json({ localBalance: localBalance || 0, remoteBalance: remoteBalance || 0, inactiveBalance: inactiveBalance || 0, pendingBalance: pendingBalance || 0 });
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Channels', 'Local Remote Balance Error', req.session.selectedNode);
|
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 });
|
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||||
@ -120,10 +140,11 @@ export const listForwards = (req, res, next) => {
|
|||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Channel List Forwards..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting Channel List Forwards..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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');
|
options.url = req.session.selectedNode.ln_server_url + '/v1/listforwards';
|
||||||
|
options.body = { status: req.query.status || 'settled' };
|
||||||
request.get(options).then((body) => {
|
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 });
|
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);
|
res.status(200).json(!body.forwards ? [] : (req.query.status === 'failed' || req.query.status === 'local_failed') ? body.forwards.slice(Math.max(0, body.forwards.length - 1000), Math.max(1000, body.forwards.length)).reverse() : body.forwards.reverse());
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Channels', 'Forwarding History Error', req.session.selectedNode);
|
const err = common.handleError(errRes, 'Channels', 'Forwarding History Error', req.session.selectedNode);
|
||||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||||
@ -134,10 +155,10 @@ export const funderUpdatePolicy = (req, res, next) => {
|
|||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting or Updating Funder Policy..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Getting or Updating Funder Policy..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/funderupdate';
|
||||||
if (req.body && req.body.policy) {
|
// if (req.body && req.body.policy) {
|
||||||
options.body = req.body;
|
// options.body = req.body;
|
||||||
}
|
// }
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Funder Update Body', data: options.body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Funder Update Body', data: options.body });
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Funder Policy Received', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Funder Policy Received', data: body });
|
||||||
@ -149,22 +170,3 @@ export const funderUpdatePolicy = (req, res, next) => {
|
|||||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
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 });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
@ -9,11 +9,12 @@ export const getFees = (req, res, next) => {
|
|||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Getting Fees..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Getting Fees..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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';
|
options.url = req.session.selectedNode.ln_server_url + '/v1/getinfo';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
if (!body.feeCollected) { body.feeCollected = 0; }
|
const versionCompatible = common.isVersionCompatible('23.02');
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Fee Received', data: body });
|
const feeData = { feeCollected: ((versionCompatible ? body.fees_collected_msat : body.msatoshi_fees_collected) || 0) };
|
||||||
res.status(200).json(body);
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Fee Received', data: feeData });
|
||||||
|
res.status(200).json(feeData);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
const err = common.handleError(errRes, 'Fees', 'Get Fees Error', req.session.selectedNode);
|
const err = common.handleError(errRes, 'Fees', 'Get Fees Error', req.session.selectedNode);
|
||||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||||
|
@ -45,8 +45,9 @@ export const getInfo = (req, res, next) => {
|
|||||||
body.uris.push(body.id + '@' + addr.address + ':' + addr.port);
|
body.uris.push(body.id + '@' + addr.address + ':' + addr.port);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
req.session.selectedNode.api_version = body.api_version || '';
|
common.setVersion(body.version || '');
|
||||||
req.session.selectedNode.ln_version = body.version || '';
|
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.' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Connecting to the Core Lightning\'s Websocket Server.' });
|
||||||
clWsClient.updateSelectedNode(req.session.selectedNode);
|
clWsClient.updateSelectedNode(req.session.selectedNode);
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Node Information Received', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Node Information Received', data: body });
|
||||||
|
@ -11,7 +11,7 @@ export const deleteExpiredInvoice = (req, res, next) => {
|
|||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
||||||
const queryStr = req.query.maxExpiry ? '?maxexpiry=' + req.query.maxExpiry : '';
|
const queryStr = req.query.maxExpiry ? '?maxexpiry=' + req.query.maxExpiry : '';
|
||||||
options.url = req.session.selectedNode.ln_server_url + '/v1/invoice/delExpiredInvoice' + queryStr;
|
options.url = req.session.selectedNode.ln_server_url + '/v1/invoice/delExpiredInvoice' + queryStr;
|
||||||
request.delete(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Invoices Deleted', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Invoice', msg: 'Invoices Deleted', data: body });
|
||||||
res.status(204).json({ status: 'Invoice Deleted Successfully' });
|
res.status(204).json({ status: 'Invoice Deleted Successfully' });
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
|
@ -88,7 +88,7 @@ export const disableOffer = (req, res, next) => {
|
|||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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;
|
options.url = req.session.selectedNode.ln_server_url + '/v1/offers/disableOffer/' + req.params.offerID;
|
||||||
request.delete(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offer Disabled', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Offers', msg: 'Offer Disabled', data: body });
|
||||||
res.status(202).json(body);
|
res.status(202).json(body);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
|
@ -52,7 +52,7 @@ export const deletePeer = (req, res, next) => {
|
|||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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;
|
options.url = req.session.selectedNode.ln_server_url + '/v1/peer/disconnect/' + req.params.peerId + '?force=' + req.query.force;
|
||||||
request.delete(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peer Disconnected', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Peer Disconnected', data: body });
|
||||||
res.status(204).json({});
|
res.status(204).json({});
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
|
@ -70,7 +70,7 @@ export const verifyMessage = (req, res, next) => {
|
|||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
|
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;
|
options.url = req.session.selectedNode.ln_server_url + '/v1/utility/checkMessage/' + req.body.message + '/' + req.body.signature;
|
||||||
request.get(options, (error, response, body) => {
|
request.post(options, (error, response, body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body });
|
||||||
res.status(201).json(body);
|
res.status(201).json(body);
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import exprs from 'express';
|
import exprs from 'express';
|
||||||
const { Router } = exprs;
|
const { Router } = exprs;
|
||||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
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, getLocalRemoteBalance, listForwards, funderUpdatePolicy } from '../../controllers/cln/channels.js';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get('/listChannels', isAuthenticated, listChannels);
|
|
||||||
router.get('/listPeerChannels', isAuthenticated, listPeerChannels);
|
router.get('/listPeerChannels', isAuthenticated, listPeerChannels);
|
||||||
router.post('/', isAuthenticated, openChannel);
|
router.post('/', isAuthenticated, openChannel);
|
||||||
router.post('/setChannelFee', isAuthenticated, setChannelFee);
|
router.post('/setChannelFee', isAuthenticated, setChannelFee);
|
||||||
@ -13,7 +12,6 @@ router.delete('/:channelId', isAuthenticated, closeChannel);
|
|||||||
|
|
||||||
router.get('/localRemoteBalance', isAuthenticated, getLocalRemoteBalance);
|
router.get('/localRemoteBalance', isAuthenticated, getLocalRemoteBalance);
|
||||||
router.get('/listForwards', isAuthenticated, listForwards);
|
router.get('/listForwards', isAuthenticated, listForwards);
|
||||||
router.get('/listForwardsPaginated', isAuthenticated, listForwardsPaginated);
|
|
||||||
|
|
||||||
router.post('/funderUpdate', isAuthenticated, funderUpdatePolicy);
|
router.post('/funderUpdate', isAuthenticated, funderUpdatePolicy);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ export class CommonService {
|
|||||||
public rtl_cookie_path = '';
|
public rtl_cookie_path = '';
|
||||||
public logout_redirect_link = '';
|
public logout_redirect_link = '';
|
||||||
public cookie_value = '';
|
public cookie_value = '';
|
||||||
|
public ln_version = '';
|
||||||
public api_version = '';
|
public api_version = '';
|
||||||
public secret_key = crypto.randomBytes(64).toString('hex');
|
public secret_key = crypto.randomBytes(64).toString('hex');
|
||||||
public read_dummy_data = false;
|
public read_dummy_data = false;
|
||||||
@ -432,13 +433,29 @@ export class CommonService {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
public isVersionCompatible = (currentVersion, checkVersion) => {
|
public setVersion = (version) => {
|
||||||
if (currentVersion) {
|
this.ln_version = version;
|
||||||
const versionsArr = currentVersion.trim()?.replace('v', '').split('-')[0].split('.') || [];
|
};
|
||||||
const checkVersionsArr = checkVersion.split('.');
|
|
||||||
return (+versionsArr[0] > +checkVersionsArr[0]) ||
|
public isVersionCompatible = (checkVersion) => {
|
||||||
(+versionsArr[0] === +checkVersionsArr[0] && +versionsArr[1] > +checkVersionsArr[1]) ||
|
if (this.ln_version && this.ln_version !== '') {
|
||||||
(+versionsArr[0] === +checkVersionsArr[0] && +versionsArr[1] === +checkVersionsArr[1] && +versionsArr[2] >= +checkVersionsArr[2]);
|
// eslint-disable-next-line prefer-named-capture-group
|
||||||
|
const pattern = /v?(\d+(\.\d+)*)/;
|
||||||
|
const match = this.ln_version.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 ' + this.ln_version });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user