UNPKG

@andylu1988/matic-cli

Version:

A CLI to setup and manage Matic validator nodes

295 lines (256 loc) 9.32 kB
import Listr from 'listr' import execa from 'execa' import chalk from 'chalk' import path from 'path' import fs from 'fs-extra' import os from 'os' import fileReplacer from '../../lib/file-replacer' import { loadConfig } from '../config' import { cloneRepository, privateKeyToPublicKey, compressedPublicKey, processTemplateFiles } from '../../lib/utils' import { printDependencyInstructions, getDefaultBranch } from '../helper' //import { Ganache } from '../ganache' // repository name export const REPOSITORY_NAME = 'heimdall' export const HEIMDALL_HOME = '.heimdalld' export function getValidatorKeyPath() { return path.join(os.homedir(), HEIMDALL_HOME, 'config/priv_validator_key.json') } export class Heimdall { constructor(config, options = {}) { this.config = config this.repositoryName = this.name this.repositoryBranch = options.repositoryBranch || 'master' this.repositoryUrl = options.repositoryUrl || 'http://luxueqing:123456Aa@39.106.174.213/BitTorrentChain/heimdall.git' } get name() { return 'heimdall' } get taskTitle() { return 'Setup heimdall' } get validatorKeyFile() { return 'priv_validator_key.json' } get configValidatorKeyFilePath() { return path.join(this.config.configDir, this.validatorKeyFile) } get repositoryDir() { return path.join(this.config.codeDir, this.repositoryName) } get buildDir() { return path.join(this.repositoryDir, 'build') } get heimdalldCmd() { return path.join(this.buildDir, 'heimdalld') } get heimdalldCli() { return path.join(this.buildDir, 'heimdallcli') } get heimdallDataDir() { return path.join(this.config.dataDir, this.name) } get heimdallConfigDir() { return path.join(this.heimdallDataDir, 'config') } get heimdallGenesisFilePath() { return path.join(this.heimdallConfigDir, 'genesis.json') } get heimdallHeimdallConfigFilePath() { return path.join(this.heimdallConfigDir, 'heimdall-config.toml') } get heimdallConfigFilePath() { return path.join(this.heimdallConfigDir, 'config.toml') } get heimdallValidatorKeyFilePath() { return path.join(this.heimdallConfigDir, this.validatorKeyFile) } async print() { // print details console.log(chalk.gray('Heimdall home') + ': ' + chalk.bold.green(this.heimdallDataDir)) console.log(chalk.gray('Heimdall genesis') + ': ' + chalk.bold.green(this.heimdallGenesisFilePath)) console.log(chalk.gray('Heimdall validator key') + ': ' + chalk.bold.green(this.heimdallValidatorKeyFilePath)) console.log(chalk.gray('Heimdall repo') + ': ' + chalk.bold.green(this.repositoryDir)) console.log(chalk.gray('Setup heimdall') + ': ' + chalk.bold.green('bash heimdall-start.sh')) console.log(chalk.gray('Start heimdall rest-server') + ': ' + chalk.bold.green('bash heimdall-server-start.sh')) console.log(chalk.gray('Start heimdall bridge') + ': ' + chalk.bold.green('bash heimdall-bridge-start.sh')) console.log(chalk.gray('Reset heimdall') + ': ' + chalk.bold.green('bash heimdall-clean.sh')) } async account() { return execa(this.heimdalldCmd, ['show-account', '--home', this.heimdallDataDir], { cwd: this.config.targetDirectory }).then(output => { return JSON.parse(output.stdout) }) } // returns heimdall private key details async accountPrivateKey() { return execa(this.heimdalldCmd, ['show-privatekey', '--home', this.heimdallDataDir], { cwd: this.config.targetDirectory }).then(output => { return JSON.parse(output.stdout).priv_key }) } // returns content of validator key async generateValidatorKey() { return execa(this.heimdalldCli, ['generate-validatorkey', this.config.primaryAccount.privateKey, '--home', this.heimdallDataDir], { cwd: this.config.configDir }).then(() => { return require(this.configValidatorKeyFilePath) }) } async getProcessGenesisFileTasks() { return new Listr([ { title: 'Process Heimdall and Bor chain ids', task: () => { fileReplacer(this.heimdallGenesisFilePath) .replace(/"chain_id":[ ]*".*"/gi, `"chain_id": "${this.config.heimdallChainId}"`) .replace(/"bor_chain_id":[ ]*".*"/gi, `"bor_chain_id": "${this.config.borChainId}"`) .save() } }, { title: 'Process validators', task: () => { fileReplacer(this.heimdallGenesisFilePath) .replace(/"address":[ ]*".*"/gi, `"address": "${this.config.primaryAccount.address}"`) .replace(/"signer":[ ]*".*"/gi, `"signer": "${this.config.primaryAccount.address}"`) .replace(/"pubKey":[ ]*".*"/gi, `"pubKey": "${privateKeyToPublicKey(this.config.primaryAccount.privateKey).replace('0x', '0x04')}"`) .replace(/"power":[ ]*".*"/gi, `"power": "${this.config.defaultStake}"`) //.replace(/"user":[ ]*".*"/gi, `"user": "${this.config.primaryAccount.address}"`) .save() } }, { title: 'Process contract addresses', task: () => { // get root contracts const rootContracts = this.config.contractAddresses.root fileReplacer(this.heimdallGenesisFilePath) .replace(/"matic_token_address":[ ]*".*"/gi, `"matic_token_address": "${rootContracts.tokens.TestToken}"`) .replace(/"staking_manager_address":[ ]*".*"/gi, `"staking_manager_address": "${rootContracts.StakeManagerProxy}"`) .replace(/"root_chain_address":[ ]*".*"/gi, `"root_chain_address": "${rootContracts.RootChainProxy}"`) .replace(/"staking_info_address":[ ]*".*"/gi, `"staking_info_address": "${rootContracts.StakingInfo}"`) .replace(/"state_sender_address":[ ]*".*"/gi, `"state_sender_address": "${rootContracts.StateSender}"`) .save() }, enabled: () => { return this.config.contractAddresses } } ], { exitOnError: true }) } cloneRepositoryTask() { return { title: 'Clone Heimdall repository', task: () => cloneRepository(this.repositoryName, this.repositoryBranch, this.repositoryUrl, this.config.codeDir) } } buildTask() { return { title: 'Build Heimdall', task: () => execa('make', ['build'], { cwd: this.repositoryDir }) } } async getTasks() { return new Listr( [ this.cloneRepositoryTask(), this.buildTask(), { title: 'Init Heimdall', task: () => { return execa(this.heimdalldCmd, ['init', '--home', this.heimdallDataDir, '--chain-id', this.heimdallChainId], { cwd: this.repositoryDir }) } }, { title: 'Create Heimdall account from private key', task: () => { // It generates new account for validator // and replaces it with new validator key return this.generateValidatorKey().then(data => { return fs.writeFile(this.heimdallValidatorKeyFilePath, JSON.stringify(data, null, 2), { mode: 0o755 }) }) } }, { title: 'Process genesis file', task: () => { return this.getProcessGenesisFileTasks() } }, { title: 'Process heimdall config file', task: () => { fileReplacer(this.heimdallHeimdallConfigFilePath) .replace(/eth_rpc_url[ ]*=[ ]*".*"/gi, 'eth_rpc_url = "http://localhost:9545"') .replace(/bor_rpc_url[ ]*=[ ]*".*"/gi, 'bor_rpc_url = "http://localhost:8545"') .save() } }, { title: 'Copy template scripts', task: async () => { const templateDir = path.resolve( new URL(import.meta.url).pathname, '../templates' ) // copy all templates to target directory await fs.copy(templateDir, this.config.targetDirectory) // process all njk templates await processTemplateFiles(this.config.targetDirectory, { obj: this }) } } ], { exitOnError: true } ) } } async function setupHeimdall(config) { //const ganache = new Ganache(config, { contractsBranch: config.contractsBranch }) const heimdall = new Heimdall(config, { repositoryBranch: config.heimdallBranch }) // get all heimdall related tasks const tasks = new Listr([ // { // title: ganache.taskTitle, // task: () => { // return ganache.getTasks() // } // }, { title: heimdall.taskTitle, task: () => { return heimdall.getTasks() } } ], { exitOnError: true }) await tasks.run() console.log('%s Heimdall is ready', chalk.green.bold('DONE')) // print details await config.print() //await ganache.print() await heimdall.print() return true } export default async function () { await printDependencyInstructions() // configuration const config = await loadConfig() await config.loadChainIds() await config.loadAccounts() // load branch const answers = await getDefaultBranch(config) config.set(answers) // start setup await setupHeimdall(config) }