Browse Source

node alias endpoint

master
Mayank 5 years ago
parent
commit
ffc2ff771c
  1. 93
      logic/lightning.js
  2. 4
      package.json
  3. 15
      routes/v1/lnd/info.js
  4. 10
      services/lnd.js

93
logic/lightning.js

@ -57,7 +57,7 @@ const OUTPUT_IS_DUST_ERROR = {
function toHexString(byteObject) { function toHexString(byteObject) {
const bytes = Object.values(byteObject); const bytes = Object.values(byteObject);
return bytes.map(function(byte) { return bytes.map(function (byte) {
return ('00' + (byte & 0xFF).toString(16)).slice(-2); // eslint-disable-line no-magic-numbers return ('00' + (byte & 0xFF).toString(16)).slice(-2); // eslint-disable-line no-magic-numbers
}).join(''); }).join('');
@ -72,18 +72,18 @@ async function addInvoice(amt, memo) {
} }
// Creates a new managed channel. // Creates a new managed channel.
async function addManagedChannel(channelPoint, name, purpose) { // async function addManagedChannel(channelPoint, name, purpose) {
const managedChannels = await getManagedChannels(); // const managedChannels = await getManagedChannels();
// Create a new managed channel. If one exists, it will be rewritten. // // Create a new managed channel. If one exists, it will be rewritten.
// However, Lnd should guarantee chanId is always unique. // // However, Lnd should guarantee chanId is always unique.
managedChannels[channelPoint] = { // managedChannels[channelPoint] = {
name: name, // eslint-disable-line object-shorthand // name: name, // eslint-disable-line object-shorthand
purpose: purpose, // eslint-disable-line object-shorthand // purpose: purpose, // eslint-disable-line object-shorthand
}; // };
await setManagedChannels(managedChannels); // await setManagedChannels(managedChannels);
} // }
// Change your lnd password. Wallet must exist and be unlocked. // Change your lnd password. Wallet must exist and be unlocked.
async function changePassword(currentPassword, newPassword) { async function changePassword(currentPassword, newPassword) {
@ -189,9 +189,9 @@ async function estimateFeeSweep(address, fullAmtToEstimate, mempoolMinFee, confT
async function estimateFeeGroupSweep(address, amt, mempoolMinFee) { async function estimateFeeGroupSweep(address, amt, mempoolMinFee) {
const calls = [estimateFeeSweep(address, amt, mempoolMinFee, FAST_BLOCK_CONF_TARGET, 0, amt), const calls = [estimateFeeSweep(address, amt, mempoolMinFee, FAST_BLOCK_CONF_TARGET, 0, amt),
estimateFeeSweep(address, amt, mempoolMinFee, NORMAL_BLOCK_CONF_TARGET, 0, amt), estimateFeeSweep(address, amt, mempoolMinFee, NORMAL_BLOCK_CONF_TARGET, 0, amt),
estimateFeeSweep(address, amt, mempoolMinFee, SLOW_BLOCK_CONF_TARGET, 0, amt), estimateFeeSweep(address, amt, mempoolMinFee, SLOW_BLOCK_CONF_TARGET, 0, amt),
estimateFeeSweep(address, amt, mempoolMinFee, CHEAPEST_BLOCK_CONF_TARGET, 0, amt), estimateFeeSweep(address, amt, mempoolMinFee, CHEAPEST_BLOCK_CONF_TARGET, 0, amt),
]; ];
const [fast, normal, slow, cheapest] const [fast, normal, slow, cheapest]
@ -217,9 +217,9 @@ async function estimateFeeWrapper(address, amt, mempoolMinFee, confTarget) {
async function estimateFeeGroup(address, amt, mempoolMinFee) { async function estimateFeeGroup(address, amt, mempoolMinFee) {
const calls = [estimateFeeWrapper(address, amt, mempoolMinFee, FAST_BLOCK_CONF_TARGET), const calls = [estimateFeeWrapper(address, amt, mempoolMinFee, FAST_BLOCK_CONF_TARGET),
estimateFeeWrapper(address, amt, mempoolMinFee, NORMAL_BLOCK_CONF_TARGET), estimateFeeWrapper(address, amt, mempoolMinFee, NORMAL_BLOCK_CONF_TARGET),
estimateFeeWrapper(address, amt, mempoolMinFee, SLOW_BLOCK_CONF_TARGET), estimateFeeWrapper(address, amt, mempoolMinFee, SLOW_BLOCK_CONF_TARGET),
estimateFeeWrapper(address, amt, mempoolMinFee, CHEAPEST_BLOCK_CONF_TARGET), estimateFeeWrapper(address, amt, mempoolMinFee, CHEAPEST_BLOCK_CONF_TARGET),
]; ];
const [fast, normal, slow, cheapest] const [fast, normal, slow, cheapest]
@ -259,7 +259,7 @@ async function generateSeed() {
if (lndStatus.operational) { if (lndStatus.operational) {
const response = await lndService.generateSeed(); const response = await lndService.generateSeed();
return {seed: response.cipherSeedMnemonic}; return { seed: response.cipherSeedMnemonic };
} }
throw new LndError('Lnd is not operational, therefore a seed cannot be created.'); throw new LndError('Lnd is not operational, therefore a seed cannot be created.');
@ -273,7 +273,7 @@ function getChannelBalance() {
// Returns a count of all open channels. // Returns a count of all open channels.
function getChannelCount() { function getChannelCount() {
return lndService.getOpenChannels() return lndService.getOpenChannels()
.then(response => ({count: response.length})); .then(response => ({ count: response.length }));
} }
function getChannelPolicy() { function getChannelPolicy() {
@ -299,9 +299,9 @@ async function getInvoices() {
// Return all managed channels. Managed channels are channels the user has manually created. // Return all managed channels. Managed channels are channels the user has manually created.
// TODO: how to handle if file becomes corrupt? Suggest simply wiping the file. The channel will still exist. // TODO: how to handle if file becomes corrupt? Suggest simply wiping the file. The channel will still exist.
function getManagedChannels() { // function getManagedChannels() {
return diskLogic.readManagedChannelsFile(); // return diskLogic.readManagedChannelsFile();
} // }
// Returns a list of all on chain transactions. // Returns a list of all on chain transactions.
async function getOnChainTransactions() { async function getOnChainTransactions() {
@ -362,9 +362,9 @@ async function getOnChainTransactions() {
} else if (transaction.amount > 0 && transaction.destAddresses.length > 0) { } else if (transaction.amount > 0 && transaction.destAddresses.length > 0) {
transaction.type = 'ON_CHAIN_TRANSACTION_RECEIVED'; transaction.type = 'ON_CHAIN_TRANSACTION_RECEIVED';
// Positive amounts are either incoming transactions or a WaitingCloseChannel. There is no way to determine which // Positive amounts are either incoming transactions or a WaitingCloseChannel. There is no way to determine which
// until the transaction has at least one confirmation. Then a WaitingCloseChannel will become a pending Closing // until the transaction has at least one confirmation. Then a WaitingCloseChannel will become a pending Closing
// channel and will have an associated tx id. // channel and will have an associated tx id.
} else if (transaction.amount > 0 && transaction.destAddresses.length === 0) { } else if (transaction.amount > 0 && transaction.destAddresses.length === 0) {
transaction.type = 'PENDING_CLOSE'; transaction.type = 'PENDING_CLOSE';
} else { } else {
@ -382,8 +382,8 @@ function getTxnHashFromChannelPoint(channelPoint) {
} }
// Returns a list of all open channels. // Returns a list of all open channels.
const getChannels = async() => { const getChannels = async () => {
const managedChannelsCall = getManagedChannels(); // const managedChannelsCall = getManagedChannels();
const openChannelsCall = lndService.getOpenChannels(); const openChannelsCall = lndService.getOpenChannels();
const pendingChannels = await lndService.getPendingChannels(); const pendingChannels = await lndService.getPendingChannels();
@ -456,7 +456,7 @@ const getChannels = async() => {
// Add additional managed channel data if it exists // Add additional managed channel data if it exists
// Call this async, because it reads from disk // Call this async, because it reads from disk
const managedChannels = await managedChannelsCall; // const managedChannels = await managedChannelsCall;
if (chainTxnCall !== null) { if (chainTxnCall !== null) {
const chainTxnList = await chainTxnCall; const chainTxnList = await chainTxnCall;
@ -511,15 +511,15 @@ const getChannels = async() => {
} }
// If a managed channel exists, set the name and purpose // If a managed channel exists, set the name and purpose
if (Object.prototype.hasOwnProperty.call(managedChannels, channel.channelPoint)) { // if (Object.prototype.hasOwnProperty.call(managedChannels, channel.channelPoint)) {
channel.managed = true; // channel.managed = true;
channel.name = managedChannels[channel.channelPoint].name; // channel.name = managedChannels[channel.channelPoint].name;
channel.purpose = managedChannels[channel.channelPoint].purpose; // channel.purpose = managedChannels[channel.channelPoint].purpose;
} else { // } else {
channel.managed = false; // channel.managed = false;
channel.name = ''; // channel.name = '';
channel.purpose = ''; // channel.purpose = '';
} // }
} }
return allChannels; return allChannels;
@ -660,7 +660,9 @@ async function openChannel(pubKey, ip, port, amt, satPerByte, name, purpose) { /
// Lnd only allows one channel to be created with a node per block. By searching pending open channels, we can find // Lnd only allows one channel to be created with a node per block. By searching pending open channels, we can find
// a unique identifier for the newly created channe. We will use ChannelPoint. // a unique identifier for the newly created channe. We will use ChannelPoint.
const pendingChannel = await getPendingChannelDetails(PENDING_OPEN_CHANNELS, pubKey); const pendingChannel = await getPendingChannelDetails(PENDING_OPEN_CHANNELS, pubKey);
await addManagedChannel(pendingChannel.channelPoint, name, purpose);
//No need for disk logic for now
// await addManagedChannel(pendingChannel.channelPoint, name, purpose);
return channel; return channel;
} }
@ -711,9 +713,9 @@ function sendCoins(addr, amt, satPerByte, sendAll) {
// Sets the managed channel data store. // Sets the managed channel data store.
// TODO: How to prevent this from getting out of data with multiple calling threads? // TODO: How to prevent this from getting out of data with multiple calling threads?
// perhaps create a mutex for reading and writing? // perhaps create a mutex for reading and writing?
function setManagedChannels(managedChannelsObject) { // function setManagedChannels(managedChannelsObject) {
return diskLogic.writeManagedChannelsFile(managedChannelsObject); // return diskLogic.writeManagedChannelsFile(managedChannelsObject);
} // }
// Returns if lnd is operation and if the wallet is unlocked. // Returns if lnd is operation and if the wallet is unlocked.
async function getStatus() { async function getStatus() {
@ -804,7 +806,13 @@ async function getVersion() {
// Remove all beta/commit info. Fragile, LND may one day GA. // Remove all beta/commit info. Fragile, LND may one day GA.
const version = unformattedVersion.split('-', 1)[0]; const version = unformattedVersion.split('-', 1)[0];
return {version: version}; // eslint-disable-line object-shorthand return { version: version }; // eslint-disable-line object-shorthand
}
async function getNodeAlias(pubkey) {
const includeChannels = false;
const nodeInfo = await lndService.getNodeInfo(pubkey, includeChannels);
return { alias: nodeInfo.node.alias }; // eslint-disable-line object-shorthand
} }
function updateChannelPolicy(global, fundingTxid, outputIndex, baseFeeMsat, feeRate, timeLockDelta) { function updateChannelPolicy(global, fundingTxid, outputIndex, baseFeeMsat, feeRate, timeLockDelta) {
@ -820,6 +828,7 @@ module.exports = {
estimateFee, estimateFee,
generateAddress, generateAddress,
generateSeed, generateSeed,
getNodeAlias,
getChannelBalance, getChannelBalance,
getChannelPolicy, getChannelPolicy,
getChannelCount, getChannelCount,

4
package.json

@ -1,6 +1,6 @@
{ {
"name": "umbrel-middleware", "name": "umbrel-middleware",
"version": "0.0.2", "version": "0.0.3",
"description": "Middleware for Umbrel Node", "description": "Middleware for Umbrel Node",
"author": "Umbrel", "author": "Umbrel",
"scripts": { "scripts": {
@ -54,4 +54,4 @@
], ],
"cache": "false" "cache": "false"
} }
} }

15
routes/v1/lnd/info.js

@ -4,6 +4,7 @@ const router = express.Router();
const auth = require('middlewares/auth.js'); const auth = require('middlewares/auth.js');
const lightning = require('logic/lightning.js'); const lightning = require('logic/lightning.js');
const safeHandler = require('utils/safeHandler'); const safeHandler = require('utils/safeHandler');
const validator = require('utils/validator.js');
router.get('/uris', auth.jwt, safeHandler((req, res) => router.get('/uris', auth.jwt, safeHandler((req, res) =>
lightning.getPublicUris() lightning.getPublicUris()
@ -25,4 +26,18 @@ router.get('/version', auth.jwt, safeHandler((req, res) =>
.then(version => res.json(version)) .then(version => res.json(version))
)); ));
router.get('/alias', auth.jwt, safeHandler((req, res, next) => {
const pubkey = req.query.pubkey;
try {
validator.isAlphanumeric(pubkey);
} catch (error) {
return next(error);
}
return lightning.getNodeAlias(pubkey)
.then(alias => res.json(alias));
}));
module.exports = router; module.exports = router;

10
services/lnd.js

@ -230,6 +230,15 @@ function getInfo() {
.then(({ lightning }) => promiseify(lightning, lightning.GetInfo, {}, 'get lnd information')); .then(({ lightning }) => promiseify(lightning, lightning.GetInfo, {}, 'get lnd information'));
} }
function getNodeInfo(pubkey, includeChannels) {
const rpcPayload = {
pub_key: pubkey,
include_channels: includeChannels
};
return initializeRPCClient()
.then(({ lightning }) => promiseify(lightning, lightning.GetNodeInfo, rpcPayload, 'get node information'));
}
// Returns a list of lnd's currently open channels. Channels are considered open by this node and it's directly // Returns a list of lnd's currently open channels. Channels are considered open by this node and it's directly
// connected peer after three confirmation. After six confirmations, the channel is broadcasted by this node and it's // connected peer after three confirmation. After six confirmations, the channel is broadcasted by this node and it's
// directly connected peer to the broader lightning network. // directly connected peer to the broader lightning network.
@ -422,6 +431,7 @@ module.exports = {
getFeeReport, getFeeReport,
getForwardingEvents, getForwardingEvents,
getInfo, getInfo,
getNodeInfo,
getInvoices, getInvoices,
getOpenChannels, getOpenChannels,
getPayments, getPayments,

Loading…
Cancel
Save