Browse Source

feat(lnd): add tls and macaroon paths to the LNDNode interface

feat/auto-update
jamaljsr 5 years ago
parent
commit
9a6555a6d0
  1. 24
      electron/lnd/lndProxy.ts
  2. 2
      electron/types.ts
  3. 2
      src/lib/docker/nodeTemplates.ts
  4. 19
      src/lib/lnd/lndService.ts
  5. 21
      src/store/models/bitcoind.ts
  6. 40
      src/store/models/network.ts
  7. 2
      src/types/index.ts
  8. 65
      src/utils/network.ts
  9. 58
      src/utils/tests.tsx

24
electron/lnd/lndProxy.ts

@ -1,20 +1,32 @@
import { IpcMain } from 'electron';
import { debug } from 'electron-log';
import createLndRpc, { LnRpc, LnRpcClientConfig } from '@radar/lnrpc';
import createLndRpc, { LnRpc } from '@radar/lnrpc';
import { LNDNode } from '../types';
// mapping of name <-> node to talk to multiple nodes
const nodes: {
[key: string]: LnRpc;
} = {};
const connect = async (args: {
node: LNDNode;
config: LnRpcClientConfig;
}): Promise<any> => {
nodes[args.node.name] = await createLndRpc(args.config);
/**
* Stores the connection info of a LND node to use for future commands
* @param args the LNDNode to connect to
*/
const connect = async (args: { node: LNDNode }): Promise<any> => {
const { ports, tlsPath, macaroonPath } = args.node;
const config = {
server: `127.0.0.1:${ports.grpc}`,
tls: tlsPath,
macaroonPath: macaroonPath,
};
nodes[args.node.name] = await createLndRpc(config);
return { success: true };
};
/**
* Calls the LND `getinfo` RPC command
* @param args the name of the LND node
*/
const getInfo = async (args: { name: string }): Promise<any> => {
return await nodes[args.name].getInfo();
};

2
electron/types.ts

@ -21,6 +21,8 @@ export interface LightningNode extends CommonNode {
}
export interface LNDNode extends LightningNode {
tlsPath: string;
macaroonPath: string;
ports: {
rest: number;
grpc: number;

2
src/lib/docker/nodeTemplates.ts

@ -27,7 +27,7 @@ export const bitcoind = (
-rpcallowip=0.0.0.0/0
-rpcport=18443
`),
volumes: [`./volumes/${name}:/home/bitcoin/.bitcoin`],
volumes: [`./volumes/bitcoind/${name}:/home/bitcoin/.bitcoin`],
expose: [
'18443', // RPC
'18444', // p2p

19
src/lib/lnd/lndService.ts

@ -1,7 +1,5 @@
import { join } from 'path';
import { createIpcSender, IcpSender } from 'lib/ipc/ipcService';
import { LndLibrary, LNDNode } from 'types';
import { dataPath } from 'utils/config';
class LndService implements LndLibrary {
ipc: IcpSender;
@ -11,22 +9,7 @@ class LndService implements LndLibrary {
}
async connect(node: LNDNode): Promise<void> {
// const macAppPath = join('/', 'Users', 'jamal', 'Library', 'Application Support');
// const dataPath = join(process.env['APPDATA'] || macAppPath, 'polar', 'data');
const adminMacaroonPath = join(
'data',
'chain',
'bitcoin',
'regtest',
'admin.macaroon',
);
const nodePath = join(dataPath, 'networks', '1', 'volumes', 'lnd', node.name);
const config = {
server: `127.0.0.1:${node.ports.grpc}`,
tls: join(nodePath, 'tls.cert'),
macaroonPath: join(nodePath, adminMacaroonPath),
};
await this.ipc('connect', { node, config });
await this.ipc('connect', { node });
}
async getInfo(node: LNDNode): Promise<void> {

21
src/store/models/bitcoind.ts

@ -1,6 +1,7 @@
import { ChainInfo, WalletInfo } from 'bitcoin-core';
import { Action, action, Thunk, thunk } from 'easy-peasy';
import { BitcoinNode, LNDNode, Status, StoreInjections } from 'types';
import { BitcoinNode, StoreInjections } from 'types';
import { createNetwork } from 'utils/network';
export interface BitcoindModel {
chainInfo: ChainInfo | undefined;
@ -26,19 +27,13 @@ const bitcoindModel: BitcoindModel = {
);
actions.setWalletinfo(await injections.bitcoindService.getWalletInfo(node.ports.rpc));
const lnd: LNDNode = {
const lnd = createNetwork({
id: 1,
name: 'polar-n1-lnd-1',
type: 'lightning',
implementation: 'LND',
version: '0.7.1-beta',
status: Status.Stopped,
backendName: 'bitcoind1',
ports: {
rest: 8081,
grpc: 10001,
},
};
name: 'my-test',
lndNodes: 2,
bitcoindNodes: 1,
}).nodes.lightning[0];
await injections.lndService.connect(lnd);
await injections.lndService.getInfo(lnd);
}),

40
src/store/models/network.ts

@ -1,11 +1,9 @@
import { info } from 'electron-log';
import { join } from 'path';
import { IChart } from '@mrblenny/react-flow-chart';
import { push } from 'connected-react-router';
import { Action, action, Computed, computed, Thunk, thunk } from 'easy-peasy';
import { Network, Status, StoreInjections } from 'types';
import { networksPath } from 'utils/config';
import { range } from 'utils/numbers';
import { createNetwork } from 'utils/network';
import { NETWORK_VIEW } from 'components/routing';
interface AddNetworkArgs {
@ -62,41 +60,7 @@ const networkModel: NetworkModel = {
}),
add: action((state, { name, lndNodes, bitcoindNodes }) => {
const nextId = Math.max(0, ...state.networks.map(n => n.id)) + 1;
const network: Network = {
id: nextId,
name,
status: Status.Stopped,
path: join(networksPath, nextId.toString()),
nodes: {
bitcoin: [],
lightning: [],
},
};
network.nodes.bitcoin = range(bitcoindNodes).map((v, i) => ({
id: i,
name: `bitcoind-${i + 1}`,
type: 'bitcoin',
implementation: 'bitcoind',
version: '0.18.1',
status: Status.Stopped,
ports: { rpc: 18443 },
}));
network.nodes.lightning = range(lndNodes).map((v, i) => ({
id: i,
name: `lnd-${i + 1}`,
type: 'lightning',
implementation: 'LND',
version: '0.7.1-beta',
status: Status.Stopped,
backendName: network.nodes.bitcoin[0].name,
ports: {
rest: 8081 + i,
grpc: 10001 + i,
},
}));
const network = createNetwork({ id: nextId, name, lndNodes, bitcoindNodes });
state.networks.push(network);
info(`Added new network '${network.name}' to redux state`);
}),

2
src/types/index.ts

@ -39,6 +39,8 @@ export interface LightningNode extends CommonNode {
}
export interface LNDNode extends LightningNode {
tlsPath: string;
macaroonPath: string;
ports: {
rest: number;
grpc: number;

65
src/utils/network.ts

@ -0,0 +1,65 @@
import { join } from 'path';
import { BitcoinNode, LNDNode, Network, Status } from 'types';
import { networksPath } from './config';
import { range } from './numbers';
export const createNetwork = (config: {
id: number;
name: string;
lndNodes: number;
bitcoindNodes: number;
status?: Status;
}): Network => {
const { id, name, lndNodes, bitcoindNodes } = config;
// need explicit undefined check because Status.Starting is 0
const status = config.status !== undefined ? config.status : Status.Stopped;
const network: Network = {
id: id,
name,
status,
path: join(networksPath, id.toString()),
nodes: {
bitcoin: [],
lightning: [],
},
};
network.nodes.bitcoin = range(bitcoindNodes).map<BitcoinNode>((v, i) => ({
id: i,
name: `bitcoind-${i + 1}`,
type: 'bitcoin',
implementation: 'bitcoind',
version: '0.18.1',
status,
ports: { rpc: 18443 },
}));
// long path games
const prefix = (name: string) => `polar-n${network.id}-${name}`;
const lndDataPath = (name: string) =>
join(network.path, 'volumes', 'lnd', prefix(name));
const lndCertPath = (name: string) => join(lndDataPath(name), 'tls.cert');
const macaroonPath = join('data', 'chain', 'bitcoin', 'regtest', 'admin.macaroon');
const lndMacaroonPath = (name: string) => join(lndDataPath(name), macaroonPath);
network.nodes.lightning = range(lndNodes)
.map((v, i) => `lnd-${i + 1}`)
.map<LNDNode>((name, i) => ({
id: i,
name: name,
type: 'lightning',
implementation: 'LND',
version: '0.7.1-beta',
status,
backendName: network.nodes.bitcoin[0].name,
tlsPath: lndCertPath(name),
macaroonPath: lndMacaroonPath(name),
ports: {
rest: 8081 + i,
grpc: 10001 + i,
},
}));
return network;
};

58
src/utils/tests.tsx

@ -1,61 +1,21 @@
import React from 'react';
import { Provider } from 'react-redux';
import { join } from 'path';
import { render } from '@testing-library/react';
import { ConnectedRouter } from 'connected-react-router';
import { StoreProvider } from 'easy-peasy';
import { createMemoryHistory } from 'history';
import { createReduxStore } from 'store';
import { Network, Status, StoreInjections } from 'types';
import { dataPath } from './config';
import { createNetwork } from './network';
export const getNetwork = (networkId = 1, name?: string, status?: Status): Network => ({
id: networkId,
name: name || 'my-test',
status: status !== undefined ? status : Status.Stopped,
path: join(dataPath, 'networks', networkId.toString()),
nodes: {
bitcoin: [
{
id: 1,
name: 'bitcoind-1',
type: 'bitcoin',
implementation: 'bitcoind',
version: '0.18.1',
status: status !== undefined ? status : Status.Stopped,
ports: { rpc: 18443 },
},
],
lightning: [
{
id: 1,
name: 'lnd-1',
type: 'lightning',
implementation: 'LND',
version: '0.7.1-beta',
status: status !== undefined ? status : Status.Stopped,
backendName: 'bitcoind1',
ports: {
rest: 8081,
grpc: 10001,
},
},
{
id: 2,
name: 'lnd-2',
type: 'lightning',
implementation: 'LND',
version: '0.7.1-beta',
status: status !== undefined ? status : Status.Stopped,
backendName: 'bitcoind1',
ports: {
rest: 8082,
grpc: 10002,
},
},
],
},
});
export const getNetwork = (networkId = 1, name?: string, status?: Status): Network =>
createNetwork({
id: networkId,
name: name || 'my-test',
lndNodes: 2,
bitcoindNodes: 1,
status,
});
// injections allow you to mock the dependencies of redux store actions
export const injections: StoreInjections = {

Loading…
Cancel
Save