Compare commits
No commits in common. 'master' and 'v0.12.1' have entirely different histories.
@ -0,0 +1,17 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see:
|
||||
# https://angular.io/guide/browser-support
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
@ -0,0 +1,108 @@
|
||||
![](./screenshots/RTL-CLT-Dashboard.png)
|
||||
|
||||
## RTL C-lightning setup
|
||||
|
||||
* [Introduction](#intro)
|
||||
* [Pre-requisite](#prereq)
|
||||
* [Architecture](#arch)
|
||||
* [Installation](#install)
|
||||
* [Prep for execution](#prep)
|
||||
* [Start the server and access the app](#start)
|
||||
|
||||
### <a name="intro"></a>Introduction
|
||||
RTL is now enabled to manage lightning nodes running C-Lightning.
|
||||
|
||||
Follow the below steps to install and setup RTL to run on C-Lightning.
|
||||
|
||||
### <a name="prereq"></a>Pre-requisites:
|
||||
1. Functioning C-Lightning node. Follow install instructions on their [github](https://github.com/ElementsProject/lightning)
|
||||
2. NodeJS - Can be downloaded [here](https://nodejs.org/en/download)
|
||||
3. Cl-REST - Ensure that `cl-rest` API server is installed and running. Install instructions [here](https://github.com/Ride-The-Lightning/c-lightning-REST)
|
||||
4. Copy the `access.macaroon` file from `cl-rest` to the device, on which RTL will be installed
|
||||
|
||||
### <a name="arch"></a>Architecture
|
||||
![](./screenshots/RTL-CLT-Arch-2.png)
|
||||
|
||||
### <a name="install"></a>Installation:
|
||||
To download a specific RTL version follow the instructions on the [release page](https://github.com/Ride-The-Lightning/RTL/releases)
|
||||
|
||||
To download from master (*not recommended*):
|
||||
|
||||
#### First time setup
|
||||
```
|
||||
$ git clone https://github.com/Ride-The-Lightning/RTL.git
|
||||
$ cd RTL
|
||||
$ npm install
|
||||
$ npm run buildfrontend
|
||||
$ npm run buildbackend
|
||||
$ npm prune --production
|
||||
```
|
||||
|
||||
#### Or: Update existing build
|
||||
```
|
||||
$ cd RTL
|
||||
$ git reset --hard HEAD
|
||||
$ git clean -f -d
|
||||
$ git pull
|
||||
$ npm install
|
||||
$ npm run buildfrontend
|
||||
$ npm run buildbackend
|
||||
$ npm prune --production
|
||||
```
|
||||
### <a name="prep"></a>Prep for Execution
|
||||
RTL requires its own config file `RTL-Config.json`, to start the server and provide user authentication on the app.
|
||||
* Copy the file `Sample-RTL-Config.json` from `./RTL/docs` to `./RTL` and rename it to `RTL-Config.json`.
|
||||
* Locate the complete path of the readable `access.macaroon` from `cl-rest` on your node.
|
||||
* Modify the RTL conf file per the example file below
|
||||
|
||||
Ensure that the follow values are correct per your config:
|
||||
* `lnImplementation` - This should be `CLT`, indicating that RTL is connecting to a c-lightning node.
|
||||
* `macaroonPath` - Path of the folder containing `access.macaroon` file from cl-rest server.
|
||||
* `lnServerUrl` - complete url with ip address and port of the cl-rest server.
|
||||
* `multiPass` - Specify the password (in plain text) to access RTL. This password will be hashed and not stored as plain text.
|
||||
* `configPath` (optional) - File path of the c-lightning config file, if RTL server is local to the c-lightning server.
|
||||
|
||||
```
|
||||
{
|
||||
"port": "3000",
|
||||
"SSO": {
|
||||
"rtlSSO": 0,
|
||||
"rtlCookiePath": "",
|
||||
"logoutRedirectLink": ""
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"index": 1,
|
||||
"lnNode": "c-lightning Testnet # 1",
|
||||
"lnImplementation": "CLT",
|
||||
"Authentication": {
|
||||
"macaroonPath": "<Modify to include the path of the folder with access.macaroon>",
|
||||
"configPath": "<Optional - Config file path for c-lightning>"
|
||||
},
|
||||
"Settings": {
|
||||
"userPersona": "OPERATOR",
|
||||
"themeMode": "DAY",
|
||||
"themeColor": "PURPLE",
|
||||
"bitcoindConfigPath": "",
|
||||
"logLevel": "INFO",
|
||||
"fiatConversion": false,
|
||||
"lnServerUrl": "https://<cl-rest api server ip address>:3001"
|
||||
}
|
||||
}
|
||||
],
|
||||
"multiPass": <password required for accessing RTL>
|
||||
}
|
||||
```
|
||||
### <a name="start"></a>Start the server and access the app
|
||||
Run the following command:
|
||||
|
||||
`$ node rtl`
|
||||
|
||||
If the server started successfully, you should get the below output on the console:
|
||||
|
||||
`$ Server is up and running, please open the UI at http://localhost:3000`
|
||||
|
||||
Open your browser at the following address: http://localhost:3000 to access the RTL app.
|
||||
|
||||
### Detailed config and instructions
|
||||
For detailed config and access options and other information, view the main readme page.
|
@ -0,0 +1,71 @@
|
||||
### C-Lightning Commands Covered on RTL
|
||||
|
||||
=== bitcoin ===
|
||||
- [x] feerates
|
||||
- [x] newaddr
|
||||
- [ ] txdiscard
|
||||
- [ ] txprepare
|
||||
- [ ] txsend
|
||||
- [x] withdraw
|
||||
|
||||
=== channels ===
|
||||
- [x] close
|
||||
- [ ] fundchannel_cancel
|
||||
- [ ] fundchannel_complete
|
||||
- [ ] fundchannel_start
|
||||
- [x] getroute
|
||||
- [x] listchannels
|
||||
- [x] listforwards
|
||||
- [x] setchannelfee
|
||||
|
||||
=== network ===
|
||||
- [x] connect
|
||||
- [x] disconnect
|
||||
- [x] listnodes
|
||||
- [x] listpeers
|
||||
- [ ] ping
|
||||
|
||||
=== payment ===
|
||||
- [ ] createonion
|
||||
- [x] decodepay
|
||||
- [x] delexpiredinvoice
|
||||
- [ ] delinvoice
|
||||
- [x] invoice
|
||||
- [x] listinvoices
|
||||
- [x] listsendpays
|
||||
- [ ] listtransactions
|
||||
- [ ] sendonion
|
||||
- [ ] sendpay
|
||||
- [ ] waitanyinvoice
|
||||
- [ ] waitinvoice
|
||||
- [ ] waitsendpay
|
||||
|
||||
=== plugin ===
|
||||
- [ ] autocleaninvoice
|
||||
- [ ] estimatefees
|
||||
- [x] fundchannel
|
||||
- [ ] getchaininfo
|
||||
- [ ] getrawblockbyheight
|
||||
- [ ] getutxout
|
||||
- [x] listpays
|
||||
- [x] pay
|
||||
- [ ] paystatus
|
||||
- [ ] plugin
|
||||
- [ ] sendrawtransaction
|
||||
|
||||
=== utility ===
|
||||
- [ ] check
|
||||
- [x] checkmessage
|
||||
- [x] getinfo
|
||||
- [ ] getlog
|
||||
- [ ] getsharedsecret
|
||||
- [ ] help
|
||||
- [ ] listconfigs
|
||||
- [x] listfunds
|
||||
- [x] signmessage
|
||||
- [ ] stop
|
||||
- [ ] waitblockheight
|
||||
|
||||
=== developer ===
|
||||
- [ ] dev-listaddrs
|
||||
- [ ] dev-rescan-outputs
|
@ -1,111 +0,0 @@
|
||||
![](../screenshots/RTL-CLN-Arch-3.png)
|
||||
|
||||
## RTL Core lightning setup
|
||||
|
||||
* [Introduction](#intro)
|
||||
* [Pre-requisite](#prereq)
|
||||
* [Architecture](#arch)
|
||||
* [Installation](#install)
|
||||
* [Prep for execution](#prep)
|
||||
* [Start the server and access the app](#start)
|
||||
|
||||
### <a name="intro"></a>Introduction
|
||||
RTL is now enabled to manage lightning nodes running Core Lightning
|
||||
|
||||
Follow the below steps to install and setup RTL to run on Core Lightning
|
||||
|
||||
### <a name="prereq"></a>Pre-requisites:
|
||||
1. Functioning Core Lightning node. Follow install instructions on their [github](https://github.com/ElementsProject/lightning)
|
||||
2. NodeJS - Can be downloaded [here](https://nodejs.org/en/download)
|
||||
3. CLNRest - Ensure that core lightning's `CLNRest` API server is configured. Configuration instructions [here](https://docs.corelightning.org/docs/rest#configuration)
|
||||
4. Create/reuse core-lightning's rune. Check [`createrune`](https://docs.corelightning.org/reference/lightning-createrune) and [`showrunes`](https://docs.corelightning.org/reference/lightning-showrunes) documentation for more details on how to create runes
|
||||
4. Copy the `rune` and save it in a file which must be accessible to RTL. The content of the file must be `LIGHTNING_RUNE="<your-rune>"`
|
||||
|
||||
### <a name="arch"></a>Architecture
|
||||
![](../screenshots/RTL-CLN-Arch-2.png)
|
||||
|
||||
### <a name="install"></a>Installation:
|
||||
To download a specific RTL version follow the instructions on the [release page](https://github.com/Ride-The-Lightning/RTL/releases)
|
||||
|
||||
To download from master (*not recommended*):
|
||||
|
||||
#### First time setup
|
||||
```
|
||||
$ git clone https://github.com/Ride-The-Lightning/RTL.git
|
||||
$ cd RTL
|
||||
$ npm install --omit=dev --legacy-peer-deps
|
||||
```
|
||||
|
||||
#### Or: Update existing build
|
||||
```
|
||||
$ cd RTL
|
||||
$ git reset --hard HEAD
|
||||
$ git clean -f -d
|
||||
$ git pull
|
||||
$ npm install --omit=dev --legacy-peer-deps
|
||||
```
|
||||
|
||||
#### Error on npm install
|
||||
If there is an error with `upstream dependency conflict` message then replace `npm install --omit=dev` with `npm install --omit=dev --legacy-peer-deps`.
|
||||
|
||||
### <a name="prep"></a>Prep for Execution
|
||||
RTL requires its own config file `RTL-Config.json`, to start the server and provide user authentication on the app
|
||||
* Rename the file `Sample-RTL-Config.json` to `RTL-Config.json` located at`./RTL`
|
||||
* Locate the complete path of the readable `.commando` file on your node
|
||||
* Modify the RTL conf file per the example file below
|
||||
|
||||
Ensure that the follow values are correct per your config:
|
||||
* `lnImplementation` - This should be `CLN`, indicating that RTL is connecting to a core lightning node
|
||||
* `runePath` - Path of the folder including **filename** which contains the `rune` for the node. The content of the file must be `LIGHTNING_RUNE="<your-rune>"`
|
||||
* `lnServerUrl` - complete url with ip address and port of the CLNRest server
|
||||
* `multiPass` - Specify the password (in plain text) to access RTL. This password will be hashed and not stored as plain text
|
||||
* `configPath` (optional) - File path of the core lightning config file, if RTL server is local to the core lightning server
|
||||
|
||||
```
|
||||
{
|
||||
"multiPass": <password required for accessing RTL>,
|
||||
"port": "3000",
|
||||
"defaultNodeIndex": 1,
|
||||
"dbDirectoryPath": "<Complete path of the folder where rtl's database file should be saved>",
|
||||
"SSO": {
|
||||
"rtlSSO": 0,
|
||||
"rtlCookiePath": "",
|
||||
"logoutRedirectLink": ""
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"index": 1,
|
||||
"lnNode": "Core Lightning Testnet # 1",
|
||||
"lnImplementation": "CLN",
|
||||
"authentication": {
|
||||
"runePath": "<Modify to include the path of the folder including filename which contains `rune`>",
|
||||
"configPath": "<Optional - Config file path for core lightning>"
|
||||
},
|
||||
"settings": {
|
||||
"userPersona": "OPERATOR",
|
||||
"themeMode": "DAY",
|
||||
"themeColor": "PURPLE",
|
||||
"bitcoindConfigPath": "",
|
||||
"logLevel": "INFO",
|
||||
"fiatConversion": false,
|
||||
"unannouncedChannels": false,
|
||||
"lnServerUrl": "https://<CLNRest api server ip address>:3001",
|
||||
"blockExplorerUrl": "<Default: https://mempool.space>"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### <a name="start"></a>Start the server and access the app
|
||||
Run the following command:
|
||||
|
||||
`$ node rtl`
|
||||
|
||||
If the server started successfully, you should get the below output on the console:
|
||||
|
||||
`$ Server is up and running, please open the UI at http://localhost:3000 or your proxy configured url`
|
||||
|
||||
Open your browser at the following address: http://localhost:3000 to access the RTL app
|
||||
|
||||
### Detailed config and instructions
|
||||
For detailed config and access options and other information, view the main readme page
|
@ -0,0 +1,57 @@
|
||||
[Intro](../README.md) -- [Application Features](Application_features.md) -- [Road Map](Roadmap.md) -- **LND API Coverage** -- [Application Configurations](Application_configurations.md)
|
||||
|
||||
- [x] GenSeed
|
||||
- [x] InitWallet
|
||||
- [x] UnlockWallet
|
||||
- [ ] ChangePassword
|
||||
- [x] WalletBalance
|
||||
- [x] ChannelBalance
|
||||
- [x] GetTransactions
|
||||
- [ ] EstimateFee
|
||||
- [x] SendCoins
|
||||
- [ ] ListUnspent
|
||||
- [ ] SubscribeTransactions
|
||||
- [ ] SendMany
|
||||
- [x] NewAddress
|
||||
- [x] SignMessage
|
||||
- [x] VerifyMessage
|
||||
- [x] ConnectPeer
|
||||
- [x] DisconnectPeer
|
||||
- [x] ListPeers
|
||||
- [x] GetInfo
|
||||
- [x] PendingChannels
|
||||
- [x] ListChannels
|
||||
- [ ] SubscribeChannelEvents
|
||||
- [x] ClosedChannels
|
||||
- [ ] OpenChannelSync
|
||||
- [x] OpenChannel
|
||||
- [x] CloseChannel
|
||||
- [ ] AbandonChannel
|
||||
- [x] SendPayment
|
||||
- [ ] SendPaymentSync
|
||||
- [ ] SendToRoute
|
||||
- [ ] SendToRouteSync
|
||||
- [x] AddInvoice
|
||||
- [x] ListInvoices
|
||||
- [ ] LookupInvoice
|
||||
- [ ] SubscribeInvoices
|
||||
- [x] DecodePayReq
|
||||
- [x] ListPayments
|
||||
- [ ] DeleteAllPayments
|
||||
- [ ] DescribeGraph
|
||||
- [x] GetChanInfo
|
||||
- [x] GetNodeInfo
|
||||
- [x] QueryRoutes
|
||||
- [x] GetNetworkInfo
|
||||
- [ ] StopDaemon
|
||||
- [ ] SubscribeChannelGraph
|
||||
- [ ] DebugLevel
|
||||
- [x] FeeReport
|
||||
- [x] UpdateChannelPolicy
|
||||
- [x] ForwardingHistory
|
||||
- [x] ExportChannelBackup
|
||||
- [x] ExportAllChannelBackups
|
||||
- [x] VerifyChanBackup
|
||||
- [x] RestoreChannelBackups
|
||||
- [ ] SubscribeChannelBackups
|
||||
- [ ] Messages
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 181 KiB |
After Width: | Height: | Size: 142 KiB |
After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
@ -1,13 +0,0 @@
|
||||
{
|
||||
"eslint.enable": true,
|
||||
"eslint.validate": [
|
||||
"typescript",
|
||||
"HTML"
|
||||
],
|
||||
"eslint.options": {
|
||||
"configFile": ".eslintrc.json"
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
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 });
|
||||
});
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
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 getFees = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Fees', msg: 'Getting Fees..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/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);
|
||||
}).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 });
|
||||
});
|
||||
};
|
@ -0,0 +1,81 @@
|
||||
import request from 'request-promise';
|
||||
import { Database } from '../../utils/database.js';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
import { CLWSClient } from './webSocketClient.js';
|
||||
let options = null;
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
const clWsClient = CLWSClient;
|
||||
const databaseService = Database;
|
||||
export const getInfo = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Getting CLightning Node Information..' });
|
||||
common.logEnvVariables(req);
|
||||
common.setOptions(req);
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/getinfo';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Selected Node ' + req.session.selectedNode.ln_node });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Calling Info from C-Lightning server url ' + options.url });
|
||||
if (!options.headers || !options.headers.macaroon) {
|
||||
const errMsg = 'C-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);
|
||||
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 });
|
||||
}
|
||||
else {
|
||||
body.lnImplementation = 'C-Lightning';
|
||||
const chainObj = { chain: '', network: '' };
|
||||
if (body.network === 'testnet') {
|
||||
chainObj.chain = 'Bitcoin';
|
||||
chainObj.network = 'Testnet';
|
||||
}
|
||||
else if (body.network === 'bitcoin') {
|
||||
chainObj.chain = 'Bitcoin';
|
||||
chainObj.network = 'Mainnet';
|
||||
}
|
||||
else if (body.network === 'signet') {
|
||||
chainObj.chain = 'Bitcoin';
|
||||
chainObj.network = 'Signet';
|
||||
}
|
||||
else if (body.network === 'litecoin') {
|
||||
chainObj.chain = 'Litecoin';
|
||||
chainObj.network = 'Mainnet';
|
||||
}
|
||||
else if (body.network === 'litecoin-testnet') {
|
||||
chainObj.chain = 'Litecoin';
|
||||
chainObj.network = 'Testnet';
|
||||
}
|
||||
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 C-Lightning\'s Websocket Server.' });
|
||||
clWsClient.updateSelectedNode(req.session.selectedNode);
|
||||
databaseService.loadDatabase(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 });
|
||||
});
|
||||
}
|
||||
};
|
@ -0,0 +1,37 @@
|
||||
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 signMessage = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Signing Message..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/utility/signMessage';
|
||||
options.form = { message: req.body.message };
|
||||
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);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Message', 'Sign Message Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const verifyMessage = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Verifying Message..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/utility/checkMessage/' + req.body.message + '/' + req.body.signature;
|
||||
request.get(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) => {
|
||||
const err = common.handleError(errRes, 'Message', 'Verify Message Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
@ -0,0 +1,56 @@
|
||||
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 getNewAddress = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Generating New Address..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/newaddr?addrType=' + req.query.type;
|
||||
request(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) => {
|
||||
const err = common.handleError(errRes, 'OnChain', 'New Address Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const onChainWithdraw = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Withdrawing from On Chain..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/withdraw';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'OnChain', msg: 'OnChain Withdraw Options', data: options.body });
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Withdraw Finished', data: body });
|
||||
res.status(201).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'OnChain', 'Withdraw Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const getUTXOs = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Listing Funds..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/listFunds';
|
||||
request(options).then((body) => {
|
||||
if (body.outputs) {
|
||||
body.outputs = common.sortDescByStrKey(body.outputs, 'status');
|
||||
}
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Funds List Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}).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 });
|
||||
});
|
||||
};
|
@ -0,0 +1,154 @@
|
||||
import request from 'request-promise';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
import { Database } from '../../utils/database.js';
|
||||
import { CollectionFieldsEnum, CollectionsEnum } from '../../models/database.model.js';
|
||||
let options = null;
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
const databaseService = Database;
|
||||
function paymentReducer(accumulator, currentPayment) {
|
||||
const currPayHash = currentPayment.payment_hash;
|
||||
if (!currentPayment.partid) {
|
||||
currentPayment.partid = 0;
|
||||
}
|
||||
if (!accumulator[currPayHash]) {
|
||||
accumulator[currPayHash] = [currentPayment];
|
||||
}
|
||||
else {
|
||||
accumulator[currPayHash].push(currentPayment);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
function summaryReducer(accumulator, mpp) {
|
||||
if (mpp.status === 'complete') {
|
||||
accumulator.msatoshi = accumulator.msatoshi + mpp.msatoshi;
|
||||
accumulator.msatoshi_sent = accumulator.msatoshi_sent + mpp.msatoshi_sent;
|
||||
accumulator.status = mpp.status;
|
||||
}
|
||||
if (mpp.bolt11) {
|
||||
accumulator.bolt11 = mpp.bolt11;
|
||||
}
|
||||
if (mpp.bolt12) {
|
||||
accumulator.bolt12 = mpp.bolt12;
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
function groupBy(payments) {
|
||||
const paymentsInGroups = payments.reduce(paymentReducer, {});
|
||||
const paymentsGrpArray = Object.keys(paymentsInGroups).map((key) => ((paymentsInGroups[key].length && paymentsInGroups[key].length > 1) ? common.sortDescByKey(paymentsInGroups[key], 'partid') : paymentsInGroups[key]));
|
||||
return paymentsGrpArray.reduce((acc, curr) => {
|
||||
let temp = {};
|
||||
if (curr.length && curr.length === 1) {
|
||||
temp = JSON.parse(JSON.stringify(curr[0]));
|
||||
temp.is_group = false;
|
||||
temp.is_expanded = false;
|
||||
temp.total_parts = 1;
|
||||
delete temp.partid;
|
||||
}
|
||||
else {
|
||||
const paySummary = curr.reduce(summaryReducer, { msatoshi: 0, msatoshi_sent: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
|
||||
temp = {
|
||||
is_group: true, is_expanded: false, total_parts: (curr.length ? curr.length : 0), status: paySummary.status, payment_hash: curr[0].payment_hash,
|
||||
destination: curr[0].destination, msatoshi: paySummary.msatoshi, msatoshi_sent: paySummary.msatoshi_sent, created_at: curr[0].created_at,
|
||||
mpps: curr
|
||||
};
|
||||
if (paySummary.bolt11) {
|
||||
temp.bolt11 = paySummary.bolt11;
|
||||
}
|
||||
if (paySummary.bolt12) {
|
||||
temp.bolt12 = paySummary.bolt12;
|
||||
}
|
||||
}
|
||||
return acc.concat(temp);
|
||||
}, []);
|
||||
}
|
||||
export const listPayments = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'List Payments..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.ln_server_url + '/v1/pay/listPayments';
|
||||
request(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment List Received', data: body.payments });
|
||||
if (body && body.payments && body.payments.length > 0) {
|
||||
body.payments = common.sortDescByKey(body.payments, 'created_at');
|
||||
}
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Sorted Payments List Received', data: body.payments });
|
||||
res.status(200).json(groupBy(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 });
|
||||
});
|
||||
};
|
||||
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) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Decoded', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Payments', 'Decode Payment Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const postPayment = (req, res, next) => {
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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() };
|
||||
if (req.body.vendor) {
|
||||
offerToUpdate['vendor'] = req.body.vendor;
|
||||
}
|
||||
if (req.body.description) {
|
||||
offerToUpdate['description'] = req.body.description;
|
||||
}
|
||||
return databaseService.update(req.session.selectedNode, CollectionsEnum.OFFERS, offerToUpdate, CollectionFieldsEnum.BOLT12, req.body.bolt12).then((updatedOffer) => {
|
||||
logger.log({ level: 'DEBUG', fileName: 'Offer', msg: 'Offer Updated', data: updatedOffer });
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: updatedOffer });
|
||||
}).catch((errDB) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'Payments', msg: 'Offer DB update error', error: errDB });
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBError: errDB });
|
||||
});
|
||||
}
|
||||
else {
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: 'NA' });
|
||||
}
|
||||
}
|
||||
if (req.body.paymentType === 'INVOICE') {
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: 'NA' });
|
||||
}
|
||||
if (req.body.paymentType === 'KEYSEND') {
|
||||
return res.status(201).json(body);
|
||||
}
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Payments', 'Send Payment Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
@ -1,60 +0,0 @@
|
||||
import request from 'request-promise';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
import { CLWSClient } from './webSocketClient.js';
|
||||
let options = null;
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
const clWsClient = CLWSClient;
|
||||
export const getInfo = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Getting Core Lightning Node Information..' });
|
||||
common.logEnvVariables(req);
|
||||
common.setOptions(req);
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/getinfo';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Selected Node ' + req.session.selectedNode.lnNode });
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Calling Info from Core Lightning server url ' + options.url });
|
||||
if (!options.headers || !options.headers.rune) {
|
||||
const errMsg = 'Core lightning get info failed due to missing rune!';
|
||||
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.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 {
|
||||
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.lnVersion = body.version || '';
|
||||
req.session.selectedNode.api_version = body.api_version || '';
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'GetInfo', msg: 'Connecting to the Core Lightning\'s Websocket Server.' });
|
||||
clWsClient.updateSelectedNode(req.session.selectedNode);
|
||||
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 });
|
||||
});
|
||||
}
|
||||
};
|
@ -1,91 +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 getNewAddress = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Generating New Address..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/newaddr';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'New Address Generated', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'OnChain', 'New Address Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const onChainWithdraw = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Withdrawing from On Chain..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/withdraw';
|
||||
options.body = req.body;
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'OnChain', msg: 'OnChain Withdraw Options', data: options.body });
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Withdraw Finished', data: body });
|
||||
res.status(201).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'OnChain', 'Withdraw Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const getUTXOs = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Listing Funds..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listfunds';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Funds List Received', data: body });
|
||||
// Local Remote Balance Calculation
|
||||
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 });
|
||||
});
|
||||
};
|
@ -1,188 +0,0 @@
|
||||
import request from 'request-promise';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
import { Database } from '../../utils/database.js';
|
||||
import { CollectionFieldsEnum, CollectionsEnum } from '../../models/database.model.js';
|
||||
let options = null;
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
const databaseService = Database;
|
||||
export const getMemo = (selNode, payment) => {
|
||||
options.url = selNode.settings.lnServerUrl + '/v1/decode';
|
||||
options.body = { string: payment.bolt11 };
|
||||
return request.post(options).then((res) => {
|
||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment Decode Received', data: res });
|
||||
payment.memo = res.description || '';
|
||||
return payment;
|
||||
}).catch((err) => {
|
||||
payment.memo = '';
|
||||
return payment;
|
||||
});
|
||||
};
|
||||
function paymentReducer(accumulator, currentPayment) {
|
||||
const currPayHash = currentPayment.payment_hash;
|
||||
if (!currentPayment.partid) {
|
||||
currentPayment.partid = 0;
|
||||
}
|
||||
if (!accumulator[currPayHash]) {
|
||||
accumulator[currPayHash] = [currentPayment];
|
||||
}
|
||||
else {
|
||||
accumulator[currPayHash].push(currentPayment);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
function summaryReducer(accumulator, mpp) {
|
||||
if (mpp.status === 'complete') {
|
||||
accumulator.amount_msat = accumulator.amount_msat + mpp.amount_msat;
|
||||
accumulator.amount_sent_msat = accumulator.amount_sent_msat + mpp.amount_sent_msat;
|
||||
accumulator.status = mpp.status;
|
||||
}
|
||||
if (mpp.bolt11) {
|
||||
accumulator.bolt11 = mpp.bolt11;
|
||||
}
|
||||
if (mpp.bolt12) {
|
||||
accumulator.bolt12 = mpp.bolt12;
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
function groupBy(payments) {
|
||||
const paymentsInGroups = payments?.reduce(paymentReducer, {});
|
||||
const paymentsGrpArray = Object.keys(paymentsInGroups)?.map((key) => ((paymentsInGroups[key].length && paymentsInGroups[key].length > 1) ? common.sortDescByKey(paymentsInGroups[key], 'partid') : paymentsInGroups[key]));
|
||||
return paymentsGrpArray?.reduce((acc, curr) => {
|
||||
let temp = {};
|
||||
if (curr.length && curr.length === 1) {
|
||||
temp = JSON.parse(JSON.stringify(curr[0]));
|
||||
temp.is_group = false;
|
||||
temp.is_expanded = false;
|
||||
temp.total_parts = 1;
|
||||
delete temp.partid;
|
||||
}
|
||||
else {
|
||||
const paySummary = curr?.reduce(summaryReducer, { amount_msat: 0, amount_sent_msat: 0, status: (curr[0] && curr[0].status) ? curr[0].status : 'failed' });
|
||||
temp = {
|
||||
is_group: true, is_expanded: false, total_parts: (curr.length ? curr.length : 0), status: paySummary.status, payment_hash: curr[0].payment_hash,
|
||||
destination: curr[0].destination, amount_msat: paySummary.amount_msat, amount_sent_msat: paySummary.amount_sent_msat, created_at: curr[0].created_at,
|
||||
mpps: curr
|
||||
};
|
||||
if (paySummary.bolt11) {
|
||||
temp.bolt11 = paySummary.bolt11;
|
||||
}
|
||||
if (paySummary.bolt12) {
|
||||
temp.bolt12 = paySummary.bolt12;
|
||||
}
|
||||
}
|
||||
return acc.concat(temp);
|
||||
}, []);
|
||||
}
|
||||
export const listPayments = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'List Payments..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listsendpays';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Payments', msg: 'Payment List Received', data: body.payments });
|
||||
body.payments = body.payments && body.payments.length && body.payments.length > 0 ? groupBy(body.payments) : [];
|
||||
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 });
|
||||
});
|
||||
};
|
||||
export const postPayment = (req, res, next) => {
|
||||
const { paymentType, saveToDB, bolt12, zeroAmtOffer, amount_msat, title, issuer, description } = req.body;
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
const options_body = JSON.parse(JSON.stringify(req.body));
|
||||
if (paymentType === 'KEYSEND') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Keysend Payment..' });
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/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 (paymentType === 'OFFER') {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Sending Offer Payment..' });
|
||||
}
|
||||
else {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Sending Invoice Payment..' });
|
||||
}
|
||||
if (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.settings.lnServerUrl + '/v1/pay';
|
||||
}
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Sent', data: body });
|
||||
if (paymentType === 'OFFER') {
|
||||
if (saveToDB && bolt12) {
|
||||
const offerToUpdate = { bolt12: bolt12, amountMSat: (zeroAmtOffer ? 0 : amount_msat), title: title, lastUpdatedAt: new Date(Date.now()).getTime() };
|
||||
if (issuer) {
|
||||
offerToUpdate['issuer'] = issuer;
|
||||
}
|
||||
if (description) {
|
||||
offerToUpdate['description'] = description;
|
||||
}
|
||||
// eslint-disable-next-line arrow-body-style
|
||||
return databaseService.validateDocument(CollectionsEnum.OFFERS, offerToUpdate).then((validated) => {
|
||||
return databaseService.update(req.session.selectedNode, CollectionsEnum.OFFERS, offerToUpdate, CollectionFieldsEnum.BOLT12, bolt12).then((updatedOffer) => {
|
||||
logger.log({ level: 'DEBUG', fileName: 'Payments', msg: 'Offer Updated', data: updatedOffer });
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: updatedOffer });
|
||||
}).catch((errDB) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'Payments', msg: 'Offer DB update error', error: errDB });
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBError: errDB });
|
||||
});
|
||||
}).catch((errValidation) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'Payments', msg: 'Offer DB validation error', error: errValidation });
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBError: errValidation });
|
||||
});
|
||||
}
|
||||
else {
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: 'NA' });
|
||||
}
|
||||
}
|
||||
if (paymentType === 'INVOICE') {
|
||||
return res.status(201).json({ paymentResponse: body, saveToDBResponse: 'NA' });
|
||||
}
|
||||
if (paymentType === 'KEYSEND') {
|
||||
return res.status(201).json(body);
|
||||
}
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Payments', 'Send Payment Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
@ -1,69 +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 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.settings.lnServerUrl + '/v1/decode';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Payment Decoded', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Payments', 'Decode Payment Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const signMessage = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Signing Message..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/signmessage';
|
||||
options.body = req.body;
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Signed', data: body });
|
||||
res.status(201).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Message', 'Sign Message Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const verifyMessage = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Verifying Message..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/checkmessage';
|
||||
options.body = req.body;
|
||||
request.post(options, (error, response, body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body });
|
||||
res.status(201).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Message', 'Verify Message Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const listConfigs = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Utility', msg: 'List Configs..' });
|
||||
options = common.getOptions(req);
|
||||
if (options.error) {
|
||||
return res.status(options.statusCode).json({ message: options.message, error: options.error });
|
||||
}
|
||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listconfigs';
|
||||
request.post(options).then((body) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Utility', msg: 'List Configs Received', data: body });
|
||||
res.status(200).json(body);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Utility', 'List Configs Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
@ -1,33 +0,0 @@
|
||||
import { Database } from '../../utils/database.js';
|
||||
import { Logger } from '../../utils/logger.js';
|
||||
import { Common } from '../../utils/common.js';
|
||||
import { CollectionsEnum } from '../../models/database.model.js';
|
||||
const logger = Logger;
|
||||
const common = Common;
|
||||
const databaseService = Database;
|
||||
export const getPageSettings = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Page Settings', msg: 'Getting Page Settings..' });
|
||||
databaseService.find(req.session.selectedNode, CollectionsEnum.PAGE_SETTINGS).then((settings) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Page Settings', msg: 'Page Settings Received', data: settings });
|
||||
res.status(200).json(settings);
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Page Settings', 'Page Settings Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
||||
export const savePageSettings = (req, res, next) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Page Settings', msg: 'Saving Page Settings..' });
|
||||
// eslint-disable-next-line arrow-body-style
|
||||
return Promise.all(req.body.map((page) => databaseService.validateDocument(CollectionsEnum.PAGE_SETTINGS, page))).then((values) => {
|
||||
return databaseService.insert(req.session.selectedNode, CollectionsEnum.PAGE_SETTINGS, req.body).then((insertRes) => {
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Page Settings', msg: 'Page Settings Updated', data: insertRes });
|
||||
res.status(201).json(insertRes);
|
||||
}).catch((insertErrRes) => {
|
||||
const err = common.handleError(insertErrRes, 'Page Settings', 'Page Settings Update Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
}).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Page Settings', 'Page Settings Validation Error', req.session.selectedNode);
|
||||
return res.status(err.statusCode).json({ message: err.message, error: err.error });
|
||||
});
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
export var ECLWSEventsEnum;
|
||||
(function (ECLWSEventsEnum) {
|
||||
ECLWSEventsEnum["PAY_RECEIVED"] = "payment-received";
|
||||
ECLWSEventsEnum["PAY_RELAYED"] = "payment-relayed";
|
||||
ECLWSEventsEnum["PAY_SENT"] = "payment-sent";
|
||||
ECLWSEventsEnum["PAY_SETTLING_ONCHAIN"] = "payment-settling-onchain";
|
||||
ECLWSEventsEnum["PAY_FAILED"] = "payment-failed";
|
||||
ECLWSEventsEnum["CHANNEL_OPENED"] = "channel-opened";
|
||||
ECLWSEventsEnum["CHANNEL_STATE_CHANGED"] = "channel-state-changed";
|
||||
ECLWSEventsEnum["CHANNEL_CLOSED"] = "channel-closed";
|
||||
ECLWSEventsEnum["ONION_MESSAGE_RECEIVED"] = "onion-message-received";
|
||||
})(ECLWSEventsEnum || (ECLWSEventsEnum = {}));
|
@ -0,0 +1,7 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getBalance } from '../../controllers/c-lightning/balance.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, getBalance);
|
||||
export default router;
|
@ -0,0 +1,12 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { listChannels, openChannel, setChannelFee, closeChannel, getLocalRemoteBalance, listForwards } from '../../controllers/c-lightning/channels.js';
|
||||
const router = Router();
|
||||
router.get('/listChannels', isAuthenticated, listChannels);
|
||||
router.post('/', isAuthenticated, openChannel);
|
||||
router.post('/setChannelFee', isAuthenticated, setChannelFee);
|
||||
router.delete('/:channelId', isAuthenticated, closeChannel);
|
||||
router.get('/localremotebalance', isAuthenticated, getLocalRemoteBalance);
|
||||
router.get('/listForwards', isAuthenticated, listForwards);
|
||||
export default router;
|
@ -0,0 +1,7 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getFees } from '../../controllers/c-lightning/fees.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, getFees);
|
||||
export default router;
|
@ -1,7 +1,7 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getInfo } from '../../controllers/cln/getInfo.js';
|
||||
import { getInfo } from '../../controllers/c-lightning/getInfo.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, getInfo);
|
||||
export default router;
|
@ -1,25 +1,29 @@
|
||||
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';
|
||||
import paymentsCLRoutes from './payments.js';
|
||||
import peersCLRoutes from './peers.js';
|
||||
import networkCLRoutes from './network.js';
|
||||
import messageCLRoutes from './message.js';
|
||||
import offersCLRoutes from './offers.js';
|
||||
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 },
|
||||
{ path: '/payments', route: paymentsCLRoutes },
|
||||
{ path: '/peers', route: peersCLRoutes },
|
||||
{ path: '/network', route: networkCLRoutes },
|
||||
{ path: '/offers', route: offersCLRoutes },
|
||||
{ path: '/utility', route: utilityCLRoutes }
|
||||
{ path: '/message', route: messageCLRoutes },
|
||||
{ path: '/offers', route: offersCLRoutes }
|
||||
];
|
||||
clRoutes.forEach((route) => {
|
||||
router.use(route.path, route.route);
|
@ -1,9 +1,9 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { listInvoices, addInvoice, deleteExpiredInvoice } from '../../controllers/cln/invoices.js';
|
||||
import { listInvoices, addInvoice, deleteExpiredInvoice } from '../../controllers/c-lightning/invoices.js';
|
||||
const router = Router();
|
||||
router.post('/lookup/', isAuthenticated, listInvoices);
|
||||
router.get('/', isAuthenticated, listInvoices);
|
||||
router.post('/', isAuthenticated, addInvoice);
|
||||
router.post('/delete/', isAuthenticated, deleteExpiredInvoice);
|
||||
router.delete('/', isAuthenticated, deleteExpiredInvoice);
|
||||
export default router;
|
@ -1,10 +1,8 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { decodePayment, signMessage, verifyMessage, listConfigs } from '../../controllers/cln/utility.js';
|
||||
import { signMessage, verifyMessage } from '../../controllers/c-lightning/message.js';
|
||||
const router = Router();
|
||||
router.post('/decode', isAuthenticated, decodePayment);
|
||||
router.post('/sign', isAuthenticated, signMessage);
|
||||
router.post('/verify', isAuthenticated, verifyMessage);
|
||||
router.get('/listConfigs', isAuthenticated, listConfigs);
|
||||
export default router;
|
@ -0,0 +1,10 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getRoute, listNode, listChannel, feeRates } from '../../controllers/c-lightning/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);
|
||||
export default router;
|
@ -1,12 +1,12 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { listOfferBookmarks, deleteOfferBookmark, listOffers, disableOffer, createOffer, fetchOfferInvoice } from '../../controllers/cln/offers.js';
|
||||
import { listOfferBookmarks, deleteOfferBookmark, listOffers, disableOffer, createOffer, fetchOfferInvoice } from '../../controllers/c-lightning/offers.js';
|
||||
const router = Router();
|
||||
router.get('/offerbookmarks', isAuthenticated, listOfferBookmarks);
|
||||
router.post('/offerbookmark/delete', isAuthenticated, deleteOfferBookmark);
|
||||
router.delete('/offerbookmark/:offerStr', isAuthenticated, deleteOfferBookmark);
|
||||
router.get('/', isAuthenticated, listOffers);
|
||||
router.post('/', isAuthenticated, createOffer);
|
||||
router.post('/fetchOfferInvoice', isAuthenticated, fetchOfferInvoice);
|
||||
router.post('/disableOffer', isAuthenticated, disableOffer);
|
||||
router.delete('/:offerID', isAuthenticated, disableOffer);
|
||||
export default router;
|
@ -1,9 +1,9 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getNewAddress, onChainWithdraw, getUTXOs } from '../../controllers/cln/onchain.js';
|
||||
import { getNewAddress, onChainWithdraw, getUTXOs } from '../../controllers/c-lightning/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;
|
@ -1,8 +1,9 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { listPayments, postPayment } from '../../controllers/cln/payments.js';
|
||||
import { listPayments, decodePayment, postPayment } from '../../controllers/c-lightning/payments.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, listPayments);
|
||||
router.get('/decode/:payReq', isAuthenticated, decodePayment);
|
||||
router.post('/', isAuthenticated, postPayment);
|
||||
export default router;
|
@ -1,9 +1,9 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getPeers, postPeer, deletePeer } from '../../controllers/cln/peers.js';
|
||||
import { getPeers, postPeer, deletePeer } from '../../controllers/c-lightning/peers.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, getPeers);
|
||||
router.post('/', isAuthenticated, postPeer);
|
||||
router.post('/disconnect/', isAuthenticated, deletePeer);
|
||||
router.delete('/:peerId', isAuthenticated, deletePeer);
|
||||
export default router;
|
@ -1,12 +0,0 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { listPeerChannels, openChannel, setChannelFee, closeChannel, listForwards, funderUpdatePolicy } from '../../controllers/cln/channels.js';
|
||||
const router = Router();
|
||||
router.get('/listPeerChannels', isAuthenticated, listPeerChannels);
|
||||
router.post('/', isAuthenticated, openChannel);
|
||||
router.post('/setChannelFee', isAuthenticated, setChannelFee);
|
||||
router.post('/close/', isAuthenticated, closeChannel);
|
||||
router.post('/listForwards', isAuthenticated, listForwards);
|
||||
router.post('/funderUpdate', isAuthenticated, funderUpdatePolicy);
|
||||
export default router;
|
@ -1,10 +0,0 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getRoute, listChannels, feeRates, listNodes } from '../../controllers/cln/network.js';
|
||||
const router = Router();
|
||||
router.post('/listNodes', isAuthenticated, listNodes);
|
||||
router.post('/getRoute', isAuthenticated, getRoute);
|
||||
router.post('/feeRates', isAuthenticated, feeRates);
|
||||
router.post('/listChannels', isAuthenticated, listChannels);
|
||||
export default router;
|
@ -1,12 +1,11 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getChannels, getChannelStats, openChannel, updateChannelRelayFee, closeChannel, circularRebalance } from '../../controllers/eclair/channels.js';
|
||||
import { getChannels, getChannelStats, openChannel, updateChannelRelayFee, closeChannel } from '../../controllers/eclair/channels.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, getChannels);
|
||||
router.get('/stats', isAuthenticated, getChannelStats);
|
||||
router.post('/', isAuthenticated, openChannel);
|
||||
router.post('/updateRelayFee', isAuthenticated, updateChannelRelayFee);
|
||||
router.post('/circularRebalance', circularRebalance);
|
||||
router.delete('/', isAuthenticated, closeChannel);
|
||||
export default router;
|
||||
|
@ -1,8 +1,7 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { getNodes, findRouteBetweenNodes } from '../../controllers/eclair/network.js';
|
||||
import { getNodes } from '../../controllers/eclair/network.js';
|
||||
const router = Router();
|
||||
router.get('/nodes/:id', isAuthenticated, getNodes);
|
||||
router.get('/routebetweennodes', isAuthenticated, findRouteBetweenNodes);
|
||||
export default router;
|
||||
|
@ -1,11 +1,10 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { queryPaymentRoute, decodePayment, getSentPaymentsInformation, postPayment, sendPaymentToRoute } from '../../controllers/eclair/payments.js';
|
||||
import { queryPaymentRoute, decodePayment, getSentPaymentsInformation, postPayment } from '../../controllers/eclair/payments.js';
|
||||
const router = Router();
|
||||
router.get('/route/', isAuthenticated, queryPaymentRoute);
|
||||
router.get('/decode/:invoice', isAuthenticated, decodePayment);
|
||||
router.post('/getsentinfos', isAuthenticated, getSentPaymentsInformation);
|
||||
router.post('/sendtoroute', isAuthenticated, sendPaymentToRoute);
|
||||
router.post('/', isAuthenticated, postPayment);
|
||||
export default router;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { listInvoices, invoiceLookup, addInvoice } from '../../controllers/lnd/invoices.js';
|
||||
import { listInvoices, getInvoice, addInvoice } from '../../controllers/lnd/invoices.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, listInvoices);
|
||||
router.get('/lookup/', isAuthenticated, invoiceLookup);
|
||||
router.get('/:rHashStr', isAuthenticated, getInvoice);
|
||||
router.post('/', isAuthenticated, addInvoice);
|
||||
export default router;
|
||||
|
@ -1,11 +1,10 @@
|
||||
import exprs from 'express';
|
||||
const { Router } = exprs;
|
||||
import { isAuthenticated } from '../../utils/authCheck.js';
|
||||
import { decodePayment, decodePayments, getPayments, getAllLightningTransactions, paymentLookup } from '../../controllers/lnd/payments.js';
|
||||
import { decodePayment, decodePayments, getPayments, getAllLightningTransactions } from '../../controllers/lnd/payments.js';
|
||||
const router = Router();
|
||||
router.get('/', isAuthenticated, getPayments);
|
||||
router.get('/alltransactions', isAuthenticated, getAllLightningTransactions);
|
||||
router.get('/decode/:payRequest', isAuthenticated, decodePayment);
|
||||
router.get('/lookup/:paymentHash', isAuthenticated, paymentLookup);
|
||||
router.post('/', isAuthenticated, decodePayments);
|
||||
export default router;
|
||||
|