UNPKG

leap-node

Version:

[![codecov](https://codecov.io/gh/leapdao/leap-node/branch/master/graph/badge.svg)](https://codecov.io/gh/leapdao/leap-node) [![Docker Repository on Quay](https://quay.io/repository/leapdao/leap-node/status "Docker Repository on Quay")](https://quay.io/re

202 lines (183 loc) 5.78 kB
const getPort = require('get-port'); const fs = require('fs-extra'); const axios = require('axios'); const { join } = require('path'); const ABCIServer = require('./lib/abci-app.js'); const Tendermint = require('./lib/tendermint.js'); const rimraf = require('rimraf'); const generateNetworkId = require('./lib/network-id.js'); const os = require('os'); const { EventEmitter } = require('events'); const LOTION_HOME = process.env.LOTION_HOME || join(os.homedir(), '.lotion'); async function getPorts(peeringPort, rpcPort, abciAppPort) { const p2pPort = process.env.P2P_PORT || peeringPort || (await getPort(peeringPort)); const tendermintPort = process.env.TENDERMINT_PORT || rpcPort || (await getPort(rpcPort)); const abciPort = process.env.ABCI_PORT || abciAppPort || (await getPort()); return { tendermintPort, abciPort, p2pPort }; } function getGenesis(genesisPath) { return fs.readFileSync(genesisPath, { encoding: 'utf8' }); } function Lotion(opts = {}) { const peers = opts.peers || []; const logTendermint = opts.logTendermint || false; const createEmptyBlocks = typeof opts.createEmptyBlocks === 'undefined' ? true : opts.createEmptyBlocks; const devMode = opts.devMode || false; const { unsafeRpc } = opts; const txMiddleware = []; const queryMiddleware = []; const blockMiddleware = []; const periodMiddleware = []; const initChainMiddleware = []; const postListenMiddleware = []; const keys = typeof opts.keys === 'string' ? JSON.parse(fs.readFileSync(opts.keys, { encoding: 'utf8' })) : opts.keys; const genesis = typeof opts.genesis === 'string' ? JSON.parse(getGenesis(opts.genesis)) : opts.genesis; const bus = new EventEmitter(); let appInfo; let abciServer; let tendermint; let lotionPath; const networkId = opts.networkId || generateNetworkId( txMiddleware, blockMiddleware, queryMiddleware, devMode, genesis ); lotionPath = opts.dataPath || join(LOTION_HOME, 'networks', networkId); if (devMode) { lotionPath += Math.floor(Math.random() * 1e9); rimraf.sync(lotionPath); process.on('SIGINT', () => { rimraf.sync(lotionPath); process.exit(); }); } fs.mkdirpSync(lotionPath); bus.on('listen', () => { postListenMiddleware.forEach(f => { f(appInfo); }); }); const appMethods = { use: middleware => { if (middleware instanceof Array) { middleware.forEach(appMethods.use); } else if (typeof middleware === 'function') { appMethods.useTx(middleware); } else if (middleware.type === 'tx') { appMethods.useTx(middleware.middleware); } else if (middleware.type === 'query') { appMethods.useQuery(middleware.middleware); } else if (middleware.type === 'block') { appMethods.useBlock(middleware.middleware); } else if (middleware.type === 'period') { appMethods.usePeriod(middleware.middleware); } else if (middleware.type === 'initChain') { appMethods.useInitChain(middleware.middleware); } else if (middleware.type === 'post-listen') { appMethods.usePostListen(middleware.middleware); } return appMethods; }, useTx: txHandler => { txMiddleware.push(txHandler); }, useBlock: blockHandler => { blockMiddleware.push(blockHandler); }, usePeriod: periodHandler => { periodMiddleware.push(periodHandler); }, useInitChain: initChainHandler => { initChainMiddleware.push(initChainHandler); }, useQuery: queryHandler => { queryMiddleware.push(queryHandler); }, usePostListen: postListener => { // TODO: rename "post listen", there's probably a more descriptive name. postListenMiddleware.push(postListener); }, listen: store => { return new Promise(async resolve => { // set up abci server, then tendermint node const { tendermintPort, abciPort, p2pPort } = await getPorts( opts.p2pPort, opts.tendermintPort, opts.abciPort ); const { tendermintAddr } = opts; abciServer = ABCIServer({ txMiddleware, blockMiddleware, queryMiddleware, store, periodMiddleware, initChainMiddleware, genesis, }); abciServer.listen(abciPort, 'localhost'); try { tendermint = await Tendermint({ lotionPath, tendermintAddr, tendermintPort, abciPort, p2pPort, logTendermint, createEmptyBlocks, networkId, peers, genesis, keys, unsafeRpc, }); } catch (e) { console.log('error starting tendermint node:'); console.log(e); // exit here, it makes no sense to keep running without tendermint process.exit(1); } await tendermint.synced; appInfo = { tendermintPort, abciPort, p2pPort, lotionPath, genesisPath: join(lotionPath, 'config', 'genesis.json'), }; bus.emit('listen'); resolve(appInfo); }); }, close: () => { abciServer.close(); tendermint.close(); }, info: () => appInfo, lotionPath: () => lotionPath, status: async () => { const { tendermintPort } = await getPorts(undefined, opts.tendermintPort); const tendermintRpcUrl = `http://localhost:${tendermintPort}`; return axios .get(`${tendermintRpcUrl}/status`) .then(rsp => rsp.data.result); }, }; return appMethods; } module.exports = Lotion;