Merge pull request #6 from shocknet/bug/wallet_status
Bug/wallet status
This commit is contained in:
commit
6c76fa175e
5 changed files with 253 additions and 199 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
// app/lnd.js
|
// app/lnd.js
|
||||||
|
|
||||||
const debug = require("debug")("lncliweb:lnd");
|
|
||||||
const logger = require("winston");
|
const logger = require("winston");
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
||||||
309
src/routes.js
309
src/routes.js
|
|
@ -12,6 +12,7 @@ const responseTime = require("response-time");
|
||||||
const getListPage = require("../utils/paginate");
|
const getListPage = require("../utils/paginate");
|
||||||
const auth = require("../services/auth/auth");
|
const auth = require("../services/auth/auth");
|
||||||
const FS = require("../utils/fs");
|
const FS = require("../utils/fs");
|
||||||
|
const LightningServices = require("../utils/lightningServices");
|
||||||
const GunDB = require("../services/gunDB/Mediator");
|
const GunDB = require("../services/gunDB/Mediator");
|
||||||
|
|
||||||
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10;
|
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10;
|
||||||
|
|
@ -19,10 +20,7 @@ const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10;
|
||||||
// module.exports = (app) => {
|
// module.exports = (app) => {
|
||||||
module.exports = (
|
module.exports = (
|
||||||
app,
|
app,
|
||||||
lightning,
|
|
||||||
config,
|
config,
|
||||||
walletUnlocker,
|
|
||||||
lnServicesData,
|
|
||||||
mySocketsEvents,
|
mySocketsEvents,
|
||||||
{ serverPort }
|
{ serverPort }
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -34,6 +32,8 @@ module.exports = (
|
||||||
|
|
||||||
const getAvailableService = () =>
|
const getAvailableService = () =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
|
|
||||||
lightning.getInfo({}, (err, response) => {
|
lightning.getInfo({}, (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.message.includes("unknown service lnrpc.Lightning")) {
|
if (err.message.includes("unknown service lnrpc.Lightning")) {
|
||||||
|
|
@ -118,16 +118,7 @@ module.exports = (
|
||||||
};
|
};
|
||||||
|
|
||||||
const recreateLnServices = async () => {
|
const recreateLnServices = async () => {
|
||||||
const lnServices = await require("../services/lnd/lightning")(
|
await LightningServices.init();
|
||||||
lnServicesData.lndProto,
|
|
||||||
lnServicesData.lndHost,
|
|
||||||
lnServicesData.lndCertPath,
|
|
||||||
lnServicesData.macaroonPath
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line prefer-destructuring, no-param-reassign
|
|
||||||
lightning = lnServices.lightning;
|
|
||||||
// eslint-disable-next-line prefer-destructuring, no-param-reassign
|
|
||||||
walletUnlocker = lnServices.walletUnlocker;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
@ -138,6 +129,7 @@ module.exports = (
|
||||||
const args = {
|
const args = {
|
||||||
wallet_password: Buffer.from(password, "utf-8")
|
wallet_password: Buffer.from(password, "utf-8")
|
||||||
};
|
};
|
||||||
|
const { walletUnlocker } = LightningServices.services;
|
||||||
walletUnlocker.unlockWallet(args, (unlockErr, unlockResponse) => {
|
walletUnlocker.unlockWallet(args, (unlockErr, unlockResponse) => {
|
||||||
if (unlockErr) {
|
if (unlockErr) {
|
||||||
reject(unlockErr);
|
reject(unlockErr);
|
||||||
|
|
@ -221,9 +213,11 @@ module.exports = (
|
||||||
walletStatus: walletStatus ? availableService.walletStatus : null
|
walletStatus: walletStatus ? availableService.walletStatus : null
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error(err);
|
||||||
|
const sanitizedMessage = sanitizeLNDError(err.message);
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
walletStatus: sanitizeLNDError(err.message),
|
walletExists: null,
|
||||||
code: err.code
|
walletStatus: sanitizedMessage ? sanitizedMessage : "An unknown error has occurred, please try restarting your LND and API servers"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -279,6 +273,7 @@ module.exports = (
|
||||||
return false;
|
return false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.debug("Unlock Error:", err);
|
logger.debug("Unlock Error:", err);
|
||||||
|
console.error(err);
|
||||||
res.status(400);
|
res.status(400);
|
||||||
res.send({ field: "user", errorMessage: sanitizeLNDError(err.message), success: false });
|
res.send({ field: "user", errorMessage: sanitizeLNDError(err.message), success: false });
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -286,6 +281,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/connect", (req, res) => {
|
app.post("/api/lnd/connect", (req, res) => {
|
||||||
|
const { lightning, walletUnlocker } = LightningServices.services;
|
||||||
const args = {
|
const args = {
|
||||||
wallet_password: Buffer.from(req.body.password, "utf-8")
|
wallet_password: Buffer.from(req.body.password, "utf-8")
|
||||||
};
|
};
|
||||||
|
|
@ -326,132 +322,152 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/wallet", async (req, res) => {
|
app.post("/api/lnd/wallet", async (req, res) => {
|
||||||
const { password, alias } = req.body;
|
try {
|
||||||
const healthResponse = await checkHealth();
|
const { walletUnlocker } = LightningServices.services;
|
||||||
if (!alias) {
|
const { password, alias } = req.body;
|
||||||
return res.status(400).json({
|
const healthResponse = await checkHealth();
|
||||||
field: "alias",
|
if (!alias) {
|
||||||
errorMessage: "Please specify an alias for your new wallet"
|
return res.status(400).json({
|
||||||
});
|
field: "alias",
|
||||||
}
|
errorMessage: "Please specify an alias for your new wallet"
|
||||||
|
});
|
||||||
if (!password) {
|
|
||||||
return res.status(400).json({
|
|
||||||
field: "password",
|
|
||||||
errorMessage: "Please specify a password for your new wallet"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (password.length < 8) {
|
|
||||||
return res.status(400).json({
|
|
||||||
field: "password",
|
|
||||||
errorMessage: "Please specify a password that's longer than 8 characters"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (healthResponse.LNDStatus.service !== "walletUnlocker") {
|
|
||||||
return res.status(400).json({
|
|
||||||
field: "wallet",
|
|
||||||
errorMessage: "Wallet is already unlocked"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
walletUnlocker.genSeed({}, async (genSeedErr, genSeedResponse) => {
|
|
||||||
if (genSeedErr) {
|
|
||||||
logger.debug("GenSeed Error:", genSeedErr);
|
|
||||||
|
|
||||||
const healthResponse = await checkHealth();
|
|
||||||
if (healthResponse.LNDStatus.success) {
|
|
||||||
const message = genSeedErr.details;
|
|
||||||
return res
|
|
||||||
.status(400)
|
|
||||||
.send({ field: "GenSeed", errorMessage, success: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
.status(500)
|
|
||||||
.send({ field: "health", errorMessage: "LND is down", success: false });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("GenSeed:", genSeedResponse);
|
if (!password) {
|
||||||
const mnemonicPhrase = genSeedResponse.cipher_seed_mnemonic;
|
return res.status(400).json({
|
||||||
const walletArgs = {
|
field: "password",
|
||||||
wallet_password: Buffer.from(password, "utf8"),
|
errorMessage: "Please specify a password for your new wallet"
|
||||||
cipher_seed_mnemonic: mnemonicPhrase
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// Register user before creating wallet
|
if (password.length < 8) {
|
||||||
const publicKey = await GunDB.register(alias, password);
|
return res.status(400).json({
|
||||||
|
field: "password",
|
||||||
|
errorMessage: "Please specify a password that's longer than 8 characters"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (healthResponse.LNDStatus.service !== "walletUnlocker") {
|
||||||
|
return res.status(400).json({
|
||||||
|
field: "wallet",
|
||||||
|
errorMessage: "Wallet is already unlocked"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
walletUnlocker.genSeed({}, async (genSeedErr, genSeedResponse) => {
|
||||||
|
try {
|
||||||
|
if (genSeedErr) {
|
||||||
|
logger.debug("GenSeed Error:", genSeedErr);
|
||||||
|
|
||||||
walletUnlocker.initWallet(
|
|
||||||
walletArgs,
|
|
||||||
async (initWalletErr, initWalletResponse) => {
|
|
||||||
if (initWalletErr) {
|
|
||||||
logger.error("initWallet Error:", initWalletErr.message);
|
|
||||||
const healthResponse = await checkHealth();
|
const healthResponse = await checkHealth();
|
||||||
if (healthResponse.LNDStatus.success) {
|
if (healthResponse.LNDStatus.success) {
|
||||||
const errorMessage = initWalletErr.details;
|
const message = genSeedErr.details;
|
||||||
|
return res
|
||||||
return res.status(400).json({
|
.status(400)
|
||||||
field: "initWallet",
|
.send({ field: "GenSeed", errorMessage: message, success: false });
|
||||||
errorMessage,
|
|
||||||
success: false
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return res.status(500).json({
|
|
||||||
field: "health",
|
return res
|
||||||
errorMessage: "LND is down",
|
.status(500)
|
||||||
success: false
|
.send({ field: "health", errorMessage: "LND is down", success: false });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
logger.debug("initWallet:", initWalletResponse);
|
|
||||||
|
|
||||||
const waitUntilFileExists = seconds => {
|
logger.debug("GenSeed:", genSeedResponse);
|
||||||
logger.debug(
|
const mnemonicPhrase = genSeedResponse.cipher_seed_mnemonic;
|
||||||
`Waiting for admin.macaroon to be created. Seconds passed: ${seconds}`
|
const walletArgs = {
|
||||||
);
|
wallet_password: Buffer.from(password, "utf8"),
|
||||||
setTimeout(async () => {
|
cipher_seed_mnemonic: mnemonicPhrase
|
||||||
try {
|
|
||||||
const macaroonExists = await FS.access(
|
|
||||||
lnServicesData.macaroonPath
|
|
||||||
);
|
|
||||||
if (!macaroonExists) {
|
|
||||||
return waitUntilFileExists(seconds + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("admin.macaroon file created");
|
|
||||||
|
|
||||||
mySocketsEvents.emit("updateLightning");
|
|
||||||
const lnServices = await require("../services/lnd/lightning")(
|
|
||||||
lnServicesData.lndProto,
|
|
||||||
lnServicesData.lndHost,
|
|
||||||
lnServicesData.lndCertPath,
|
|
||||||
lnServicesData.macaroonPath
|
|
||||||
);
|
|
||||||
lightning = lnServices.lightning;
|
|
||||||
walletUnlocker = lnServices.walletUnlocker;
|
|
||||||
const token = await auth.generateToken();
|
|
||||||
return res.json({
|
|
||||||
mnemonicPhrase,
|
|
||||||
authorization: token,
|
|
||||||
user: {
|
|
||||||
alias,
|
|
||||||
publicKey
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
res.status(400).json({
|
|
||||||
field: "unknown",
|
|
||||||
errorMessage: sanitizeLNDError(err.message)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
waitUntilFileExists(1);
|
// Register user before creating wallet
|
||||||
|
const publicKey = await GunDB.register(alias, password);
|
||||||
|
|
||||||
|
walletUnlocker.initWallet(
|
||||||
|
walletArgs,
|
||||||
|
async (initWalletErr, initWalletResponse) => {
|
||||||
|
try {
|
||||||
|
if (initWalletErr) {
|
||||||
|
logger.error("initWallet Error:", initWalletErr.message);
|
||||||
|
const healthResponse = await checkHealth();
|
||||||
|
if (healthResponse.LNDStatus.success) {
|
||||||
|
const errorMessage = initWalletErr.details;
|
||||||
|
|
||||||
|
return res.status(400).json({
|
||||||
|
field: "initWallet",
|
||||||
|
errorMessage,
|
||||||
|
success: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.status(500).json({
|
||||||
|
field: "health",
|
||||||
|
errorMessage: "LND is down",
|
||||||
|
success: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logger.info("initWallet:", initWalletResponse);
|
||||||
|
|
||||||
|
const waitUntilFileExists = seconds => {
|
||||||
|
logger.info(
|
||||||
|
`Waiting for admin.macaroon to be created. Seconds passed: ${seconds} Path: ${LightningServices.servicesConfig.macaroonPath}`
|
||||||
|
);
|
||||||
|
setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
const macaroonExists = await FS.access(
|
||||||
|
LightningServices.servicesConfig.macaroonPath
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!macaroonExists) {
|
||||||
|
return waitUntilFileExists(seconds + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("admin.macaroon file created");
|
||||||
|
|
||||||
|
await LightningServices.init();
|
||||||
|
|
||||||
|
const token = await auth.generateToken();
|
||||||
|
return res.json({
|
||||||
|
mnemonicPhrase,
|
||||||
|
authorization: token,
|
||||||
|
user: {
|
||||||
|
alias,
|
||||||
|
publicKey
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(400).json({
|
||||||
|
field: "unknown",
|
||||||
|
errorMessage: sanitizeLNDError(err.message)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
waitUntilFileExists(1);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return res.status(500).json({
|
||||||
|
field: "unknown",
|
||||||
|
errorMessage: err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return res.status(500).json({
|
||||||
|
field: "unknown",
|
||||||
|
errorMessage: err
|
||||||
|
})
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
});
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return res.status(500).json({
|
||||||
|
field: "unknown",
|
||||||
|
errorMessage: err
|
||||||
|
})
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/wallet/existing", async (req, res) => {
|
app.post("/api/lnd/wallet/existing", async (req, res) => {
|
||||||
|
|
@ -519,7 +535,8 @@ module.exports = (
|
||||||
|
|
||||||
// get lnd info
|
// get lnd info
|
||||||
app.get("/api/lnd/getinfo", (req, res) => {
|
app.get("/api/lnd/getinfo", (req, res) => {
|
||||||
// logger.debug("Estimated Fee:", lightning.estimateFee);
|
const { lightning } = LightningServices.services;
|
||||||
|
|
||||||
lightning.getInfo({}, async (err, response) => {
|
lightning.getInfo({}, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error("GetInfo Error:", err);
|
logger.error("GetInfo Error:", err);
|
||||||
|
|
@ -546,6 +563,8 @@ module.exports = (
|
||||||
|
|
||||||
// get lnd node info
|
// get lnd node info
|
||||||
app.post("/api/lnd/getnodeinfo", (req, res) => {
|
app.post("/api/lnd/getnodeinfo", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
|
|
||||||
lightning.getNodeInfo(
|
lightning.getNodeInfo(
|
||||||
{ pub_key: req.body.pubkey },
|
{ pub_key: req.body.pubkey },
|
||||||
async (err, response) => {
|
async (err, response) => {
|
||||||
|
|
@ -570,6 +589,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/lnd/getnetworkinfo", (req, res) => {
|
app.get("/api/lnd/getnetworkinfo", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.getNetworkInfo({}, async (err, response) => {
|
lightning.getNetworkInfo({}, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.debug("GetNetworkInfo Error:", err);
|
logger.debug("GetNetworkInfo Error:", err);
|
||||||
|
|
@ -591,6 +611,7 @@ module.exports = (
|
||||||
|
|
||||||
// get lnd node active channels list
|
// get lnd node active channels list
|
||||||
app.get("/api/lnd/listpeers", (req, res) => {
|
app.get("/api/lnd/listpeers", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.listPeers({}, async (err, response) => {
|
lightning.listPeers({}, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.debug("ListPeers Error:", err);
|
logger.debug("ListPeers Error:", err);
|
||||||
|
|
@ -612,6 +633,7 @@ module.exports = (
|
||||||
|
|
||||||
// newaddress
|
// newaddress
|
||||||
app.post("/api/lnd/newaddress", (req, res) => {
|
app.post("/api/lnd/newaddress", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.newAddress({ type: req.body.type }, async (err, response) => {
|
lightning.newAddress({ type: req.body.type }, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.debug("NewAddress Error:", err);
|
logger.debug("NewAddress Error:", err);
|
||||||
|
|
@ -633,6 +655,7 @@ module.exports = (
|
||||||
|
|
||||||
// connect peer to lnd node
|
// connect peer to lnd node
|
||||||
app.post("/api/lnd/connectpeer", async (req, res) => {
|
app.post("/api/lnd/connectpeer", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
if (req.limituser) {
|
if (req.limituser) {
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
if (health.LNDStatus.success) {
|
if (health.LNDStatus.success) {
|
||||||
|
|
@ -663,6 +686,7 @@ module.exports = (
|
||||||
|
|
||||||
// disconnect peer from lnd node
|
// disconnect peer from lnd node
|
||||||
app.post("/api/lnd/disconnectpeer", async (req, res) => {
|
app.post("/api/lnd/disconnectpeer", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
if (req.limituser) {
|
if (req.limituser) {
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
if (health.LNDStatus.success) {
|
if (health.LNDStatus.success) {
|
||||||
|
|
@ -690,6 +714,7 @@ module.exports = (
|
||||||
|
|
||||||
// get lnd node opened channels list
|
// get lnd node opened channels list
|
||||||
app.get("/api/lnd/listchannels", (req, res) => {
|
app.get("/api/lnd/listchannels", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.listChannels({}, async (err, response) => {
|
lightning.listChannels({}, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.debug("ListChannels Error:", err);
|
logger.debug("ListChannels Error:", err);
|
||||||
|
|
@ -711,6 +736,7 @@ module.exports = (
|
||||||
|
|
||||||
// get lnd node pending channels list
|
// get lnd node pending channels list
|
||||||
app.get("/api/lnd/pendingchannels", (req, res) => {
|
app.get("/api/lnd/pendingchannels", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.pendingChannels({}, async (err, response) => {
|
lightning.pendingChannels({}, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.debug("PendingChannels Error:", err);
|
logger.debug("PendingChannels Error:", err);
|
||||||
|
|
@ -731,6 +757,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/lnd/unifiedTrx", (req, res) => {
|
app.get("/api/lnd/unifiedTrx", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { itemsPerPage, page, reversed = true } = req.query;
|
const { itemsPerPage, page, reversed = true } = req.query;
|
||||||
const offset = (page - 1) * itemsPerPage;
|
const offset = (page - 1) * itemsPerPage;
|
||||||
lightning.listPayments({}, (err, { payments = [] } = {}) => {
|
lightning.listPayments({}, (err, { payments = [] } = {}) => {
|
||||||
|
|
@ -776,6 +803,7 @@ module.exports = (
|
||||||
|
|
||||||
// get lnd node payments list
|
// get lnd node payments list
|
||||||
app.get("/api/lnd/listpayments", (req, res) => {
|
app.get("/api/lnd/listpayments", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { itemsPerPage, page, paginate = true } = req.query;
|
const { itemsPerPage, page, paginate = true } = req.query;
|
||||||
lightning.listPayments({
|
lightning.listPayments({
|
||||||
include_incomplete: !!req.include_incomplete,
|
include_incomplete: !!req.include_incomplete,
|
||||||
|
|
@ -796,6 +824,7 @@ module.exports = (
|
||||||
|
|
||||||
// get lnd node invoices list
|
// get lnd node invoices list
|
||||||
app.get("/api/lnd/listinvoices", (req, res) => {
|
app.get("/api/lnd/listinvoices", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { page, itemsPerPage, reversed = true } = req.query;
|
const { page, itemsPerPage, reversed = true } = req.query;
|
||||||
const offset = (page - 1) * itemsPerPage;
|
const offset = (page - 1) * itemsPerPage;
|
||||||
// const limit = page * itemsPerPage;
|
// const limit = page * itemsPerPage;
|
||||||
|
|
@ -826,6 +855,7 @@ module.exports = (
|
||||||
|
|
||||||
// get lnd node forwarding history
|
// get lnd node forwarding history
|
||||||
app.get("/api/lnd/forwardinghistory", (req, res) => {
|
app.get("/api/lnd/forwardinghistory", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.forwardingHistory({}, async (err, response) => {
|
lightning.forwardingHistory({}, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.debug("ForwardingHistory Error:", err);
|
logger.debug("ForwardingHistory Error:", err);
|
||||||
|
|
@ -847,6 +877,7 @@ module.exports = (
|
||||||
|
|
||||||
// get the lnd node wallet balance
|
// get the lnd node wallet balance
|
||||||
app.get("/api/lnd/walletbalance", (req, res) => {
|
app.get("/api/lnd/walletbalance", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.walletBalance({}, async (err, response) => {
|
lightning.walletBalance({}, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.debug("WalletBalance Error:", err);
|
logger.debug("WalletBalance Error:", err);
|
||||||
|
|
@ -868,6 +899,7 @@ module.exports = (
|
||||||
|
|
||||||
// get the lnd node wallet balance and channel balance
|
// get the lnd node wallet balance and channel balance
|
||||||
app.get("/api/lnd/balance", async (req, res) => {
|
app.get("/api/lnd/balance", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
lightning.walletBalance({}, (err, walletBalance) => {
|
lightning.walletBalance({}, (err, walletBalance) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -910,6 +942,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/decodePayReq", (req, res) => {
|
app.post("/api/lnd/decodePayReq", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { payReq } = req.body;
|
const { payReq } = req.body;
|
||||||
lightning.decodePayReq({ pay_req: payReq }, async (err, paymentRequest) => {
|
lightning.decodePayReq({ pay_req: payReq }, async (err, paymentRequest) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -932,6 +965,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/lnd/channelbalance", (req, res) => {
|
app.get("/api/lnd/channelbalance", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.channelBalance({}, async (err, response) => {
|
lightning.channelBalance({}, async (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.debug("ChannelBalance Error:", err);
|
logger.debug("ChannelBalance Error:", err);
|
||||||
|
|
@ -953,6 +987,7 @@ module.exports = (
|
||||||
|
|
||||||
// openchannel
|
// openchannel
|
||||||
app.post("/api/lnd/openchannel", async (req, res) => {
|
app.post("/api/lnd/openchannel", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
if (req.limituser) {
|
if (req.limituser) {
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
if (health.LNDStatus.success) {
|
if (health.LNDStatus.success) {
|
||||||
|
|
@ -994,6 +1029,7 @@ module.exports = (
|
||||||
|
|
||||||
// closechannel
|
// closechannel
|
||||||
app.post("/api/lnd/closechannel", async (req, res) => {
|
app.post("/api/lnd/closechannel", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
if (req.limituser) {
|
if (req.limituser) {
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
if (health.LNDStatus.success) {
|
if (health.LNDStatus.success) {
|
||||||
|
|
@ -1043,6 +1079,7 @@ module.exports = (
|
||||||
|
|
||||||
// sendpayment
|
// sendpayment
|
||||||
app.post("/api/lnd/sendpayment", async (req, res) => {
|
app.post("/api/lnd/sendpayment", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
if (req.limituser) {
|
if (req.limituser) {
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
if (health.LNDStatus.success) {
|
if (health.LNDStatus.success) {
|
||||||
|
|
@ -1095,6 +1132,7 @@ module.exports = (
|
||||||
|
|
||||||
// addinvoice
|
// addinvoice
|
||||||
app.post("/api/lnd/addinvoice", async (req, res) => {
|
app.post("/api/lnd/addinvoice", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
if (req.limituser) {
|
if (req.limituser) {
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
if (health.LNDStatus.success) {
|
if (health.LNDStatus.success) {
|
||||||
|
|
@ -1134,6 +1172,7 @@ module.exports = (
|
||||||
|
|
||||||
// signmessage
|
// signmessage
|
||||||
app.post("/api/lnd/signmessage", async (req, res) => {
|
app.post("/api/lnd/signmessage", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
if (req.limituser) {
|
if (req.limituser) {
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
if (health.LNDStatus.success) {
|
if (health.LNDStatus.success) {
|
||||||
|
|
@ -1164,6 +1203,7 @@ module.exports = (
|
||||||
|
|
||||||
// verifymessage
|
// verifymessage
|
||||||
app.post("/api/lnd/verifymessage", (req, res) => {
|
app.post("/api/lnd/verifymessage", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.verifyMessage(
|
lightning.verifyMessage(
|
||||||
{ msg: Buffer.from(req.body.msg, "utf8"), signature: req.body.signature },
|
{ msg: Buffer.from(req.body.msg, "utf8"), signature: req.body.signature },
|
||||||
async (err, response) => {
|
async (err, response) => {
|
||||||
|
|
@ -1185,6 +1225,7 @@ module.exports = (
|
||||||
|
|
||||||
// sendcoins
|
// sendcoins
|
||||||
app.post("/api/lnd/sendcoins", async (req, res) => {
|
app.post("/api/lnd/sendcoins", async (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
if (req.limituser) {
|
if (req.limituser) {
|
||||||
const health = await checkHealth();
|
const health = await checkHealth();
|
||||||
if (health.LNDStatus.success) {
|
if (health.LNDStatus.success) {
|
||||||
|
|
@ -1217,6 +1258,7 @@ module.exports = (
|
||||||
|
|
||||||
// queryroute
|
// queryroute
|
||||||
app.post("/api/lnd/queryroute", (req, res) => {
|
app.post("/api/lnd/queryroute", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const numRoutes =
|
const numRoutes =
|
||||||
config.maxNumRoutesToQuery || DEFAULT_MAX_NUM_ROUTES_TO_QUERY;
|
config.maxNumRoutesToQuery || DEFAULT_MAX_NUM_ROUTES_TO_QUERY;
|
||||||
lightning.queryRoutes(
|
lightning.queryRoutes(
|
||||||
|
|
@ -1239,6 +1281,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/estimatefee", (req, res) => {
|
app.post("/api/lnd/estimatefee", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { amount, confirmationBlocks } = req.body;
|
const { amount, confirmationBlocks } = req.body;
|
||||||
lightning.estimateFee(
|
lightning.estimateFee(
|
||||||
{
|
{
|
||||||
|
|
@ -1267,6 +1310,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/listunspent", (req, res) => {
|
app.post("/api/lnd/listunspent", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { minConfirmations = 3, maxConfirmations = 6 } = req.body;
|
const { minConfirmations = 3, maxConfirmations = 6 } = req.body;
|
||||||
lightning.listUnspent(
|
lightning.listUnspent(
|
||||||
{
|
{
|
||||||
|
|
@ -1284,6 +1328,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/lnd/transactions", (req, res) => {
|
app.get("/api/lnd/transactions", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { page, paginate = true, itemsPerPage } = req.query;
|
const { page, paginate = true, itemsPerPage } = req.query;
|
||||||
lightning.getTransactions({}, (err, { transactions = [] } = {}) => {
|
lightning.getTransactions({}, (err, { transactions = [] } = {}) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -1299,6 +1344,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/sendmany", (req, res) => {
|
app.post("/api/lnd/sendmany", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { addresses } = req.body;
|
const { addresses } = req.body;
|
||||||
lightning.sendMany({ AddrToAmount: addresses }, (err, transactions) => {
|
lightning.sendMany({ AddrToAmount: addresses }, (err, transactions) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -1310,6 +1356,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/lnd/closedchannels", (req, res) => {
|
app.get("/api/lnd/closedchannels", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { closeTypeFilters = [] } = req.query;
|
const { closeTypeFilters = [] } = req.query;
|
||||||
const lndFilters = closeTypeFilters.reduce(
|
const lndFilters = closeTypeFilters.reduce(
|
||||||
(filters, filter) => ({ ...filters, [filter]: true }),
|
(filters, filter) => ({ ...filters, [filter]: true }),
|
||||||
|
|
@ -1325,6 +1372,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/exportchanbackup", (req, res) => {
|
app.post("/api/lnd/exportchanbackup", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
const { channelPoint } = req.body;
|
const { channelPoint } = req.body;
|
||||||
lightning.exportChannelBackup(
|
lightning.exportChannelBackup(
|
||||||
{ chan_point: { funding_txid_str: channelPoint } },
|
{ chan_point: { funding_txid_str: channelPoint } },
|
||||||
|
|
@ -1339,6 +1387,7 @@ module.exports = (
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/lnd/exportallchanbackups", (req, res) => {
|
app.post("/api/lnd/exportallchanbackups", (req, res) => {
|
||||||
|
const { lightning } = LightningServices.services;
|
||||||
lightning.exportAllChannelBackups({}, (err, channelBackups) => {
|
lightning.exportAllChannelBackups({}, (err, channelBackups) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return handleError(res, err);
|
return handleError(res, err);
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@ const server = program => {
|
||||||
const Https = require("https");
|
const Https = require("https");
|
||||||
const Http = require("http");
|
const Http = require("http");
|
||||||
const Express = require("express");
|
const Express = require("express");
|
||||||
// const Cluster = require("cluster");
|
const LightningServices = require("../utils/lightningServices");
|
||||||
// const OS = require("os");
|
|
||||||
const app = Express();
|
const app = Express();
|
||||||
|
|
||||||
const FS = require("../utils/fs");
|
const FS = require("../utils/fs");
|
||||||
|
|
@ -32,12 +31,6 @@ const server = program => {
|
||||||
// utilities functions =================
|
// utilities functions =================
|
||||||
require("../utils/server-utils")(module);
|
require("../utils/server-utils")(module);
|
||||||
|
|
||||||
// setup lightning client =================
|
|
||||||
const lnrpc = require("../services/lnd/lightning");
|
|
||||||
const lndHost = program.lndhost || defaults.lndHost;
|
|
||||||
const lndCertPath = program.lndCertPath || defaults.lndCertPath;
|
|
||||||
const macaroonPath = program.macaroonPath || defaults.macaroonPath;
|
|
||||||
|
|
||||||
logger.info("Mainnet Mode:", !!program.mainnet);
|
logger.info("Mainnet Mode:", !!program.mainnet);
|
||||||
|
|
||||||
const wait = seconds =>
|
const wait = seconds =>
|
||||||
|
|
@ -48,24 +41,11 @@ const server = program => {
|
||||||
// eslint-disable-next-line consistent-return
|
// eslint-disable-next-line consistent-return
|
||||||
const startServer = async () => {
|
const startServer = async () => {
|
||||||
try {
|
try {
|
||||||
const macaroonExists = await FS.access(macaroonPath);
|
LightningServices.setDefaults(program);
|
||||||
const lnServices = await lnrpc(
|
await LightningServices.init();
|
||||||
defaults.lndProto,
|
|
||||||
lndHost,
|
|
||||||
lndCertPath,
|
|
||||||
macaroonExists ? macaroonPath : null
|
|
||||||
);
|
|
||||||
const { lightning } = lnServices;
|
|
||||||
const { walletUnlocker } = lnServices;
|
|
||||||
const lnServicesData = {
|
|
||||||
lndProto: defaults.lndProto,
|
|
||||||
lndHost,
|
|
||||||
lndCertPath,
|
|
||||||
macaroonPath: macaroonExists ? macaroonPath : null
|
|
||||||
};
|
|
||||||
|
|
||||||
// init lnd module =================
|
// init lnd module =================
|
||||||
const lnd = require("../services/lnd/lnd")(lightning);
|
const lnd = require("../services/lnd/lnd")(LightningServices.services.lightning);
|
||||||
|
|
||||||
const unprotectedRoutes = {
|
const unprotectedRoutes = {
|
||||||
GET: {
|
GET: {
|
||||||
|
|
@ -166,7 +146,7 @@ const server = program => {
|
||||||
logger.error(err);
|
logger.error(err);
|
||||||
res
|
res
|
||||||
.status(500)
|
.status(500)
|
||||||
.send({ status: 500, message: "internal error", type: "internal" });
|
.send({ status: 500, errorMessage: "internal error" });
|
||||||
});
|
});
|
||||||
|
|
||||||
const createServer = async () => {
|
const createServer = async () => {
|
||||||
|
|
@ -193,27 +173,18 @@ const server = program => {
|
||||||
|
|
||||||
const io = require("socket.io")(serverInstance);
|
const io = require("socket.io")(serverInstance);
|
||||||
|
|
||||||
// setup sockets =================
|
|
||||||
const lndLogfile = program.lndlogfile || defaults.lndLogFile;
|
|
||||||
|
|
||||||
const Sockets = require("./sockets")(
|
const Sockets = require("./sockets")(
|
||||||
io,
|
io,
|
||||||
lightning,
|
|
||||||
lnd,
|
lnd,
|
||||||
program.user,
|
program.user,
|
||||||
program.pwd,
|
program.pwd,
|
||||||
program.limituser,
|
program.limituser,
|
||||||
program.limitpwd,
|
program.limitpwd
|
||||||
lndLogfile,
|
|
||||||
lnServicesData
|
|
||||||
);
|
);
|
||||||
|
|
||||||
require("./routes")(
|
require("./routes")(
|
||||||
app,
|
app,
|
||||||
lightning,
|
|
||||||
defaults,
|
defaults,
|
||||||
walletUnlocker,
|
|
||||||
lnServicesData,
|
|
||||||
Sockets,
|
Sockets,
|
||||||
{
|
{
|
||||||
serverHost: module.serverHost,
|
serverHost: module.serverHost,
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
// app/sockets.js
|
// app/sockets.js
|
||||||
|
|
||||||
const logger = require("winston");
|
const logger = require("winston");
|
||||||
const FS = require("../utils/fs");
|
|
||||||
|
|
||||||
module.exports = (
|
module.exports = (
|
||||||
io,
|
io,
|
||||||
lightning,
|
|
||||||
lnd,
|
lnd,
|
||||||
login,
|
login,
|
||||||
pass,
|
pass,
|
||||||
limitlogin,
|
limitlogin,
|
||||||
limitpass,
|
limitpass
|
||||||
lndLogfile,
|
|
||||||
lnServicesData
|
|
||||||
) => {
|
) => {
|
||||||
const Mediator = require("../services/gunDB/Mediator/index.js");
|
const Mediator = require("../services/gunDB/Mediator/index.js");
|
||||||
const EventEmitter = require("events");
|
const EventEmitter = require("events");
|
||||||
|
|
@ -72,33 +68,11 @@ module.exports = (
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
io.on("connection", async socket => {
|
io.on("connection", socket => {
|
||||||
// this is where we create the websocket connection
|
// this is where we create the websocket connection
|
||||||
// with the GunDB service.
|
// with the GunDB service.
|
||||||
Mediator.createMediator(socket);
|
Mediator.createMediator(socket);
|
||||||
|
|
||||||
const macaroonExists = await (lnServicesData.macaroonPath ? FS.access(lnServicesData.macaroonPath) : false);
|
|
||||||
const lnServices = await require("../services/lnd/lightning")(
|
|
||||||
lnServicesData.lndProto,
|
|
||||||
lnServicesData.lndHost,
|
|
||||||
lnServicesData.lndCertPath,
|
|
||||||
macaroonExists ? lnServicesData.macaroonPath : null
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line prefer-destructuring, no-param-reassign
|
|
||||||
lightning = lnServices.lightning;
|
|
||||||
|
|
||||||
mySocketsEvents.addListener("updateLightning", async () => {
|
|
||||||
const newMacaroonExists = await (lnServicesData.macaroonPath ? FS.access(lnServicesData.macaroonPath) : false);
|
|
||||||
const newLNServices = await require("../services/lnd/lightning")(
|
|
||||||
lnServicesData.lndProto,
|
|
||||||
lnServicesData.lndHost,
|
|
||||||
lnServicesData.lndCertPath,
|
|
||||||
newMacaroonExists ? lnServicesData.macaroonPath : null
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line prefer-destructuring, no-param-reassign
|
|
||||||
lightning = newLNServices.lightning;
|
|
||||||
});
|
|
||||||
|
|
||||||
logger.debug("socket.handshake", socket.handshake);
|
logger.debug("socket.handshake", socket.handshake);
|
||||||
|
|
||||||
if (authEnabled) {
|
if (authEnabled) {
|
||||||
|
|
|
||||||
61
utils/lightningServices.js
Normal file
61
utils/lightningServices.js
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
const FS = require("../utils/fs");
|
||||||
|
const lnrpc = require("../services/lnd/lightning");
|
||||||
|
|
||||||
|
class LightningServices {
|
||||||
|
setDefaults = program => {
|
||||||
|
const defaults = require("../config/defaults")(program.mainnet);
|
||||||
|
|
||||||
|
this.defaults = defaults;
|
||||||
|
this.config = {
|
||||||
|
useTLS: program.usetls,
|
||||||
|
serverPort: program.serverport || defaults.serverPort,
|
||||||
|
serverHost: program.serverhost || defaults.serverHost,
|
||||||
|
lndHost: program.lndhost || defaults.lndHost,
|
||||||
|
lndCertPath: program.lndCertPath || defaults.lndCertPath,
|
||||||
|
macaroonPath: program.macaroonPath || defaults.macaroonPath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
isInitialized = () => {
|
||||||
|
return !!(this.lightning && this.walletUnlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
get services() {
|
||||||
|
return {
|
||||||
|
lightning: this.lightning,
|
||||||
|
walletUnlocker: this.walletUnlocker,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get servicesData() {
|
||||||
|
return this.lnServicesData;
|
||||||
|
}
|
||||||
|
|
||||||
|
get servicesConfig() {
|
||||||
|
return this.config;
|
||||||
|
}
|
||||||
|
|
||||||
|
init = async () => {
|
||||||
|
const { macaroonPath, lndHost, lndCertPath } = this.config;
|
||||||
|
const macaroonExists = await FS.access(macaroonPath);
|
||||||
|
const lnServices = await lnrpc(
|
||||||
|
this.defaults.lndProto,
|
||||||
|
lndHost,
|
||||||
|
lndCertPath,
|
||||||
|
macaroonExists ? macaroonPath : null
|
||||||
|
);
|
||||||
|
const { lightning, walletUnlocker } = lnServices;
|
||||||
|
this.lightning = lightning;
|
||||||
|
this.walletUnlocker = walletUnlocker
|
||||||
|
this.lnServicesData = {
|
||||||
|
lndProto: this.defaults.lndProto,
|
||||||
|
lndHost,
|
||||||
|
lndCertPath,
|
||||||
|
macaroonPath: macaroonExists ? macaroonPath : null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const lightningServices = new LightningServices();
|
||||||
|
|
||||||
|
module.exports = lightningServices;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue