From adc76a4e5bbecf507a5e8b1718c0b7581192120d Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 18 Aug 2020 20:25:10 +1200 Subject: [PATCH 01/44] feat: add more masternode status output --- src/commands/status/masternode.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index b2bdca33..570a5abc 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -27,14 +27,33 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['Version', versionOutput.out.split('\n')[0]]); - // Block count - const blockCountOutput = await dockerCompose.execCommand( + // Sync status + const syncStatusOutput = await dockerCompose.execCommand( config.toEnvs(), 'core', - 'dash-cli getblockcount', + 'dash-cli mnsync status' ); - rows.push(['Blocks', blockCountOutput.out.trim()]); + rows.push(['Sync Status', JSON.parse(syncStatusOutput.out).AssetName]); + + // Header and block count + const blockchaininfoOutput = await dockerCompose.execCommand( + config.toEnvs(), + 'core', + 'dash-cli getblockchaininfo', + ); + + rows.push(['Blocks', JSON.parse(blockchaininfoOutput.out).blocks]); + rows.push(['Headers', JSON.parse(blockchaininfoOutput.out).headers]); + + // Sentinel + const sentinelOutput = await dockerCompose.execCommand( + config.toEnvs(), + 'sentinel', + 'python bin/sentinel.py', + ); + + rows.push(['Sentinel', sentinelOutput.out.split('\n')[0]]) const output = table(rows, { singleLine: true }); From 55fd6a7e366c448372083f25eef3e1ee4a55a25c Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 18 Aug 2020 20:28:37 +1200 Subject: [PATCH 02/44] feat: add masternode status --- src/commands/status/masternode.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 570a5abc..a302bb56 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -46,6 +46,15 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['Blocks', JSON.parse(blockchaininfoOutput.out).blocks]); rows.push(['Headers', JSON.parse(blockchaininfoOutput.out).headers]); + // Header and block count + const masternodeStatusOutput = await dockerCompose.execCommand( + config.toEnvs(), + 'core', + 'dash-cli masternode status', + ); + + rows.push(['Masternode', JSON.parse(masternodeStatusOutput.out).status]); + // Sentinel const sentinelOutput = await dockerCompose.execCommand( config.toEnvs(), From b279c498c7dc14e5200b7dfc0bc91f0c9eb35f78 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 18 Aug 2020 22:37:04 +1200 Subject: [PATCH 03/44] fix: handle sentinel success case --- src/commands/status/masternode.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index a302bb56..551ac96b 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -61,8 +61,10 @@ class MasternodeStatusCommand extends BaseCommand { 'sentinel', 'python bin/sentinel.py', ); + + const sentinelState = sentinelOutput.out.split('\n')[0]; - rows.push(['Sentinel', sentinelOutput.out.split('\n')[0]]) + rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors' )]); const output = table(rows, { singleLine: true }); From 0daa6bb7ec8b345c91a8b05d2c36a6ed4ee9cfa9 Mon Sep 17 00:00:00 2001 From: Leon White Date: Wed, 19 Aug 2020 19:54:57 +1200 Subject: [PATCH 04/44] feat: add port check --- package-lock.json | 5 +++++ package.json | 1 + src/commands/status/masternode.js | 10 ++++++++++ 3 files changed, 16 insertions(+) diff --git a/package-lock.json b/package-lock.json index 989c85b4..0efc82e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3532,6 +3532,11 @@ "tslib": "^1.10.0" } }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, "node-graceful": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/node-graceful/-/node-graceful-3.0.0.tgz", diff --git a/package.json b/package.json index 592f5ddc..c2069d51 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "lodash.get": "^4.4.2", "lodash.merge": "^4.6.2", "lodash.set": "^4.3.2", + "node-fetch": "^2.6.0", "node-graceful": "^3.0.0", "pretty-bytes": "^5.3.0", "pretty-ms": "^7.0.0", diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 551ac96b..d816f92c 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -1,4 +1,5 @@ const { table } = require('table'); +const fetch = require('node-fetch'); const BaseCommand = require('../../oclif/command/BaseCommand'); @@ -66,6 +67,15 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors' )]); + // protx + + rows.push(['ProTx','']) + + // port check + const portState = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); + + rows.push(['Port Check', config.options.core.p2p.port + ' ' + portState]); + const output = table(rows, { singleLine: true }); // eslint-disable-next-line no-console From 7d2609d7c7596504188009ca03b7f3d7a2f0bc69 Mon Sep 17 00:00:00 2001 From: Leon White Date: Thu, 20 Aug 2020 12:41:29 +1200 Subject: [PATCH 05/44] refactor: use JSON where possible --- src/commands/status/masternode.js | 56 ++++++++++++++----------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index d816f92c..7c36db9b 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -20,62 +20,56 @@ class MasternodeStatusCommand extends BaseCommand { const rows = []; // Version - const versionOutput = await dockerCompose.execCommand( + const dashdVersion = (await dockerCompose.execCommand( config.toEnvs(), 'core', 'dashd --version', - ); - - rows.push(['Version', versionOutput.out.split('\n')[0]]); + )).out.split('\n')[0]; // Sync status - const syncStatusOutput = await dockerCompose.execCommand( + const mnsyncStatus = JSON.parse((await dockerCompose.execCommand( config.toEnvs(), 'core', 'dash-cli mnsync status' - ); - - rows.push(['Sync Status', JSON.parse(syncStatusOutput.out).AssetName]); + )).out); + // Header and block count - const blockchaininfoOutput = await dockerCompose.execCommand( + const blockchaininfo = JSON.parse((await dockerCompose.execCommand( config.toEnvs(), 'core', 'dash-cli getblockchaininfo', - ); - - rows.push(['Blocks', JSON.parse(blockchaininfoOutput.out).blocks]); - rows.push(['Headers', JSON.parse(blockchaininfoOutput.out).headers]); + )).out); - // Header and block count - const masternodeStatusOutput = await dockerCompose.execCommand( + // Masternode data + const masternodeStatus = JSON.parse((await dockerCompose.execCommand( config.toEnvs(), 'core', 'dash-cli masternode status', - ); - - rows.push(['Masternode', JSON.parse(masternodeStatusOutput.out).status]); + )).out); // Sentinel - const sentinelOutput = await dockerCompose.execCommand( + const sentinelState = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', 'python bin/sentinel.py', - ); - - const sentinelState = sentinelOutput.out.split('\n')[0]; + )).out.split('\n')[0]; - rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors' )]); - - // protx - - rows.push(['ProTx','']) - - // port check + // Port check const portState = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); - - rows.push(['Port Check', config.options.core.p2p.port + ' ' + portState]); + // Build table*/ + rows.push(['Version', dashdVersion]); + rows.push(['Sync Status', mnsyncStatus.AssetName]); + rows.push(['Headers', blockchaininfo.headers]); + rows.push(['Blocks', blockchaininfo.blocks]); + rows.push(['Masternode Status', masternodeStatus.state]); + if (masternodeStatus.state === 'READY') { + rows.push(['Service', masternodeStatus.dmnState.service]); + rows.push(['ProTx','']); + } + rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors' )]); + rows.push(['Port Check', config.options.core.p2p.port + ' ' + portState]); const output = table(rows, { singleLine: true }); // eslint-disable-next-line no-console From 82c02f5af55de3e4502619c636de8777c370813e Mon Sep 17 00:00:00 2001 From: Leon White Date: Thu, 20 Aug 2020 12:50:59 +1200 Subject: [PATCH 06/44] feat: show dmn state --- src/commands/status/masternode.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 7c36db9b..953cf3f7 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -65,11 +65,13 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['Blocks', blockchaininfo.blocks]); rows.push(['Masternode Status', masternodeStatus.state]); if (masternodeStatus.state === 'READY') { + rows.push(['ProTx Hash', masternodeStatus.proTxHash]); rows.push(['Service', masternodeStatus.dmnState.service]); - rows.push(['ProTx','']); + rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); } rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors' )]); rows.push(['Port Check', config.options.core.p2p.port + ' ' + portState]); + const output = table(rows, { singleLine: true }); // eslint-disable-next-line no-console From f9fa44dc27b634cc9893643b62c0649c5f57204a Mon Sep 17 00:00:00 2001 From: Leon White Date: Thu, 20 Aug 2020 12:54:46 +1200 Subject: [PATCH 07/44] fix: syntax --- src/commands/status/masternode.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 953cf3f7..07e58d30 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -33,7 +33,6 @@ class MasternodeStatusCommand extends BaseCommand { 'dash-cli mnsync status' )).out); - // Header and block count const blockchaininfo = JSON.parse((await dockerCompose.execCommand( config.toEnvs(), @@ -58,7 +57,7 @@ class MasternodeStatusCommand extends BaseCommand { // Port check const portState = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); - // Build table*/ + // Build table rows.push(['Version', dashdVersion]); rows.push(['Sync Status', mnsyncStatus.AssetName]); rows.push(['Headers', blockchaininfo.headers]); From 7ab1567dae0384146e55da271b0aaeda639fb250 Mon Sep 17 00:00:00 2001 From: Leon White Date: Fri, 21 Aug 2020 14:43:43 +1200 Subject: [PATCH 08/44] feat: show tendermint status --- src/commands/status/masternode.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 07e58d30..3f831076 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -54,11 +54,23 @@ class MasternodeStatusCommand extends BaseCommand { 'python bin/sentinel.py', )).out.split('\n')[0]; + const tendermintVersion = (await dockerCompose.execCommand( + config.toEnvs(), + 'drive_tendermint', + 'tendermint version', + )).out.split('\n')[0]; + + const tendermintStatus = JSON.parse((await dockerCompose.execCommand( + config.toEnvs(), + 'drive_tendermint', + 'curl localhost:26657/status', + )).out); + // Port check const portState = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); // Build table - rows.push(['Version', dashdVersion]); + rows.push(['Dashd Version', dashdVersion]); rows.push(['Sync Status', mnsyncStatus.AssetName]); rows.push(['Headers', blockchaininfo.headers]); rows.push(['Blocks', blockchaininfo.blocks]); @@ -70,6 +82,11 @@ class MasternodeStatusCommand extends BaseCommand { } rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors' )]); rows.push(['Port Check', config.options.core.p2p.port + ' ' + portState]); + if (config.network !== 'testnet') { + rows.push(['Tendermint Version', tendermintVersion]); + rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); + rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); + } const output = table(rows, { singleLine: true }); From 761505be33b6f042ee8ee7698ae5e553b1012572 Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 24 Aug 2020 16:37:54 +1200 Subject: [PATCH 09/44] feat: use RPC instead of exec in container --- docker-compose.yml | 1 + src/commands/status/masternode.js | 40 +++++++++++++------------------ 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ddd4a15e..620e2288 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,7 @@ services: restart: unless-stopped ports: - ${CORE_P2P_PORT:?err}:${CORE_P2P_PORT:?err} # P2P + - 20002:20002 volumes: - ./configs/${NETWORK:?err}/core/dashd.conf:/dash/.dashcore/dash.conf - ./data/${NETWORK:?err}/core:/dash/data diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 3f831076..8acddfde 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -2,12 +2,14 @@ const { table } = require('table'); const fetch = require('node-fetch'); const BaseCommand = require('../../oclif/command/BaseCommand'); +const CoreService = require('../../core/CoreService'); class MasternodeStatusCommand extends BaseCommand { /** * @param {Object} args * @param {Object} flags * @param {DockerCompose} dockerCompose + * @param {CoreService} coreService * @param {Config} config * @return {Promise} */ @@ -15,10 +17,16 @@ class MasternodeStatusCommand extends BaseCommand { args, flags, dockerCompose, + createRpcClient, config, ) { const rows = []; + const coreService = new CoreService( + createRpcClient(), + dockerCompose.docker.getContainer('core') + ); + // Version const dashdVersion = (await dockerCompose.execCommand( config.toEnvs(), @@ -26,26 +34,9 @@ class MasternodeStatusCommand extends BaseCommand { 'dashd --version', )).out.split('\n')[0]; - // Sync status - const mnsyncStatus = JSON.parse((await dockerCompose.execCommand( - config.toEnvs(), - 'core', - 'dash-cli mnsync status' - )).out); - - // Header and block count - const blockchaininfo = JSON.parse((await dockerCompose.execCommand( - config.toEnvs(), - 'core', - 'dash-cli getblockchaininfo', - )).out); - - // Masternode data - const masternodeStatus = JSON.parse((await dockerCompose.execCommand( - config.toEnvs(), - 'core', - 'dash-cli masternode status', - )).out); + const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; + const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; + const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; // Sentinel const sentinelState = (await dockerCompose.execCommand( @@ -54,6 +45,7 @@ class MasternodeStatusCommand extends BaseCommand { 'python bin/sentinel.py', )).out.split('\n')[0]; + // Tendermint const tendermintVersion = (await dockerCompose.execCommand( config.toEnvs(), 'drive_tendermint', @@ -72,22 +64,22 @@ class MasternodeStatusCommand extends BaseCommand { // Build table rows.push(['Dashd Version', dashdVersion]); rows.push(['Sync Status', mnsyncStatus.AssetName]); - rows.push(['Headers', blockchaininfo.headers]); - rows.push(['Blocks', blockchaininfo.blocks]); + rows.push(['Headers', blockchainInfo.headers]); + rows.push(['Blocks', blockchainInfo.blocks]); rows.push(['Masternode Status', masternodeStatus.state]); if (masternodeStatus.state === 'READY') { rows.push(['ProTx Hash', masternodeStatus.proTxHash]); rows.push(['Service', masternodeStatus.dmnState.service]); rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); } - rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors' )]); + rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors')]); rows.push(['Port Check', config.options.core.p2p.port + ' ' + portState]); if (config.network !== 'testnet') { rows.push(['Tendermint Version', tendermintVersion]); rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); } - + const output = table(rows, { singleLine: true }); // eslint-disable-next-line no-console From 1374d9dd3436ee51b5fb2b6304673d6365b771b0 Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 24 Aug 2020 18:13:23 +1200 Subject: [PATCH 10/44] feat: show docker image and version --- src/commands/status/services.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/commands/status/services.js b/src/commands/status/services.js index c65a13c0..084fa379 100644 --- a/src/commands/status/services.js +++ b/src/commands/status/services.js @@ -39,14 +39,13 @@ class ServicesStatusCommand extends BaseCommand { } const tableRows = [ - ['Service', 'Container ID', 'Version', 'Status'], + ['Service', 'Container ID', 'Image', 'Version', 'Status'], ]; for (const [serviceName, serviceDescription] of Object.entries(serviceHumanNames)) { let containerId; let status; let exitCode; - let version; try { ({ @@ -55,11 +54,6 @@ class ServicesStatusCommand extends BaseCommand { Status: status, ExitCode: exitCode, }, - Config: { - Labels: { - 'org.dash.version': version, - }, - }, } = await dockerCompose.inspectService(config.toEnvs(), serviceName)); } catch (e) { if (e instanceof ContainerIsNotPresentError) { @@ -77,9 +71,26 @@ class ServicesStatusCommand extends BaseCommand { statusText = chalk.keyword(status === 'running' ? 'green' : 'red')(status); } + let path; + let image; + let version; + + if (serviceName === 'sentinel') { continue }; + if (serviceName === 'dapi_tx_filter_stream') { continue }; + if (serviceName === 'core') { + path = serviceName + } else { + path = 'platform.' + serviceName.replace('_', '.'); + } + image = config.get(path + '.docker.image') + version = config.get(path + '.version'); + + + tableRows.push([ serviceDescription, containerId ? containerId.slice(0, 12) : undefined, + image, version, statusText, ]); From c81d70067285c1dc9aee8f498881b6a8c06b0c69 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 25 Aug 2020 17:05:34 +1200 Subject: [PATCH 11/44] refactor: get image & version from docker inspect --- src/commands/status/services.js | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/commands/status/services.js b/src/commands/status/services.js index 084fa379..a61bc159 100644 --- a/src/commands/status/services.js +++ b/src/commands/status/services.js @@ -46,6 +46,8 @@ class ServicesStatusCommand extends BaseCommand { let containerId; let status; let exitCode; + let image; + let version; try { ({ @@ -54,6 +56,9 @@ class ServicesStatusCommand extends BaseCommand { Status: status, ExitCode: exitCode, }, + Config: { + Image: image, + } } = await dockerCompose.inspectService(config.toEnvs(), serviceName)); } catch (e) { if (e instanceof ContainerIsNotPresentError) { @@ -71,21 +76,7 @@ class ServicesStatusCommand extends BaseCommand { statusText = chalk.keyword(status === 'running' ? 'green' : 'red')(status); } - let path; - let image; - let version; - - if (serviceName === 'sentinel') { continue }; - if (serviceName === 'dapi_tx_filter_stream') { continue }; - if (serviceName === 'core') { - path = serviceName - } else { - path = 'platform.' + serviceName.replace('_', '.'); - } - image = config.get(path + '.docker.image') - version = config.get(path + '.version'); - - + [image, version] = image.split(':'); tableRows.push([ serviceDescription, From 2fd9b8697d1b400cceb79a901015ebf8300cb969 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 25 Aug 2020 17:58:05 +1200 Subject: [PATCH 12/44] refactor: go back to docker exec instead of RPC --- docker-compose.yml | 1 - src/commands/status/masternode.js | 74 ++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 620e2288..ddd4a15e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,6 @@ services: restart: unless-stopped ports: - ${CORE_P2P_PORT:?err}:${CORE_P2P_PORT:?err} # P2P - - 20002:20002 volumes: - ./configs/${NETWORK:?err}/core/dashd.conf:/dash/.dashcore/dash.conf - ./data/${NETWORK:?err}/core:/dash/data diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 8acddfde..7e05ebad 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -2,14 +2,12 @@ const { table } = require('table'); const fetch = require('node-fetch'); const BaseCommand = require('../../oclif/command/BaseCommand'); -const CoreService = require('../../core/CoreService'); class MasternodeStatusCommand extends BaseCommand { /** * @param {Object} args * @param {Object} flags * @param {DockerCompose} dockerCompose - * @param {CoreService} coreService * @param {Config} config * @return {Promise} */ @@ -17,16 +15,10 @@ class MasternodeStatusCommand extends BaseCommand { args, flags, dockerCompose, - createRpcClient, config, ) { const rows = []; - const coreService = new CoreService( - createRpcClient(), - dockerCompose.docker.getContainer('core') - ); - // Version const dashdVersion = (await dockerCompose.execCommand( config.toEnvs(), @@ -34,9 +26,26 @@ class MasternodeStatusCommand extends BaseCommand { 'dashd --version', )).out.split('\n')[0]; - const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; - const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; + // Sync status + const mnsyncStatus = JSON.parse((await dockerCompose.execCommand( + config.toEnvs(), + 'core', + 'dash-cli mnsync status' + )).out); + + // Header and block count + const blockchainInfo = JSON.parse((await dockerCompose.execCommand( + config.toEnvs(), + 'core', + 'dash-cli getblockchaininfo', + )).out); + + // Masternode data + const masternodeStatus = JSON.parse((await dockerCompose.execCommand( + config.toEnvs(), + 'core', + 'dash-cli masternode status', + )).out); // Sentinel const sentinelState = (await dockerCompose.execCommand( @@ -45,27 +54,38 @@ class MasternodeStatusCommand extends BaseCommand { 'python bin/sentinel.py', )).out.split('\n')[0]; - // Tendermint - const tendermintVersion = (await dockerCompose.execCommand( - config.toEnvs(), - 'drive_tendermint', - 'tendermint version', - )).out.split('\n')[0]; + let tendermintVersion; + let tendermintStatus; - const tendermintStatus = JSON.parse((await dockerCompose.execCommand( - config.toEnvs(), - 'drive_tendermint', - 'curl localhost:26657/status', - )).out); + if (config.network !== 'testnet') { + // Tendermint + tendermintVersion = (await dockerCompose.execCommand( + config.toEnvs(), + 'drive_tendermint', + 'tendermint version', + )).out.split('\n')[0]; + + // curl fails if tendermint has not started yet because abci is waiting for core to sync + if (mnsyncStatus.IsSynced === true) { + tendermintStatus = JSON.parse((await dockerCompose.execCommand( + config.toEnvs(), + 'drive_tendermint', + 'curl localhost:26657/status', + )).out); + } + } // Port check - const portState = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); + const corePort = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); + //const tendermintPort = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); // Build table rows.push(['Dashd Version', dashdVersion]); rows.push(['Sync Status', mnsyncStatus.AssetName]); + rows.push(['Core Port', config.options.core.p2p.port + ' ' + corePort]); rows.push(['Headers', blockchainInfo.headers]); rows.push(['Blocks', blockchainInfo.blocks]); + rows.push(['Core Sync', mnsyncStatus.IsSynced]); rows.push(['Masternode Status', masternodeStatus.state]); if (masternodeStatus.state === 'READY') { rows.push(['ProTx Hash', masternodeStatus.proTxHash]); @@ -73,11 +93,13 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); } rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors')]); - rows.push(['Port Check', config.options.core.p2p.port + ' ' + portState]); if (config.network !== 'testnet') { rows.push(['Tendermint Version', tendermintVersion]); - rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); - rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); + //rows.push(['Tendermint Port', config.options.core.p2p.port + ' ' + tendermintPort]); + if (mnsyncStatus.IsSynced === true) { + rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); + rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); + } } const output = table(rows, { singleLine: true }); From 9ac4226c762b824ff57327e982d2238bc356d4f8 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 25 Aug 2020 19:06:23 +1200 Subject: [PATCH 13/44] feat: port check for tendermint --- src/commands/status/masternode.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 7e05ebad..b3791e57 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -77,7 +77,7 @@ class MasternodeStatusCommand extends BaseCommand { // Port check const corePort = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); - //const tendermintPort = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); + const tendermintPort = await fetch('https://mnowatch.org/26656/').then(res => res.text()); // Build table rows.push(['Dashd Version', dashdVersion]); @@ -95,7 +95,7 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors')]); if (config.network !== 'testnet') { rows.push(['Tendermint Version', tendermintVersion]); - //rows.push(['Tendermint Port', config.options.core.p2p.port + ' ' + tendermintPort]); + rows.push(['Tendermint Port', '26656 ' + tendermintPort]); if (mnsyncStatus.IsSynced === true) { rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); From a0b2bcfcbb18cab88f138698925b53dbd2443e8b Mon Sep 17 00:00:00 2001 From: Leon White Date: Wed, 26 Aug 2020 14:15:16 +1200 Subject: [PATCH 14/44] feat: add tendermint app hash --- src/commands/status/masternode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index b3791e57..318cf728 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -99,6 +99,7 @@ class MasternodeStatusCommand extends BaseCommand { if (mnsyncStatus.IsSynced === true) { rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); + rows.push(['Tendermint App Hash', tendermintStatus.result.sync_info.latest_app_hash]); } } From 611284bc06a40f9740e7070fdaf66a458b40c58f Mon Sep 17 00:00:00 2001 From: Leon White Date: Wed, 26 Aug 2020 16:54:41 +1200 Subject: [PATCH 15/44] feat: support arbitrary port for tendermint --- src/commands/status/masternode.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 318cf728..96de198f 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -76,13 +76,19 @@ class MasternodeStatusCommand extends BaseCommand { } // Port check - const corePort = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); - const tendermintPort = await fetch('https://mnowatch.org/26656/').then(res => res.text()); + const corePortState = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); + + const tendermintPortNum = (await dockerCompose.inspectService( + config.toEnvs(), + 'drive_tendermint' + )).NetworkSettings.Ports['26656/tcp'][0].HostPort; + + const tendermintPortState = await fetch('https://mnowatch.org/' + tendermintPortNum + '/').then(res => res.text()); // Build table rows.push(['Dashd Version', dashdVersion]); rows.push(['Sync Status', mnsyncStatus.AssetName]); - rows.push(['Core Port', config.options.core.p2p.port + ' ' + corePort]); + rows.push(['Core Port', config.options.core.p2p.port + ' ' + corePortState]); rows.push(['Headers', blockchainInfo.headers]); rows.push(['Blocks', blockchainInfo.blocks]); rows.push(['Core Sync', mnsyncStatus.IsSynced]); @@ -95,7 +101,7 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors')]); if (config.network !== 'testnet') { rows.push(['Tendermint Version', tendermintVersion]); - rows.push(['Tendermint Port', '26656 ' + tendermintPort]); + rows.push(['Tendermint Port', tendermintPortNum + ' ' + tendermintPortState]); if (mnsyncStatus.IsSynced === true) { rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); From 79f8355b9408d38dc1ad604ea696ba21928d49d7 Mon Sep 17 00:00:00 2001 From: Leon White Date: Thu, 27 Aug 2020 19:11:37 +1200 Subject: [PATCH 16/44] fix: show tag in image column --- src/commands/status/services.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/commands/status/services.js b/src/commands/status/services.js index a61bc159..9a8a7eb5 100644 --- a/src/commands/status/services.js +++ b/src/commands/status/services.js @@ -39,7 +39,7 @@ class ServicesStatusCommand extends BaseCommand { } const tableRows = [ - ['Service', 'Container ID', 'Image', 'Version', 'Status'], + ['Service', 'Container ID', 'Image', 'Status'], ]; for (const [serviceName, serviceDescription] of Object.entries(serviceHumanNames)) { @@ -47,7 +47,6 @@ class ServicesStatusCommand extends BaseCommand { let status; let exitCode; let image; - let version; try { ({ @@ -76,13 +75,10 @@ class ServicesStatusCommand extends BaseCommand { statusText = chalk.keyword(status === 'running' ? 'green' : 'red')(status); } - [image, version] = image.split(':'); - tableRows.push([ serviceDescription, containerId ? containerId.slice(0, 12) : undefined, image, - version, statusText, ]); } From b15c098f2ea9bc82113af5b32b110e1af9cb32bf Mon Sep 17 00:00:00 2001 From: Leon White Date: Thu, 3 Sep 2020 12:46:23 +1200 Subject: [PATCH 17/44] fix: check for testnet properly --- src/commands/status/masternode.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 96de198f..4d718ccb 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -57,7 +57,7 @@ class MasternodeStatusCommand extends BaseCommand { let tendermintVersion; let tendermintStatus; - if (config.network !== 'testnet') { + if (config.options.network !== 'testnet') { // Tendermint tendermintVersion = (await dockerCompose.execCommand( config.toEnvs(), @@ -77,14 +77,16 @@ class MasternodeStatusCommand extends BaseCommand { // Port check const corePortState = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); - - const tendermintPortNum = (await dockerCompose.inspectService( - config.toEnvs(), - 'drive_tendermint' - )).NetworkSettings.Ports['26656/tcp'][0].HostPort; - const tendermintPortState = await fetch('https://mnowatch.org/' + tendermintPortNum + '/').then(res => res.text()); + if (config.options.network !== 'testnet') { + const tendermintPortNum = (await dockerCompose.inspectService( + config.toEnvs(), + 'drive_tendermint' + )).NetworkSettings.Ports['26656/tcp'][0].HostPort; + const tendermintPortState = await fetch('https://mnowatch.org/' + tendermintPortNum + '/').then(res => res.text()); + } + // Build table rows.push(['Dashd Version', dashdVersion]); rows.push(['Sync Status', mnsyncStatus.AssetName]); @@ -99,7 +101,7 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); } rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors')]); - if (config.network !== 'testnet') { + if (config.options.network !== 'testnet') { rows.push(['Tendermint Version', tendermintVersion]); rows.push(['Tendermint Port', tendermintPortNum + ' ' + tendermintPortState]); if (mnsyncStatus.IsSynced === true) { From 133068aa35459161aeca325597195ae03df2c133 Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 16 Nov 2020 13:31:52 -0800 Subject: [PATCH 18/44] fix: refactor to use RPC --- src/commands/status/masternode.js | 51 ++++++++++++++++--------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 4d718ccb..8b3de525 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -2,12 +2,14 @@ const { table } = require('table'); const fetch = require('node-fetch'); const BaseCommand = require('../../oclif/command/BaseCommand'); +const CoreService = require('../../core/CoreService'); class MasternodeStatusCommand extends BaseCommand { /** * @param {Object} args * @param {Object} flags * @param {DockerCompose} dockerCompose + * @param {CoreService} coreService * @param {Config} config * @return {Promise} */ @@ -15,10 +17,22 @@ class MasternodeStatusCommand extends BaseCommand { args, flags, dockerCompose, + createRpcClient, config, ) { const rows = []; + const coreService = new CoreService( + createRpcClient( + { + port: config.get('core.rpc.port'), + user: config.get('core.rpc.user'), + pass: config.get('core.rpc.password'), + }, + ), + dockerCompose.docker.getContainer('core'), + ); + // Version const dashdVersion = (await dockerCompose.execCommand( config.toEnvs(), @@ -27,25 +41,13 @@ class MasternodeStatusCommand extends BaseCommand { )).out.split('\n')[0]; // Sync status - const mnsyncStatus = JSON.parse((await dockerCompose.execCommand( - config.toEnvs(), - 'core', - 'dash-cli mnsync status' - )).out); + const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - // Header and block count - const blockchainInfo = JSON.parse((await dockerCompose.execCommand( - config.toEnvs(), - 'core', - 'dash-cli getblockchaininfo', - )).out); + // Header and block count + const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; - // Masternode data - const masternodeStatus = JSON.parse((await dockerCompose.execCommand( - config.toEnvs(), - 'core', - 'dash-cli masternode status', - )).out); + // Masternode data + const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; // Sentinel const sentinelState = (await dockerCompose.execCommand( @@ -76,25 +78,26 @@ class MasternodeStatusCommand extends BaseCommand { } // Port check - const corePortState = await fetch('https://mnowatch.org/' + config.options.core.p2p.port + '/').then(res => res.text()); + const corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); if (config.options.network !== 'testnet') { const tendermintPortNum = (await dockerCompose.inspectService( config.toEnvs(), - 'drive_tendermint' + 'drive_tendermint', )).NetworkSettings.Ports['26656/tcp'][0].HostPort; - const tendermintPortState = await fetch('https://mnowatch.org/' + tendermintPortNum + '/').then(res => res.text()); + const tendermintPortState = await fetch(`https://mnowatch.org/${tendermintPortNum}/`).then((res) => res.text()); } - + // Build table rows.push(['Dashd Version', dashdVersion]); rows.push(['Sync Status', mnsyncStatus.AssetName]); - rows.push(['Core Port', config.options.core.p2p.port + ' ' + corePortState]); + rows.push(['Core Port', `${config.options.core.p2p.port} ${corePortState}`]); rows.push(['Headers', blockchainInfo.headers]); rows.push(['Blocks', blockchainInfo.blocks]); rows.push(['Core Sync', mnsyncStatus.IsSynced]); - rows.push(['Masternode Status', masternodeStatus.state]); + rows.push(['Masternode State', masternodeStatus.state]); + rows.push(['Masternode Status', masternodeStatus.status]); if (masternodeStatus.state === 'READY') { rows.push(['ProTx Hash', masternodeStatus.proTxHash]); rows.push(['Service', masternodeStatus.dmnState.service]); @@ -103,7 +106,7 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors')]); if (config.options.network !== 'testnet') { rows.push(['Tendermint Version', tendermintVersion]); - rows.push(['Tendermint Port', tendermintPortNum + ' ' + tendermintPortState]); + rows.push(['Tendermint Port', `${tendermintPortNum} ${tendermintPortState}`]); if (mnsyncStatus.IsSynced === true) { rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); From 3ff0fc018d5d50db4055b35b8979a1a340974366 Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 16 Nov 2020 17:26:23 -0800 Subject: [PATCH 19/44] fix: refactor tendermint calls --- src/commands/status/masternode.js | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 8b3de525..6c463df0 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -58,6 +58,8 @@ class MasternodeStatusCommand extends BaseCommand { let tendermintVersion; let tendermintStatus; + let tendermintPortNum; + let tendermintPortState; if (config.options.network !== 'testnet') { // Tendermint @@ -69,11 +71,7 @@ class MasternodeStatusCommand extends BaseCommand { // curl fails if tendermint has not started yet because abci is waiting for core to sync if (mnsyncStatus.IsSynced === true) { - tendermintStatus = JSON.parse((await dockerCompose.execCommand( - config.toEnvs(), - 'drive_tendermint', - 'curl localhost:26657/status', - )).out); + tendermintStatus = JSON.parse(await fetch(`localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); } } @@ -81,12 +79,8 @@ class MasternodeStatusCommand extends BaseCommand { const corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); if (config.options.network !== 'testnet') { - const tendermintPortNum = (await dockerCompose.inspectService( - config.toEnvs(), - 'drive_tendermint', - )).NetworkSettings.Ports['26656/tcp'][0].HostPort; - - const tendermintPortState = await fetch(`https://mnowatch.org/${tendermintPortNum}/`).then((res) => res.text()); + tendermintPortNum = config.get('platform.drive.tendermint.p2p.port'); + tendermintPortState = await fetch(`https://mnowatch.org/${tendermintPortNum}/`).then((res) => res.text()); } // Build table From 4d228c0c236711f216d7dc40de94413505a3831e Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 16 Nov 2020 17:29:21 -0800 Subject: [PATCH 20/44] fix: specify tendermint RPC protocol --- src/commands/status/masternode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 6c463df0..543730a3 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -71,7 +71,7 @@ class MasternodeStatusCommand extends BaseCommand { // curl fails if tendermint has not started yet because abci is waiting for core to sync if (mnsyncStatus.IsSynced === true) { - tendermintStatus = JSON.parse(await fetch(`localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); + tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); } } From d29d922e8a47fb851421ff5563a8e0ffb073e62b Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 16 Nov 2020 19:07:05 -0800 Subject: [PATCH 21/44] fix: consistent terminology --- src/commands/status/masternode.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 543730a3..16c9086e 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -85,10 +85,10 @@ class MasternodeStatusCommand extends BaseCommand { // Build table rows.push(['Dashd Version', dashdVersion]); - rows.push(['Sync Status', mnsyncStatus.AssetName]); + rows.push(['Core Sync', mnsyncStatus.AssetName]); rows.push(['Core Port', `${config.options.core.p2p.port} ${corePortState}`]); - rows.push(['Headers', blockchainInfo.headers]); - rows.push(['Blocks', blockchainInfo.blocks]); + rows.push(['Core Headers', blockchainInfo.headers]); + rows.push(['Core Blocks', blockchainInfo.blocks]); rows.push(['Core Sync', mnsyncStatus.IsSynced]); rows.push(['Masternode State', masternodeStatus.state]); rows.push(['Masternode Status', masternodeStatus.status]); @@ -97,7 +97,7 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['Service', masternodeStatus.dmnState.service]); rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); } - rows.push(['Sentinel', (sentinelState !== '' ? sentinelState : 'No errors')]); + rows.push(['Sentinel Status', (sentinelState !== '' ? sentinelState : 'No errors')]); if (config.options.network !== 'testnet') { rows.push(['Tendermint Version', tendermintVersion]); rows.push(['Tendermint Port', `${tendermintPortNum} ${tendermintPortState}`]); From c6bd73edb3fcb0e11476b873487593a326c764e8 Mon Sep 17 00:00:00 2001 From: Leon White Date: Wed, 18 Nov 2020 16:27:01 -0800 Subject: [PATCH 22/44] feat: add arch --- src/commands/status/host.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commands/status/host.js b/src/commands/status/host.js index 19adc20c..2eb826ac 100644 --- a/src/commands/status/host.js +++ b/src/commands/status/host.js @@ -16,6 +16,7 @@ class HostStatusCommand extends BaseCommand { rows.push(['Hostname', os.hostname()]); rows.push(['Uptime', prettyMs(os.uptime() * 1000)]); rows.push(['Platform', os.platform()]); + rows.push(['Arch', os.arch()]); rows.push(['Username', os.userInfo().username]); rows.push(['Loadavg', os.loadavg()]); rows.push(['Diskfree', 0]); // Waiting for feature: https://github.com/nodejs/node/pull/31351 From 3eb0e097e36aac87f35d2ccfa65a800644e6fa76 Mon Sep 17 00:00:00 2001 From: Leon White Date: Wed, 18 Nov 2020 16:28:33 -0800 Subject: [PATCH 23/44] fix: round loadavg to 2 decimal places (for ARM) --- src/commands/status/host.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/status/host.js b/src/commands/status/host.js index 2eb826ac..3c301f02 100644 --- a/src/commands/status/host.js +++ b/src/commands/status/host.js @@ -18,7 +18,7 @@ class HostStatusCommand extends BaseCommand { rows.push(['Platform', os.platform()]); rows.push(['Arch', os.arch()]); rows.push(['Username', os.userInfo().username]); - rows.push(['Loadavg', os.loadavg()]); + rows.push(['Loadavg', os.loadavg().map((load) => load.toFixed(2))]); rows.push(['Diskfree', 0]); // Waiting for feature: https://github.com/nodejs/node/pull/31351 rows.push(['Memory', `${prettyByte(os.totalmem())} / ${prettyByte(os.freemem())}`]); rows.push(['CPUs', os.cpus().length]); From 5040dc9cc19959ed703beacf88edb7462ed13e90 Mon Sep 17 00:00:00 2001 From: Leon White Date: Thu, 19 Nov 2020 10:18:36 -0800 Subject: [PATCH 24/44] feat: initial refactor for different command names --- src/commands/status/core.js | 84 +++++++++++++++++++++++ src/commands/status/index.js | 117 ++++++++++++++++++++++++++++++++ src/commands/status/platform.js | 80 ++++++++++++++++++++++ 3 files changed, 281 insertions(+) create mode 100644 src/commands/status/core.js create mode 100644 src/commands/status/index.js create mode 100644 src/commands/status/platform.js diff --git a/src/commands/status/core.js b/src/commands/status/core.js new file mode 100644 index 00000000..3a2edf05 --- /dev/null +++ b/src/commands/status/core.js @@ -0,0 +1,84 @@ +const { table } = require('table'); +const fetch = require('node-fetch'); + +const BaseCommand = require('../../oclif/command/BaseCommand'); +const CoreService = require('../../core/CoreService'); + +class CoreStatusCommand extends BaseCommand { + /** + * @param {Object} args + * @param {Object} flags + * @param {DockerCompose} dockerCompose + * @param {CoreService} coreService + * @param {Config} config + * @return {Promise} + */ + async runWithDependencies( + args, + flags, + dockerCompose, + createRpcClient, + config, + ) { + const rows = []; + + const coreService = new CoreService( + createRpcClient( + { + port: config.get('core.rpc.port'), + user: config.get('core.rpc.user'), + pass: config.get('core.rpc.password'), + }, + ), + dockerCompose.docker.getContainer('core'), + ); + + // Network data + const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; + const networkInfo = (await coreService.getRpcClient().getNetworkInfo()).result; + const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; + const peerInfo = (await coreService.getRpcClient().getPeerInfo()).result; + const latestVersion = JSON.parse(await fetch('https://api.github.com/repos/dashpay/dash/releases/latest').then((res) => res.text())); + const corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); + const SentinelVersion = (await dockerCompose.execCommand( + config.toEnvs(), + 'sentinel', + 'python bin/sentinel.py -v', + )).out.split('\n')[0]; + const sentinelState = (await dockerCompose.execCommand( + config.toEnvs(), + 'sentinel', + 'python bin/sentinel.py', + )).out.split('\n')[0]; + + // Build table + rows.push(['Version', networkInfo.subversion.replace(/\/|\(.*?\)/g, '')]); + rows.push(['Latest version', latestVersion.tag_name]); + rows.push(['Network', blockchainInfo.chain]); + rows.push(['Status', '-']); + rows.push(['Sync asset', mnsyncStatus.AssetName]); + rows.push(['Peer count', peerInfo.length]); + rows.push(['P2P service', `${config.options.externalIp}:${config.options.core.p2p.port}`]); + rows.push(['P2P port', `${config.options.core.p2p.port} ${corePortState}`]); + rows.push(['RPC service', `127.0.0.1:${config.options.core.rpc.port}`]); + rows.push(['Header height', blockchainInfo.headers]); + rows.push(['Block height', blockchainInfo.blocks]); + rows.push(['Remote block height', '-']); + rows.push(['Difficulty', blockchainInfo.difficulty]); + rows.push(['Sentinel version', SentinelVersion]); + rows.push(['Sentinel status', sentinelState]); + + const output = table(rows, { singleLine: true }); + + // eslint-disable-next-line no-console + console.log(output); + } +} + +CoreStatusCommand.description = 'Show status overview'; + +CoreStatusCommand.flags = { + ...BaseCommand.flags, +}; + +module.exports = CoreStatusCommand; diff --git a/src/commands/status/index.js b/src/commands/status/index.js new file mode 100644 index 00000000..e201dd52 --- /dev/null +++ b/src/commands/status/index.js @@ -0,0 +1,117 @@ +const { table } = require('table'); +const fetch = require('node-fetch'); + +const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPresentError'); + +const BaseCommand = require('../../oclif/command/BaseCommand'); +const CoreService = require('../../core/CoreService'); + +class StatusCommand extends BaseCommand { + /** + * @param {Object} args + * @param {Object} flags + * @param {DockerCompose} dockerCompose + * @param {CoreService} coreService + * @param {Config} config + * @return {Promise} + */ + async runWithDependencies( + args, + flags, + dockerCompose, + createRpcClient, + config, + ) { + const rows = []; + + const serviceHumanNames = { + core: 'Core Status', + }; + + if (config.options.network !== 'testnet') { + Object.assign(serviceHumanNames, { + drive_tendermint: 'Tenderdash Status', + }); + } + + for (const [serviceName, serviceDescription] of Object.entries(serviceHumanNames)) { + let status; + + try { + ({ + State: { + Status: status, + }, + } = await dockerCompose.inspectService(config.toEnvs(), serviceName)); + } catch (e) { + if (e instanceof ContainerIsNotPresentError) { + status = 'not started'; + } + } + + rows.push([ + serviceDescription, + status, + ]); + } + + const coreService = new CoreService( + createRpcClient( + { + port: config.get('core.rpc.port'), + user: config.get('core.rpc.user'), + pass: config.get('core.rpc.password'), + }, + ), + dockerCompose.docker.getContainer('core'), + ); + + // Core status + const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; + + // Network data + const networkStatus = (await coreService.getRpcClient().getNetworkInfo()).result; + + // Network data + const blockchainStatus = (await coreService.getRpcClient().getBlockchainInfo()).result; + + // Masternode data + const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; + + // Platform status + let tendermintStatus; + if (config.options.network !== 'testnet') { + // curl fails if tendermint has not started yet because abci is waiting for core to sync + if (mnsyncStatus.IsSynced === true) { + tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); + } + } + + // Build table + rows.push(['Network', blockchainStatus.chain]); + rows.push(['Masternode Status', masternodeStatus.status]); + rows.push(['Core Version', networkStatus.subversion.replace(/\/|\(.*?\)/g, '')]); + rows.push(['Core Status', mnsyncStatus.AssetName]); + if (config.options.network !== 'testnet') { + rows.push(['Platform Version', tendermintStatus.result.node_info.version]); + rows.push(['Platform Status', '-']); + } + if (masternodeStatus.state === 'READY') { + rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); + rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); + } + + const output = table(rows, { singleLine: true }); + + // eslint-disable-next-line no-console + console.log(output); + } +} + +StatusCommand.description = 'Show status overview'; + +StatusCommand.flags = { + ...BaseCommand.flags, +}; + +module.exports = StatusCommand; diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js new file mode 100644 index 00000000..91d29d38 --- /dev/null +++ b/src/commands/status/platform.js @@ -0,0 +1,80 @@ +const { table } = require('table'); +const fetch = require('node-fetch'); + +const BaseCommand = require('../../oclif/command/BaseCommand'); +const CoreService = require('../../core/CoreService'); + +class CoreStatusCommand extends BaseCommand { + /** + * @param {Object} args + * @param {Object} flags + * @param {DockerCompose} dockerCompose + * @param {CoreService} coreService + * @param {Config} config + * @return {Promise} + */ + async runWithDependencies( + args, + flags, + dockerCompose, + createRpcClient, + config, + ) { + const rows = []; + + const coreService = new CoreService( + createRpcClient( + { + port: config.get('core.rpc.port'), + user: config.get('core.rpc.user'), + pass: config.get('core.rpc.password'), + }, + ), + dockerCompose.docker.getContainer('core'), + ); + + // Core status + const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; + + // Platform status + let tendermintStatus; + let tendermintNetInfo; + if (config.options.network !== 'testnet') { + // curl fails if tendermint has not started yet because abci is waiting for core to sync + if (mnsyncStatus.IsSynced === true) { + tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); + tendermintNetInfo = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); + } + } + + // Build table + if (config.options.network !== 'testnet') { + rows.push(['Tenderdash Version', tendermintStatus.result.node_info.version]); + rows.push(['Network', tendermintStatus.result.node_info.network]); + rows.push(['Status', '-']); + rows.push(['Block height', tendermintStatus.result.sync_info.latest_block_height]); + rows.push(['Remote block height', '-']); + rows.push(['Peer count', tendermintNetInfo.result.n_peers]); + rows.push(['App hash', tendermintStatus.result.sync_info.latest_app_hash]); + rows.push(['HTTP service', '-']); + rows.push(['HTTP port', '-']); + rows.push(['gRPC service', '-']); + rows.push(['gRPC port', '-']); + rows.push(['P2P service', '-']); + rows.push(['P2P port', '-']); + rows.push(['RPC service', '-']); + } + const output = table(rows, { singleLine: true }); + + // eslint-disable-next-line no-console + console.log(output); + } +} + +CoreStatusCommand.description = 'Show status overview'; + +CoreStatusCommand.flags = { + ...BaseCommand.flags, +}; + +module.exports = CoreStatusCommand; From 7019987122c1c749234225858c6715b1f621d49b Mon Sep 17 00:00:00 2001 From: Leon White Date: Thu, 19 Nov 2020 13:12:19 -0800 Subject: [PATCH 25/44] feat: add remaining core status output --- src/commands/status/core.js | 40 ++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index 3a2edf05..b7f5b82e 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -4,6 +4,8 @@ const fetch = require('node-fetch'); const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); +const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPresentError'); + class CoreStatusCommand extends BaseCommand { /** * @param {Object} args @@ -33,14 +35,23 @@ class CoreStatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); - // Network data + let insightUrl; + switch (config.options.network) { + case 'evonet': insightUrl = 'http://insight.evonet.networks.dash.org:3001/insight-api'; break; + case 'testnet': insightUrl = 'https://testnet-insight.dashevo.org/insight-api'; break; + case 'mainnet': insightUrl = 'https://insight.dash.org/insight-api'; break; + default: insightUrl = 'https://insight.dash.org/insight-api'; + } + + // Collect data const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; const networkInfo = (await coreService.getRpcClient().getNetworkInfo()).result; const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; const peerInfo = (await coreService.getRpcClient().getPeerInfo()).result; const latestVersion = JSON.parse(await fetch('https://api.github.com/repos/dashpay/dash/releases/latest').then((res) => res.text())); const corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); - const SentinelVersion = (await dockerCompose.execCommand( + const insightBlockHeight = JSON.parse(await fetch(`${insightUrl}/status`).then((res) => res.text())); + const sentinelVersion = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', 'python bin/sentinel.py -v', @@ -51,11 +62,30 @@ class CoreStatusCommand extends BaseCommand { 'python bin/sentinel.py', )).out.split('\n')[0]; + // Determine status + let status; + try { + ({ + State: { + Status: status, + }, + } = await dockerCompose.inspectService(config.toEnvs(), 'core')); + } catch (e) { + if (e instanceof ContainerIsNotPresentError) { + status = 'not started'; + } + } + if (status === 'running') { + if (mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { + status = `syncing ${(blockchainInfo.verificationprogress * 100).toFixed(2)}%`; + } + } + // Build table rows.push(['Version', networkInfo.subversion.replace(/\/|\(.*?\)/g, '')]); rows.push(['Latest version', latestVersion.tag_name]); rows.push(['Network', blockchainInfo.chain]); - rows.push(['Status', '-']); + rows.push(['Status', status]); rows.push(['Sync asset', mnsyncStatus.AssetName]); rows.push(['Peer count', peerInfo.length]); rows.push(['P2P service', `${config.options.externalIp}:${config.options.core.p2p.port}`]); @@ -63,9 +93,9 @@ class CoreStatusCommand extends BaseCommand { rows.push(['RPC service', `127.0.0.1:${config.options.core.rpc.port}`]); rows.push(['Header height', blockchainInfo.headers]); rows.push(['Block height', blockchainInfo.blocks]); - rows.push(['Remote block height', '-']); + rows.push(['Remote block height', insightBlockHeight.info.blocks]); rows.push(['Difficulty', blockchainInfo.difficulty]); - rows.push(['Sentinel version', SentinelVersion]); + rows.push(['Sentinel version', sentinelVersion]); rows.push(['Sentinel status', sentinelState]); const output = table(rows, { singleLine: true }); From 999806db2e727055de2d3707085ba4d83c74f853 Mon Sep 17 00:00:00 2001 From: Leon White Date: Thu, 19 Nov 2020 15:06:11 -0800 Subject: [PATCH 26/44] fix: tidy output for index, masternode & platform --- src/commands/status/index.js | 86 +++++++++++++++---------------- src/commands/status/masternode.js | 85 +++++++++--------------------- src/commands/status/platform.js | 66 +++++++++++++++++------- 3 files changed, 113 insertions(+), 124 deletions(-) diff --git a/src/commands/status/index.js b/src/commands/status/index.js index e201dd52..43b7ec3d 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -24,37 +24,6 @@ class StatusCommand extends BaseCommand { ) { const rows = []; - const serviceHumanNames = { - core: 'Core Status', - }; - - if (config.options.network !== 'testnet') { - Object.assign(serviceHumanNames, { - drive_tendermint: 'Tenderdash Status', - }); - } - - for (const [serviceName, serviceDescription] of Object.entries(serviceHumanNames)) { - let status; - - try { - ({ - State: { - Status: status, - }, - } = await dockerCompose.inspectService(config.toEnvs(), serviceName)); - } catch (e) { - if (e instanceof ContainerIsNotPresentError) { - status = 'not started'; - } - } - - rows.push([ - serviceDescription, - status, - ]); - } - const coreService = new CoreService( createRpcClient( { @@ -66,16 +35,10 @@ class StatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); - // Core status + // Collect data const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - - // Network data - const networkStatus = (await coreService.getRpcClient().getNetworkInfo()).result; - - // Network data - const blockchainStatus = (await coreService.getRpcClient().getBlockchainInfo()).result; - - // Masternode data + const networkInfo = (await coreService.getRpcClient().getNetworkInfo()).result; + const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; // Platform status @@ -87,14 +50,49 @@ class StatusCommand extends BaseCommand { } } + // Determine status + let coreStatus; + try { + ({ + State: { + Status: coreStatus, + }, + } = await dockerCompose.inspectService(config.toEnvs(), 'core')); + } catch (e) { + if (e instanceof ContainerIsNotPresentError) { + coreStatus = 'not started'; + } + } + if (coreStatus === 'running') { + if (mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { + coreStatus = `syncing ${(blockchainInfo.verificationprogress * 100).toFixed(2)}%`; + } + } + + let platformStatus; + try { + ({ + State: { + Status: platformStatus, + }, + } = await dockerCompose.inspectService(config.toEnvs(), 'drive_tendermint')); + } catch (e) { + if (e instanceof ContainerIsNotPresentError) { + platformStatus = 'not started'; + } + } + if (platformStatus === 'running' && tendermintStatus.result.sync_info.catching_up === true) { + platformStatus = 'syncing'; + } + // Build table - rows.push(['Network', blockchainStatus.chain]); + rows.push(['Network', blockchainInfo.chain]); rows.push(['Masternode Status', masternodeStatus.status]); - rows.push(['Core Version', networkStatus.subversion.replace(/\/|\(.*?\)/g, '')]); - rows.push(['Core Status', mnsyncStatus.AssetName]); + rows.push(['Core Version', networkInfo.subversion.replace(/\/|\(.*?\)/g, '')]); + rows.push(['Core Status', coreStatus]); if (config.options.network !== 'testnet') { rows.push(['Platform Version', tendermintStatus.result.node_info.version]); - rows.push(['Platform Status', '-']); + rows.push(['Platform Status', platformStatus]); } if (masternodeStatus.state === 'READY') { rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 16c9086e..685fc2a0 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -1,9 +1,10 @@ const { table } = require('table'); -const fetch = require('node-fetch'); const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); +const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPresentError'); + class MasternodeStatusCommand extends BaseCommand { /** * @param {Object} args @@ -33,79 +34,43 @@ class MasternodeStatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); - // Version - const dashdVersion = (await dockerCompose.execCommand( - config.toEnvs(), - 'core', - 'dashd --version', - )).out.split('\n')[0]; - - // Sync status + // Collect data const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - - // Header and block count const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; - - // Masternode data const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; - // Sentinel + // Determine status + let status; + try { + ({ + State: { + Status: status, + }, + } = await dockerCompose.inspectService(config.toEnvs(), 'core')); + } catch (e) { + if (e instanceof ContainerIsNotPresentError) { + status = 'not started'; + } + } + if (status === 'running') { + if (mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { + status = `syncing ${(blockchainInfo.verificationprogress * 100).toFixed(2)}%`; + } + } + const sentinelState = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', 'python bin/sentinel.py', )).out.split('\n')[0]; - let tendermintVersion; - let tendermintStatus; - let tendermintPortNum; - let tendermintPortState; - - if (config.options.network !== 'testnet') { - // Tendermint - tendermintVersion = (await dockerCompose.execCommand( - config.toEnvs(), - 'drive_tendermint', - 'tendermint version', - )).out.split('\n')[0]; - - // curl fails if tendermint has not started yet because abci is waiting for core to sync - if (mnsyncStatus.IsSynced === true) { - tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); - } - } - - // Port check - const corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); - - if (config.options.network !== 'testnet') { - tendermintPortNum = config.get('platform.drive.tendermint.p2p.port'); - tendermintPortState = await fetch(`https://mnowatch.org/${tendermintPortNum}/`).then((res) => res.text()); - } - // Build table - rows.push(['Dashd Version', dashdVersion]); - rows.push(['Core Sync', mnsyncStatus.AssetName]); - rows.push(['Core Port', `${config.options.core.p2p.port} ${corePortState}`]); - rows.push(['Core Headers', blockchainInfo.headers]); - rows.push(['Core Blocks', blockchainInfo.blocks]); - rows.push(['Core Sync', mnsyncStatus.IsSynced]); - rows.push(['Masternode State', masternodeStatus.state]); - rows.push(['Masternode Status', masternodeStatus.status]); + rows.push(['Masternode status', status]); + rows.push(['Sentinel status', sentinelState]); if (masternodeStatus.state === 'READY') { rows.push(['ProTx Hash', masternodeStatus.proTxHash]); - rows.push(['Service', masternodeStatus.dmnState.service]); rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); - } - rows.push(['Sentinel Status', (sentinelState !== '' ? sentinelState : 'No errors')]); - if (config.options.network !== 'testnet') { - rows.push(['Tendermint Version', tendermintVersion]); - rows.push(['Tendermint Port', `${tendermintPortNum} ${tendermintPortState}`]); - if (mnsyncStatus.IsSynced === true) { - rows.push(['Tendermint Blocks', tendermintStatus.result.sync_info.latest_block_height]); - rows.push(['Tendermint Sync', !tendermintStatus.result.sync_info.catching_up]); - rows.push(['Tendermint App Hash', tendermintStatus.result.sync_info.latest_app_hash]); - } + rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); } const output = table(rows, { singleLine: true }); diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index 91d29d38..161ee970 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -4,6 +4,8 @@ const fetch = require('node-fetch'); const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); +const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPresentError'); + class CoreStatusCommand extends BaseCommand { /** * @param {Object} args @@ -20,6 +22,13 @@ class CoreStatusCommand extends BaseCommand { createRpcClient, config, ) { + + if (config.options.network === 'testnet') { + // eslint-disable-next-line no-console + console.log('Platform is not supported on testnet yet!'); + this.exit(); + } + const rows = []; const coreService = new CoreService( @@ -33,37 +42,54 @@ class CoreStatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); - // Core status + // Collect data const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - - // Platform status let tendermintStatus; let tendermintNetInfo; if (config.options.network !== 'testnet') { // curl fails if tendermint has not started yet because abci is waiting for core to sync if (mnsyncStatus.IsSynced === true) { tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); - tendermintNetInfo = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); + tendermintNetInfo = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`).then((res) => res.text())); } } - // Build table - if (config.options.network !== 'testnet') { - rows.push(['Tenderdash Version', tendermintStatus.result.node_info.version]); - rows.push(['Network', tendermintStatus.result.node_info.network]); - rows.push(['Status', '-']); - rows.push(['Block height', tendermintStatus.result.sync_info.latest_block_height]); - rows.push(['Remote block height', '-']); - rows.push(['Peer count', tendermintNetInfo.result.n_peers]); - rows.push(['App hash', tendermintStatus.result.sync_info.latest_app_hash]); - rows.push(['HTTP service', '-']); - rows.push(['HTTP port', '-']); - rows.push(['gRPC service', '-']); - rows.push(['gRPC port', '-']); - rows.push(['P2P service', '-']); - rows.push(['P2P port', '-']); - rows.push(['RPC service', '-']); + const httpPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`).then((res) => res.text()); + const gRpcPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.grpc.port}/`).then((res) => res.text()); + const p2pPortState = await fetch(`https://mnowatch.org/${config.options.platform.drive.tendermint.p2p.port}/`).then((res) => res.text()); + + // Determine status + let status; + try { + ({ + State: { + Status: status, + }, + } = await dockerCompose.inspectService(config.toEnvs(), 'drive_tendermint')); + } catch (e) { + if (e instanceof ContainerIsNotPresentError) { + status = 'not started'; + } } + if (status === 'running' && tendermintStatus.result.sync_info.catching_up === true) { + status = 'syncing'; + } + + // Build table + rows.push(['Tenderdash Version', tendermintStatus.result.node_info.version]); + rows.push(['Network', tendermintStatus.result.node_info.network]); + rows.push(['Status', status]); + rows.push(['Block height', tendermintStatus.result.sync_info.latest_block_height]); + rows.push(['Remote block height', '-']); + rows.push(['Peer count', tendermintNetInfo.result.n_peers]); + rows.push(['App hash', tendermintStatus.result.sync_info.latest_app_hash]); + rows.push(['HTTP service', `${config.options.externalIp}:${config.options.platform.dapi.nginx.http.port}`]); + rows.push(['HTTP port', `${config.options.platform.dapi.nginx.http.port} ${httpPortState}`]); + rows.push(['gRPC service', `${config.options.externalIp}:${config.options.platform.dapi.nginx.grpc.port}`]); + rows.push(['gRPC port', `${config.options.platform.dapi.nginx.grpc.port} ${gRpcPortState}`]); + rows.push(['P2P service', `${config.options.externalIp}:${config.options.platform.drive.tendermint.p2p.port}`]); + rows.push(['P2P port', `${config.options.platform.drive.tendermint.p2p.port} ${p2pPortState}`]); + rows.push(['RPC service', `127.0.0.1:${config.options.platform.drive.tendermint.rpc.port}`]); const output = table(rows, { singleLine: true }); // eslint-disable-next-line no-console From 754bb97d8cae2ec237b327081b18e9ed3c90ab9b Mon Sep 17 00:00:00 2001 From: Leon White Date: Fri, 20 Nov 2020 00:01:35 -0800 Subject: [PATCH 27/44] feat: implement queue position --- src/commands/status/index.js | 11 +++++++++++ src/commands/status/masternode.js | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/commands/status/index.js b/src/commands/status/index.js index 43b7ec3d..b8020db1 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -40,6 +40,7 @@ class StatusCommand extends BaseCommand { const networkInfo = (await coreService.getRpcClient().getNetworkInfo()).result; const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; + const masternodeCount = (await coreService.getRpcClient().masternode('count')).result; // Platform status let tendermintStatus; @@ -85,6 +86,15 @@ class StatusCommand extends BaseCommand { platformStatus = 'syncing'; } + let paymentQueuePosition; + if (masternodeStatus.state === 'READY') { + paymentQueuePosition = (masternodeStatus.dmnState.lastPaidHeight === 0 + ? masternodeStatus.dmnState.registeredHeight + : masternodeStatus.dmnState.lastPaidHeight) + + masternodeCount.enabled + - blockchainInfo.blocks; + } + // Build table rows.push(['Network', blockchainInfo.chain]); rows.push(['Masternode Status', masternodeStatus.status]); @@ -97,6 +107,7 @@ class StatusCommand extends BaseCommand { if (masternodeStatus.state === 'READY') { rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); + rows.push(['Payment queue', `${paymentQueuePosition}/${masternodeCount.enabled}`]); } const output = table(rows, { singleLine: true }); diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 685fc2a0..a00db2e1 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -38,6 +38,7 @@ class MasternodeStatusCommand extends BaseCommand { const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; + const masternodeCount = (await coreService.getRpcClient().masternode('count')).result; // Determine status let status; @@ -58,6 +59,15 @@ class MasternodeStatusCommand extends BaseCommand { } } + let paymentQueuePosition; + if (masternodeStatus.state === 'READY') { + paymentQueuePosition = (masternodeStatus.dmnState.lastPaidHeight === 0 + ? masternodeStatus.dmnState.registeredHeight + : masternodeStatus.dmnState.lastPaidHeight) + + masternodeCount.enabled + - blockchainInfo.blocks; + } + const sentinelState = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', @@ -71,6 +81,7 @@ class MasternodeStatusCommand extends BaseCommand { rows.push(['ProTx Hash', masternodeStatus.proTxHash]); rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); + rows.push(['Payment queue', `${paymentQueuePosition}/${masternodeCount.enabled}`]); } const output = table(rows, { singleLine: true }); From 3fea150d3f92848607657a0d508454bec50e502e Mon Sep 17 00:00:00 2001 From: Leon White Date: Fri, 20 Nov 2020 12:11:51 -0800 Subject: [PATCH 28/44] fix: queue and sentinel output --- src/commands/status/core.js | 2 +- src/commands/status/index.js | 18 +++++++++++++----- src/commands/status/masternode.js | 20 ++++++++++++++------ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index b7f5b82e..d1602eb7 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -96,7 +96,7 @@ class CoreStatusCommand extends BaseCommand { rows.push(['Remote block height', insightBlockHeight.info.blocks]); rows.push(['Difficulty', blockchainInfo.difficulty]); rows.push(['Sentinel version', sentinelVersion]); - rows.push(['Sentinel status', sentinelState]); + rows.push(['Sentinel status', (sentinelState !== '' ? sentinelState : 'No errors')]); const output = table(rows, { singleLine: true }); diff --git a/src/commands/status/index.js b/src/commands/status/index.js index b8020db1..86902b58 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -88,11 +88,19 @@ class StatusCommand extends BaseCommand { let paymentQueuePosition; if (masternodeStatus.state === 'READY') { - paymentQueuePosition = (masternodeStatus.dmnState.lastPaidHeight === 0 - ? masternodeStatus.dmnState.registeredHeight - : masternodeStatus.dmnState.lastPaidHeight) - + masternodeCount.enabled - - blockchainInfo.blocks; + if (masternodeStatus.dmnState.PoSeRevivedHeight > 0) { + paymentQueuePosition = masternodeStatus.dmnState.PoSeRevivedHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } else if (masternodeStatus.dmnState.lastPaidHeight === 0) { + paymentQueuePosition = masternodeStatus.dmnState.registeredHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } else { + paymentQueuePosition = masternodeStatus.dmnState.lastPaidHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } } // Build table diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index a00db2e1..fcbb3c04 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -61,11 +61,19 @@ class MasternodeStatusCommand extends BaseCommand { let paymentQueuePosition; if (masternodeStatus.state === 'READY') { - paymentQueuePosition = (masternodeStatus.dmnState.lastPaidHeight === 0 - ? masternodeStatus.dmnState.registeredHeight - : masternodeStatus.dmnState.lastPaidHeight) - + masternodeCount.enabled - - blockchainInfo.blocks; + if (masternodeStatus.dmnState.PoSeRevivedHeight > 0) { + paymentQueuePosition = masternodeStatus.dmnState.PoSeRevivedHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } else if (masternodeStatus.dmnState.lastPaidHeight === 0) { + paymentQueuePosition = masternodeStatus.dmnState.registeredHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } else { + paymentQueuePosition = masternodeStatus.dmnState.lastPaidHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } } const sentinelState = (await dockerCompose.execCommand( @@ -76,7 +84,7 @@ class MasternodeStatusCommand extends BaseCommand { // Build table rows.push(['Masternode status', status]); - rows.push(['Sentinel status', sentinelState]); + rows.push(['Sentinel status', (sentinelState !== '' ? sentinelState : 'No errors')]); if (masternodeStatus.state === 'READY') { rows.push(['ProTx Hash', masternodeStatus.proTxHash]); rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); From ffc62d666ac38cea00e30349a755008b38ec9a5d Mon Sep 17 00:00:00 2001 From: Leon White Date: Fri, 20 Nov 2020 12:15:57 -0800 Subject: [PATCH 29/44] fix: linting --- src/commands/status/platform.js | 1 - src/commands/status/services.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index 161ee970..b29028ea 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -22,7 +22,6 @@ class CoreStatusCommand extends BaseCommand { createRpcClient, config, ) { - if (config.options.network === 'testnet') { // eslint-disable-next-line no-console console.log('Platform is not supported on testnet yet!'); diff --git a/src/commands/status/services.js b/src/commands/status/services.js index 6dde9123..88b5ce05 100644 --- a/src/commands/status/services.js +++ b/src/commands/status/services.js @@ -54,7 +54,7 @@ class ServicesStatusCommand extends BaseCommand { }, Config: { Image: image, - } + }, } = await dockerCompose.inspectService(config.toEnvs(), serviceName)); } catch (e) { if (e instanceof ContainerIsNotPresentError) { From 4818d1c5ce98658a193082f8e28460972f669680 Mon Sep 17 00:00:00 2001 From: Leon White Date: Fri, 20 Nov 2020 15:02:05 -0800 Subject: [PATCH 30/44] fix: tenderdash sync progress & conditional checks --- src/commands/status/index.js | 63 +++++++++++++++++++------------ src/commands/status/masternode.js | 6 +++ src/commands/status/platform.js | 25 +++++++----- 3 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/commands/status/index.js b/src/commands/status/index.js index 86902b58..487dbad7 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -39,8 +39,12 @@ class StatusCommand extends BaseCommand { const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; const networkInfo = (await coreService.getRpcClient().getNetworkInfo()).result; const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; - const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; - const masternodeCount = (await coreService.getRpcClient().masternode('count')).result; + let masternodeStatus; + let masternodeCount; + if (config.options.core.masternode.enable === true) { + masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; + masternodeCount = (await coreService.getRpcClient().masternode('count')).result; + } // Platform status let tendermintStatus; @@ -50,6 +54,7 @@ class StatusCommand extends BaseCommand { tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); } } + const explorerBlockHeight = JSON.parse(await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text())); // Determine status let coreStatus; @@ -82,40 +87,50 @@ class StatusCommand extends BaseCommand { platformStatus = 'not started'; } } - if (platformStatus === 'running' && tendermintStatus.result.sync_info.catching_up === true) { - platformStatus = 'syncing'; + if (platformStatus === 'running' && mnsyncStatus.IsSynced === false) { + platformStatus = 'waiting for core sync'; + } else if (platformStatus === 'running' && tendermintStatus.result.sync_info.catching_up === true) { + platformStatus = `syncing ${((tendermintStatus.result.sync_info.latest_block_height + / explorerBlockHeight.result.sync_info.latest_block_height) + * 100).toFixed(2)}%`; } let paymentQueuePosition; - if (masternodeStatus.state === 'READY') { - if (masternodeStatus.dmnState.PoSeRevivedHeight > 0) { - paymentQueuePosition = masternodeStatus.dmnState.PoSeRevivedHeight - + masternodeCount.enabled - - blockchainInfo.blocks; - } else if (masternodeStatus.dmnState.lastPaidHeight === 0) { - paymentQueuePosition = masternodeStatus.dmnState.registeredHeight - + masternodeCount.enabled - - blockchainInfo.blocks; - } else { - paymentQueuePosition = masternodeStatus.dmnState.lastPaidHeight - + masternodeCount.enabled - - blockchainInfo.blocks; + if (config.options.core.masternode.enable === true) { + if (masternodeStatus.state === 'READY') { + if (masternodeStatus.dmnState.PoSeRevivedHeight > 0) { + paymentQueuePosition = masternodeStatus.dmnState.PoSeRevivedHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } else if (masternodeStatus.dmnState.lastPaidHeight === 0) { + paymentQueuePosition = masternodeStatus.dmnState.registeredHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } else { + paymentQueuePosition = masternodeStatus.dmnState.lastPaidHeight + + masternodeCount.enabled + - blockchainInfo.blocks; + } } } // Build table rows.push(['Network', blockchainInfo.chain]); - rows.push(['Masternode Status', masternodeStatus.status]); + if (config.options.core.masternode.enable === true) { + rows.push(['Masternode Status', masternodeStatus.status]); + } rows.push(['Core Version', networkInfo.subversion.replace(/\/|\(.*?\)/g, '')]); rows.push(['Core Status', coreStatus]); - if (config.options.network !== 'testnet') { + if (config.options.network !== 'testnet' && mnsyncStatus.IsSynced === true) { rows.push(['Platform Version', tendermintStatus.result.node_info.version]); - rows.push(['Platform Status', platformStatus]); } - if (masternodeStatus.state === 'READY') { - rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); - rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); - rows.push(['Payment queue', `${paymentQueuePosition}/${masternodeCount.enabled}`]); + rows.push(['Platform Status', platformStatus]); + if (config.options.core.masternode.enable === true) { + if (masternodeStatus.state === 'READY') { + rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); + rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); + rows.push(['Payment queue', `${paymentQueuePosition}/${masternodeCount.enabled}`]); + } } const output = table(rows, { singleLine: true }); diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index fcbb3c04..267b2c9f 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -34,6 +34,12 @@ class MasternodeStatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); + if (config.options.core.masternode.enable === false) { + // eslint-disable-next-line no-console + console.log('This is not a masternode!'); + this.exit(); + } + // Collect data const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index b29028ea..a7ad07a4 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -43,20 +43,23 @@ class CoreStatusCommand extends BaseCommand { // Collect data const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - let tendermintStatus; - let tendermintNetInfo; - if (config.options.network !== 'testnet') { - // curl fails if tendermint has not started yet because abci is waiting for core to sync - if (mnsyncStatus.IsSynced === true) { - tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); - tendermintNetInfo = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`).then((res) => res.text())); - } + + // curl fails if tendermint has not started yet because abci is waiting for core to sync + if (mnsyncStatus.IsSynced === false) { + // eslint-disable-next-line no-console + console.log('Platform status is not available until core sync is complete!'); + this.exit(); } + const tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); + const tendermintNetInfo = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`).then((res) => res.text())); + const httpPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`).then((res) => res.text()); const gRpcPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.grpc.port}/`).then((res) => res.text()); const p2pPortState = await fetch(`https://mnowatch.org/${config.options.platform.drive.tendermint.p2p.port}/`).then((res) => res.text()); + const explorerBlockHeight = JSON.parse(await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text())); + // Determine status let status; try { @@ -71,7 +74,9 @@ class CoreStatusCommand extends BaseCommand { } } if (status === 'running' && tendermintStatus.result.sync_info.catching_up === true) { - status = 'syncing'; + status = `syncing ${((tendermintStatus.result.sync_info.latest_block_height + / explorerBlockHeight.result.sync_info.latest_block_height) + * 100).toFixed(2)}%`; } // Build table @@ -79,7 +84,7 @@ class CoreStatusCommand extends BaseCommand { rows.push(['Network', tendermintStatus.result.node_info.network]); rows.push(['Status', status]); rows.push(['Block height', tendermintStatus.result.sync_info.latest_block_height]); - rows.push(['Remote block height', '-']); + rows.push(['Remote block height', explorerBlockHeight.result.sync_info.latest_block_height]); rows.push(['Peer count', tendermintNetInfo.result.n_peers]); rows.push(['App hash', tendermintStatus.result.sync_info.latest_app_hash]); rows.push(['HTTP service', `${config.options.externalIp}:${config.options.platform.dapi.nginx.http.port}`]); From e7867be7554bf9d932160b9447406d21df9398a4 Mon Sep 17 00:00:00 2001 From: Leon White Date: Fri, 20 Nov 2020 20:55:08 -0800 Subject: [PATCH 31/44] feat: apply colors --- src/commands/status/core.js | 47 +++++++++++++++++++++++++++---- src/commands/status/index.js | 24 ++++++++++++++-- src/commands/status/masternode.js | 27 ++++++++++++++++-- src/commands/status/platform.js | 42 ++++++++++++++++++++++++--- 4 files changed, 126 insertions(+), 14 deletions(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index d1602eb7..0acc64c8 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -1,5 +1,6 @@ const { table } = require('table'); const fetch = require('node-fetch'); +const chalk = require('chalk'); const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); @@ -49,14 +50,15 @@ class CoreStatusCommand extends BaseCommand { const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; const peerInfo = (await coreService.getRpcClient().getPeerInfo()).result; const latestVersion = JSON.parse(await fetch('https://api.github.com/repos/dashpay/dash/releases/latest').then((res) => res.text())); - const corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); const insightBlockHeight = JSON.parse(await fetch(`${insightUrl}/status`).then((res) => res.text())); + let corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); + let coreVersion = networkInfo.subversion.replace(/\/|\(.*?\)/g, ''); const sentinelVersion = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', 'python bin/sentinel.py -v', )).out.split('\n')[0]; - const sentinelState = (await dockerCompose.execCommand( + let sentinelState = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', 'python bin/sentinel.py', @@ -81,8 +83,43 @@ class CoreStatusCommand extends BaseCommand { } } + // Apply colors + if (status === 'running') { + status = chalk.green(status); + } else if (status.includes('syncing')) { + status = chalk.yellow(status); + } else { + status = chalk.red(status); + } + + if (coreVersion.substring(coreVersion.indexOf(':') + 1) === latestVersion.tag_name.substring(1)) { + coreVersion = chalk.green(coreVersion); + } else { + coreVersion = chalk.red(coreVersion); + } + + if (corePortState === 'OPEN') { + corePortState = chalk.green(corePortState); + } else { + corePortState = chalk.red(corePortState); + } + + let blocks; + if (blockchainInfo.blocks === blockchainInfo.headers + || blockchainInfo.blocks >= insightBlockHeight.info.blocks) { + blocks = chalk.green(blockchainInfo.blocks); + } else { + blocks = chalk.red(blockchainInfo.blocks); + } + + if (sentinelState === '') { + sentinelState = chalk.green('No errors'); + } else { + sentinelState = chalk.red(sentinelState); + } + // Build table - rows.push(['Version', networkInfo.subversion.replace(/\/|\(.*?\)/g, '')]); + rows.push(['Version', coreVersion]); rows.push(['Latest version', latestVersion.tag_name]); rows.push(['Network', blockchainInfo.chain]); rows.push(['Status', status]); @@ -91,12 +128,12 @@ class CoreStatusCommand extends BaseCommand { rows.push(['P2P service', `${config.options.externalIp}:${config.options.core.p2p.port}`]); rows.push(['P2P port', `${config.options.core.p2p.port} ${corePortState}`]); rows.push(['RPC service', `127.0.0.1:${config.options.core.rpc.port}`]); + rows.push(['Block height', blocks]); rows.push(['Header height', blockchainInfo.headers]); - rows.push(['Block height', blockchainInfo.blocks]); rows.push(['Remote block height', insightBlockHeight.info.blocks]); rows.push(['Difficulty', blockchainInfo.difficulty]); rows.push(['Sentinel version', sentinelVersion]); - rows.push(['Sentinel status', (sentinelState !== '' ? sentinelState : 'No errors')]); + rows.push(['Sentinel status', (sentinelState)]); const output = table(rows, { singleLine: true }); diff --git a/src/commands/status/index.js b/src/commands/status/index.js index 487dbad7..14113398 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -1,5 +1,6 @@ const { table } = require('table'); const fetch = require('node-fetch'); +const chalk = require('chalk'); const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPresentError'); @@ -114,13 +115,30 @@ class StatusCommand extends BaseCommand { } } + // Apply colors + if (coreStatus === 'running') { + coreStatus = chalk.keyword('green')(coreStatus); + } else if (coreStatus.includes('syncing')) { + coreStatus = chalk.keyword('yellow')(coreStatus); + } else { + coreStatus = chalk.keyword('red')(coreStatus); + } + + if (platformStatus === 'running') { + platformStatus = chalk.keyword('green')(platformStatus); + } else if (platformStatus.includes('syncing')) { + platformStatus = chalk.keyword('yellow')(platformStatus); + } else { + platformStatus = chalk.keyword('red')(platformStatus); + } + // Build table rows.push(['Network', blockchainInfo.chain]); - if (config.options.core.masternode.enable === true) { - rows.push(['Masternode Status', masternodeStatus.status]); - } rows.push(['Core Version', networkInfo.subversion.replace(/\/|\(.*?\)/g, '')]); rows.push(['Core Status', coreStatus]); + if (config.options.core.masternode.enable === true) { + rows.push(['Masternode Status', chalk.keyword(masternodeStatus.status === 'Ready' ? 'green' : 'red')(masternodeStatus.status)]); + } if (config.options.network !== 'testnet' && mnsyncStatus.IsSynced === true) { rows.push(['Platform Version', tendermintStatus.result.node_info.version]); } diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 267b2c9f..90c2ecd9 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -1,4 +1,5 @@ const { table } = require('table'); +const chalk = require('chalk'); const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); @@ -82,18 +83,40 @@ class MasternodeStatusCommand extends BaseCommand { } } - const sentinelState = (await dockerCompose.execCommand( + let sentinelState = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', 'python bin/sentinel.py', )).out.split('\n')[0]; + // Apply colors + if (status === 'running') { + status = chalk.green(status); + } else if (status.includes('syncing')) { + status = chalk.yellow(status); + } else { + status = chalk.red(status); + } + + if (sentinelState === '') { + sentinelState = chalk.green('No errors'); + } else { + sentinelState = chalk.red(sentinelState); + } + + let PoSePenalty; + if (masternodeStatus.dmnState.PoSePenalty === 0) { + PoSePenalty = chalk.green(masternodeStatus.dmnState.PoSePenalty); + } else { + PoSePenalty = chalk.red(masternodeStatus.dmnState.PoSePenalty); + } + // Build table rows.push(['Masternode status', status]); rows.push(['Sentinel status', (sentinelState !== '' ? sentinelState : 'No errors')]); if (masternodeStatus.state === 'READY') { rows.push(['ProTx Hash', masternodeStatus.proTxHash]); - rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); + rows.push(['PoSe Penalty', PoSePenalty]); rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); rows.push(['Payment queue', `${paymentQueuePosition}/${masternodeCount.enabled}`]); } diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index a7ad07a4..fb2b79dc 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -1,5 +1,6 @@ const { table } = require('table'); const fetch = require('node-fetch'); +const chalk = require('chalk'); const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); @@ -54,9 +55,9 @@ class CoreStatusCommand extends BaseCommand { const tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); const tendermintNetInfo = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`).then((res) => res.text())); - const httpPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`).then((res) => res.text()); - const gRpcPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.grpc.port}/`).then((res) => res.text()); - const p2pPortState = await fetch(`https://mnowatch.org/${config.options.platform.drive.tendermint.p2p.port}/`).then((res) => res.text()); + let httpPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`).then((res) => res.text()); + let gRpcPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.grpc.port}/`).then((res) => res.text()); + let p2pPortState = await fetch(`https://mnowatch.org/${config.options.platform.drive.tendermint.p2p.port}/`).then((res) => res.text()); const explorerBlockHeight = JSON.parse(await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text())); @@ -79,11 +80,44 @@ class CoreStatusCommand extends BaseCommand { * 100).toFixed(2)}%`; } + // Apply colors + if (status === 'running') { + status = chalk.green(status); + } else if (status.includes('syncing')) { + status = chalk.yellow(status); + } else { + status = chalk.red(status); + } + + let blocks; + if (tendermintStatus.result.sync_info.latest_block_height + >= explorerBlockHeight.result.sync_info.latest_block_height) { + blocks = chalk.green(tendermintStatus.result.sync_info.latest_block_height); + } else { + blocks = chalk.red(tendermintStatus.result.sync_info.latest_block_height); + } + + if (httpPortState === 'OPEN') { + httpPortState = chalk.green(httpPortState); + } else { + httpPortState = chalk.red(httpPortState); + } + if (gRpcPortState === 'OPEN') { + gRpcPortState = chalk.green(gRpcPortState); + } else { + gRpcPortState = chalk.red(gRpcPortState); + } + if (p2pPortState === 'OPEN') { + p2pPortState = chalk.green(p2pPortState); + } else { + p2pPortState = chalk.red(p2pPortState); + } + // Build table rows.push(['Tenderdash Version', tendermintStatus.result.node_info.version]); rows.push(['Network', tendermintStatus.result.node_info.network]); rows.push(['Status', status]); - rows.push(['Block height', tendermintStatus.result.sync_info.latest_block_height]); + rows.push(['Block height', blocks]); rows.push(['Remote block height', explorerBlockHeight.result.sync_info.latest_block_height]); rows.push(['Peer count', tendermintNetInfo.result.n_peers]); rows.push(['App hash', tendermintStatus.result.sync_info.latest_app_hash]); From de6736e0317bb988906007517ccb5e793b5acc61 Mon Sep 17 00:00:00 2001 From: Leon White Date: Fri, 20 Nov 2020 21:01:34 -0800 Subject: [PATCH 32/44] refactor: use object for insight urls --- src/commands/status/core.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index 0acc64c8..3b7f0f60 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -36,13 +36,11 @@ class CoreStatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); - let insightUrl; - switch (config.options.network) { - case 'evonet': insightUrl = 'http://insight.evonet.networks.dash.org:3001/insight-api'; break; - case 'testnet': insightUrl = 'https://testnet-insight.dashevo.org/insight-api'; break; - case 'mainnet': insightUrl = 'https://insight.dash.org/insight-api'; break; - default: insightUrl = 'https://insight.dash.org/insight-api'; - } + const insightURLs = { + evonet: 'http://insight.evonet.networks.dash.org:3001/insight-api', + testnet: 'https://testnet-insight.dashevo.org/insight-api', + mainnet: 'https://insight.dash.org/insight-api', + }; // Collect data const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; @@ -50,7 +48,7 @@ class CoreStatusCommand extends BaseCommand { const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; const peerInfo = (await coreService.getRpcClient().getPeerInfo()).result; const latestVersion = JSON.parse(await fetch('https://api.github.com/repos/dashpay/dash/releases/latest').then((res) => res.text())); - const insightBlockHeight = JSON.parse(await fetch(`${insightUrl}/status`).then((res) => res.text())); + const insightBlockHeight = JSON.parse(await fetch(`${insightURLs[config.options.network]}/status`).then((res) => res.text())); let corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); let coreVersion = networkInfo.subversion.replace(/\/|\(.*?\)/g, ''); const sentinelVersion = (await dockerCompose.execCommand( From 50f54fa609991346fe7fa59364001b90bb04ffc8 Mon Sep 17 00:00:00 2001 From: Leon White Date: Sat, 21 Nov 2020 14:36:13 -0800 Subject: [PATCH 33/44] docs: update command descriptions --- src/commands/status/core.js | 2 +- src/commands/status/platform.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index 3b7f0f60..9939f65b 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -140,7 +140,7 @@ class CoreStatusCommand extends BaseCommand { } } -CoreStatusCommand.description = 'Show status overview'; +CoreStatusCommand.description = 'Show core status details'; CoreStatusCommand.flags = { ...BaseCommand.flags, diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index fb2b79dc..842de858 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -135,7 +135,7 @@ class CoreStatusCommand extends BaseCommand { } } -CoreStatusCommand.description = 'Show status overview'; +CoreStatusCommand.description = 'Show platform status details'; CoreStatusCommand.flags = { ...BaseCommand.flags, From f71c01065caeb3f6c4f61d5f9074b2d0668dc480 Mon Sep 17 00:00:00 2001 From: Leon White Date: Sun, 22 Nov 2020 12:55:34 -0800 Subject: [PATCH 34/44] refactor: use destructuring assignment --- src/commands/status/core.js | 14 ++++++++------ src/commands/status/index.js | 17 ++++++++++------- src/commands/status/masternode.js | 8 ++++---- src/commands/status/platform.js | 12 +++++++----- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index 9939f65b..5480b461 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -43,12 +43,14 @@ class CoreStatusCommand extends BaseCommand { }; // Collect data - const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; - const networkInfo = (await coreService.getRpcClient().getNetworkInfo()).result; - const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - const peerInfo = (await coreService.getRpcClient().getPeerInfo()).result; - const latestVersion = JSON.parse(await fetch('https://api.github.com/repos/dashpay/dash/releases/latest').then((res) => res.text())); - const insightBlockHeight = JSON.parse(await fetch(`${insightURLs[config.options.network]}/status`).then((res) => res.text())); + const { result: blockchainInfo } = await coreService.getRpcClient().getBlockchainInfo(); + const { result: networkInfo } = await coreService.getRpcClient().getNetworkInfo(); + const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); + const { result: peerInfo } = await coreService.getRpcClient().getPeerInfo(); + const latestVersionRes = await fetch('https://api.github.com/repos/dashpay/dash/releases/latest').then((res) => res.text()); + const latestVersion = JSON.parse(latestVersionRes); + const insightBlockHeightRes = await fetch(`${insightURLs[config.options.network]}/status`).then((res) => res.text()); + const insightBlockHeight = JSON.parse(insightBlockHeightRes); let corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); let coreVersion = networkInfo.subversion.replace(/\/|\(.*?\)/g, ''); const sentinelVersion = (await dockerCompose.execCommand( diff --git a/src/commands/status/index.js b/src/commands/status/index.js index 14113398..fae80bab 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -37,14 +37,15 @@ class StatusCommand extends BaseCommand { ); // Collect data - const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - const networkInfo = (await coreService.getRpcClient().getNetworkInfo()).result; - const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; + const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); + const { result: networkInfo } = await coreService.getRpcClient().getNetworkInfo(); + const { result: blockchainInfo } = await coreService.getRpcClient().getBlockchainInfo(); + let masternodeStatus; let masternodeCount; if (config.options.core.masternode.enable === true) { - masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; - masternodeCount = (await coreService.getRpcClient().masternode('count')).result; + ({ result: masternodeStatus } = await coreService.getRpcClient().masternode('status')); + ({ result: masternodeCount } = await coreService.getRpcClient().masternode('count')); } // Platform status @@ -52,10 +53,12 @@ class StatusCommand extends BaseCommand { if (config.options.network !== 'testnet') { // curl fails if tendermint has not started yet because abci is waiting for core to sync if (mnsyncStatus.IsSynced === true) { - tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); + const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text()); + tendermintStatus = JSON.parse(tendermintStatusRes); } } - const explorerBlockHeight = JSON.parse(await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text())); + const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text()); + const explorerBlockHeight = JSON.parse(explorerBlockHeightRes); // Determine status let coreStatus; diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 90c2ecd9..ddc9aa0f 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -42,10 +42,10 @@ class MasternodeStatusCommand extends BaseCommand { } // Collect data - const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; - const blockchainInfo = (await coreService.getRpcClient().getBlockchainInfo()).result; - const masternodeStatus = (await coreService.getRpcClient().masternode('status')).result; - const masternodeCount = (await coreService.getRpcClient().masternode('count')).result; + const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); + const { result: blockchainInfo } = await coreService.getRpcClient().getBlockchainInfo(); + const { result: masternodeStatus } = await coreService.getRpcClient().masternode('status'); + const { result: masternodeCount } = await coreService.getRpcClient().masternode('count'); // Determine status let status; diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index 842de858..a91894d0 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -43,7 +43,7 @@ class CoreStatusCommand extends BaseCommand { ); // Collect data - const mnsyncStatus = (await coreService.getRpcClient().mnsync('status')).result; + const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); // curl fails if tendermint has not started yet because abci is waiting for core to sync if (mnsyncStatus.IsSynced === false) { @@ -52,15 +52,17 @@ class CoreStatusCommand extends BaseCommand { this.exit(); } - const tendermintStatus = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text())); - const tendermintNetInfo = JSON.parse(await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`).then((res) => res.text())); + const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text()); + const tendermintStatus = JSON.parse(tendermintStatusRes); + const tendermintNetInfoRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`).then((res) => res.text()); + const tendermintNetInfo = JSON.parse(tendermintNetInfoRes); + const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text()); + const explorerBlockHeight = JSON.parse(explorerBlockHeightRes); let httpPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`).then((res) => res.text()); let gRpcPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.grpc.port}/`).then((res) => res.text()); let p2pPortState = await fetch(`https://mnowatch.org/${config.options.platform.drive.tendermint.p2p.port}/`).then((res) => res.text()); - const explorerBlockHeight = JSON.parse(await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text())); - // Determine status let status; try { From 130fd4d6b914b3ed944b04f5ccb4deb99fc872ed Mon Sep 17 00:00:00 2001 From: Leon White Date: Sun, 22 Nov 2020 13:29:09 -0800 Subject: [PATCH 35/44] feat: add time converter --- src/commands/status/index.js | 7 +++++-- src/commands/status/masternode.js | 7 +++++-- src/util/blocksToTime.js | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 src/util/blocksToTime.js diff --git a/src/commands/status/index.js b/src/commands/status/index.js index fae80bab..26c98799 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -6,6 +6,7 @@ const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPr const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); +const blocksToTime = require('../../util/blocksToTime'); class StatusCommand extends BaseCommand { /** @@ -149,8 +150,10 @@ class StatusCommand extends BaseCommand { if (config.options.core.masternode.enable === true) { if (masternodeStatus.state === 'READY') { rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); - rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); - rows.push(['Payment queue', `${paymentQueuePosition}/${masternodeCount.enabled}`]); + rows.push(['Last paid block', masternodeStatus.dmnState.lastPaidHeight]); + rows.push(['Last paid time', `${blocksToTime(blockchainInfo.blocks - masternodeStatus.dmnState.lastPaidHeight)} ago`]); + rows.push(['Payment queue position', `${paymentQueuePosition}/${masternodeCount.enabled}`]); + rows.push(['Next payment time', `in ${blocksToTime(paymentQueuePosition)}`]); } } diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index ddc9aa0f..3118d6c0 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -3,6 +3,7 @@ const chalk = require('chalk'); const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); +const blocksToTime = require('../../util/blocksToTime'); const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPresentError'); @@ -117,8 +118,10 @@ class MasternodeStatusCommand extends BaseCommand { if (masternodeStatus.state === 'READY') { rows.push(['ProTx Hash', masternodeStatus.proTxHash]); rows.push(['PoSe Penalty', PoSePenalty]); - rows.push(['Last paid', masternodeStatus.dmnState.lastPaidHeight]); - rows.push(['Payment queue', `${paymentQueuePosition}/${masternodeCount.enabled}`]); + rows.push(['Last paid block', masternodeStatus.dmnState.lastPaidHeight]); + rows.push(['Last paid time', `${blocksToTime(blockchainInfo.blocks - masternodeStatus.dmnState.lastPaidHeight)} ago`]); + rows.push(['Payment queue position', `${paymentQueuePosition}/${masternodeCount.enabled}`]); + rows.push(['Next payment time', `in ${blocksToTime(paymentQueuePosition)}`]); } const output = table(rows, { singleLine: true }); diff --git a/src/util/blocksToTime.js b/src/util/blocksToTime.js new file mode 100644 index 00000000..16f18a68 --- /dev/null +++ b/src/util/blocksToTime.js @@ -0,0 +1,15 @@ +function blocksToTime(blocks) { + let time; + const blockTime = 2.625; + const mins = blockTime * blocks; + if (mins > 2880) { + time = `${(mins / 60 / 24).toFixed(2)} days`; + } else if (mins > 300) { + time = `${(mins / 60).toFixed(2)} hours`; + } else { + time = `${(mins).toFixed(2)} minutes`; + } + return time; +} + +module.exports = blocksToTime; From 0779d768ba7ab9fe0d393853ce592e76b449aa36 Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 23 Nov 2020 12:19:25 -0800 Subject: [PATCH 36/44] refactor: don't mix await/then --- src/commands/status/core.js | 11 ++++++----- src/commands/status/index.js | 8 ++++---- src/commands/status/platform.js | 23 +++++++++++++---------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index 5480b461..afe726da 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -47,11 +47,12 @@ class CoreStatusCommand extends BaseCommand { const { result: networkInfo } = await coreService.getRpcClient().getNetworkInfo(); const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); const { result: peerInfo } = await coreService.getRpcClient().getPeerInfo(); - const latestVersionRes = await fetch('https://api.github.com/repos/dashpay/dash/releases/latest').then((res) => res.text()); - const latestVersion = JSON.parse(latestVersionRes); - const insightBlockHeightRes = await fetch(`${insightURLs[config.options.network]}/status`).then((res) => res.text()); - const insightBlockHeight = JSON.parse(insightBlockHeightRes); - let corePortState = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`).then((res) => res.text()); + const latestVersionRes = await fetch('https://api.github.com/repos/dashpay/dash/releases/latest'); + const latestVersion = await latestVersionRes.json(); + const insightBlockHeightRes = await fetch(`${insightURLs[config.options.network]}/status`); + const insightBlockHeight = await insightBlockHeightRes.json(); + const corePortStateRes = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`); + let corePortState = await corePortStateRes.text(); let coreVersion = networkInfo.subversion.replace(/\/|\(.*?\)/g, ''); const sentinelVersion = (await dockerCompose.execCommand( config.toEnvs(), diff --git a/src/commands/status/index.js b/src/commands/status/index.js index 26c98799..3e39e7a6 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -54,12 +54,12 @@ class StatusCommand extends BaseCommand { if (config.options.network !== 'testnet') { // curl fails if tendermint has not started yet because abci is waiting for core to sync if (mnsyncStatus.IsSynced === true) { - const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text()); - tendermintStatus = JSON.parse(tendermintStatusRes); + const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`); + tendermintStatus = await tendermintStatusRes.json(); } } - const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text()); - const explorerBlockHeight = JSON.parse(explorerBlockHeightRes); + const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status'); + const explorerBlockHeight = await explorerBlockHeightRes.json(); // Determine status let coreStatus; diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index a91894d0..bf095844 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -52,16 +52,19 @@ class CoreStatusCommand extends BaseCommand { this.exit(); } - const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`).then((res) => res.text()); - const tendermintStatus = JSON.parse(tendermintStatusRes); - const tendermintNetInfoRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`).then((res) => res.text()); - const tendermintNetInfo = JSON.parse(tendermintNetInfoRes); - const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status').then((res) => res.text()); - const explorerBlockHeight = JSON.parse(explorerBlockHeightRes); - - let httpPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`).then((res) => res.text()); - let gRpcPortState = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.grpc.port}/`).then((res) => res.text()); - let p2pPortState = await fetch(`https://mnowatch.org/${config.options.platform.drive.tendermint.p2p.port}/`).then((res) => res.text()); + const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`); + const tendermintStatus = await tendermintStatusRes.json(); + const tendermintNetInfoRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`); + const tendermintNetInfo = await tendermintNetInfoRes.json(); + const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status'); + const explorerBlockHeight = await explorerBlockHeightRes.json(); + + const httpPortStateRes = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`); + let httpPortState = await httpPortStateRes.text(); + const gRpcPortStateRes = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.grpc.port}/`); + let gRpcPortState = await gRpcPortStateRes.text(); + const p2pPortStateRes = await fetch(`https://mnowatch.org/${config.options.platform.drive.tendermint.p2p.port}/`); + let p2pPortState = await p2pPortStateRes.text(); // Determine status let status; From 4b22b1763b835de90d132e06280055ac2e4343a8 Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 23 Nov 2020 12:24:51 -0800 Subject: [PATCH 37/44] fix: use consistent colours --- src/commands/status/index.js | 14 +++++++------- src/commands/status/services.js | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/commands/status/index.js b/src/commands/status/index.js index 3e39e7a6..c9bc2bb5 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -121,19 +121,19 @@ class StatusCommand extends BaseCommand { // Apply colors if (coreStatus === 'running') { - coreStatus = chalk.keyword('green')(coreStatus); + coreStatus = chalk.green(coreStatus); } else if (coreStatus.includes('syncing')) { - coreStatus = chalk.keyword('yellow')(coreStatus); + coreStatus = chalk.yellow(coreStatus); } else { - coreStatus = chalk.keyword('red')(coreStatus); + coreStatus = chalk.red(coreStatus); } if (platformStatus === 'running') { - platformStatus = chalk.keyword('green')(platformStatus); + platformStatus = chalk.green(platformStatus); } else if (platformStatus.includes('syncing')) { - platformStatus = chalk.keyword('yellow')(platformStatus); + platformStatus = chalk.yellow(platformStatus); } else { - platformStatus = chalk.keyword('red')(platformStatus); + platformStatus = chalk.red(platformStatus); } // Build table @@ -141,7 +141,7 @@ class StatusCommand extends BaseCommand { rows.push(['Core Version', networkInfo.subversion.replace(/\/|\(.*?\)/g, '')]); rows.push(['Core Status', coreStatus]); if (config.options.core.masternode.enable === true) { - rows.push(['Masternode Status', chalk.keyword(masternodeStatus.status === 'Ready' ? 'green' : 'red')(masternodeStatus.status)]); + rows.push(['Masternode Status', (masternodeStatus.status === 'Ready' ? chalk.green : chalk.red)(masternodeStatus.status)]); } if (config.options.network !== 'testnet' && mnsyncStatus.IsSynced === true) { rows.push(['Platform Version', tendermintStatus.result.node_info.version]); diff --git a/src/commands/status/services.js b/src/commands/status/services.js index 88b5ce05..6dbcc2d5 100644 --- a/src/commands/status/services.js +++ b/src/commands/status/services.js @@ -64,7 +64,7 @@ class ServicesStatusCommand extends BaseCommand { let statusText; if (status) { - statusText = chalk.keyword(status === 'running' ? 'green' : 'red')(status); + statusText = (status === 'running' ? chalk.green : chalk.red)(status); } tableRows.push([ From 4c34b2bc662e167b1b112969b182f59420392df2 Mon Sep 17 00:00:00 2001 From: Leon White Date: Mon, 23 Nov 2020 13:48:04 -0800 Subject: [PATCH 38/44] refactor: try more destructuring assignment --- src/commands/status/index.js | 112 ++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 34 deletions(-) diff --git a/src/commands/status/index.js b/src/commands/status/index.js index c9bc2bb5..4243e1d4 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -39,27 +39,73 @@ class StatusCommand extends BaseCommand { // Collect data const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); - const { result: networkInfo } = await coreService.getRpcClient().getNetworkInfo(); - const { result: blockchainInfo } = await coreService.getRpcClient().getBlockchainInfo(); + const { + result: { + subversion: coreVersion, + }, + } = await coreService.getRpcClient().getNetworkInfo(); + const { + result: { + blocks: coreBlocks, + chain: coreChain, + verificationprogress: coreVerificationProgress, + }, + } = await coreService.getRpcClient().getBlockchainInfo(); let masternodeStatus; - let masternodeCount; + let masternodePoSeRevivedHeight; + let masternodeLastPaidHeight; + let masternodeRegisteredHeight; + let masternodeEnabledCount; + let masternodePoSePenalty; if (config.options.core.masternode.enable === true) { - ({ result: masternodeStatus } = await coreService.getRpcClient().masternode('status')); - ({ result: masternodeCount } = await coreService.getRpcClient().masternode('count')); + ({ + result: { + dmnState: { + lastPaidHeight: masternodeLastPaidHeight, + registeredHeight: masternodeRegisteredHeight, + PoSeRevivedHeight: masternodePoSeRevivedHeight, + PoSePenalty: masternodePoSePenalty, + }, + status: masternodeStatus, + }, + } = await coreService.getRpcClient().masternode('status')); + ({ + result: { + enabled: masternodeEnabledCount, + }, + } = await coreService.getRpcClient().masternode('count')); } // Platform status - let tendermintStatus; + let tendermintVersion; + let tendermintBlockHeight; + let tendermintCatchingUp; if (config.options.network !== 'testnet') { // curl fails if tendermint has not started yet because abci is waiting for core to sync if (mnsyncStatus.IsSynced === true) { const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`); - tendermintStatus = await tendermintStatusRes.json(); + ({ + result: { + node_info: { + version: tendermintVersion, + }, + sync_info: { + latest_block_height: tendermintBlockHeight, + catching_up: tendermintCatchingUp, + }, + }, + } = await tendermintStatusRes.json()); } } const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status'); - const explorerBlockHeight = await explorerBlockHeightRes.json(); + const { + result: { + sync_info: { + latest_block_height: explorerBlockHeight, + }, + }, + } = await explorerBlockHeightRes.json(); // Determine status let coreStatus; @@ -76,7 +122,7 @@ class StatusCommand extends BaseCommand { } if (coreStatus === 'running') { if (mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { - coreStatus = `syncing ${(blockchainInfo.verificationprogress * 100).toFixed(2)}%`; + coreStatus = `syncing ${(coreVerificationProgress * 100).toFixed(2)}%`; } } @@ -94,27 +140,25 @@ class StatusCommand extends BaseCommand { } if (platformStatus === 'running' && mnsyncStatus.IsSynced === false) { platformStatus = 'waiting for core sync'; - } else if (platformStatus === 'running' && tendermintStatus.result.sync_info.catching_up === true) { - platformStatus = `syncing ${((tendermintStatus.result.sync_info.latest_block_height - / explorerBlockHeight.result.sync_info.latest_block_height) - * 100).toFixed(2)}%`; + } else if (platformStatus === 'running' && tendermintCatchingUp === true) { + platformStatus = `syncing ${((tendermintBlockHeight / explorerBlockHeight) * 100).toFixed(2)}%`; } let paymentQueuePosition; if (config.options.core.masternode.enable === true) { - if (masternodeStatus.state === 'READY') { - if (masternodeStatus.dmnState.PoSeRevivedHeight > 0) { - paymentQueuePosition = masternodeStatus.dmnState.PoSeRevivedHeight - + masternodeCount.enabled - - blockchainInfo.blocks; - } else if (masternodeStatus.dmnState.lastPaidHeight === 0) { - paymentQueuePosition = masternodeStatus.dmnState.registeredHeight - + masternodeCount.enabled - - blockchainInfo.blocks; + if (masternodeStatus === 'Ready') { + if (masternodePoSeRevivedHeight > 0) { + paymentQueuePosition = masternodePoSeRevivedHeight + + masternodeEnabledCount + - coreBlocks; + } else if (masternodeLastPaidHeight === 0) { + paymentQueuePosition = masternodeRegisteredHeight + + masternodeEnabledCount + - coreBlocks; } else { - paymentQueuePosition = masternodeStatus.dmnState.lastPaidHeight - + masternodeCount.enabled - - blockchainInfo.blocks; + paymentQueuePosition = masternodeLastPaidHeight + + masternodeEnabledCount + - coreBlocks; } } } @@ -137,22 +181,22 @@ class StatusCommand extends BaseCommand { } // Build table - rows.push(['Network', blockchainInfo.chain]); - rows.push(['Core Version', networkInfo.subversion.replace(/\/|\(.*?\)/g, '')]); + rows.push(['Network', coreChain]); + rows.push(['Core Version', coreVersion.replace(/\/|\(.*?\)/g, '')]); rows.push(['Core Status', coreStatus]); if (config.options.core.masternode.enable === true) { - rows.push(['Masternode Status', (masternodeStatus.status === 'Ready' ? chalk.green : chalk.red)(masternodeStatus.status)]); + rows.push(['Masternode Status', (masternodeStatus === 'Ready' ? chalk.green : chalk.red)(masternodeStatus)]); } if (config.options.network !== 'testnet' && mnsyncStatus.IsSynced === true) { - rows.push(['Platform Version', tendermintStatus.result.node_info.version]); + rows.push(['Platform Version', tendermintVersion]); } rows.push(['Platform Status', platformStatus]); if (config.options.core.masternode.enable === true) { - if (masternodeStatus.state === 'READY') { - rows.push(['PoSe Penalty', masternodeStatus.dmnState.PoSePenalty]); - rows.push(['Last paid block', masternodeStatus.dmnState.lastPaidHeight]); - rows.push(['Last paid time', `${blocksToTime(blockchainInfo.blocks - masternodeStatus.dmnState.lastPaidHeight)} ago`]); - rows.push(['Payment queue position', `${paymentQueuePosition}/${masternodeCount.enabled}`]); + if (masternodeStatus === 'Ready') { + rows.push(['PoSe Penalty', masternodePoSePenalty]); + rows.push(['Last paid block', masternodeLastPaidHeight]); + rows.push(['Last paid time', `${blocksToTime(coreBlocks - masternodeLastPaidHeight)} ago`]); + rows.push(['Payment queue position', `${paymentQueuePosition}/${masternodeEnabledCount}`]); rows.push(['Next payment time', `in ${blocksToTime(paymentQueuePosition)}`]); } } From a48413acd74b41967b26710b63ad4e2c733bf497 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 24 Nov 2020 10:46:08 -0800 Subject: [PATCH 39/44] fix: run masternode checks only if masternode is ready --- src/commands/status/masternode.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 3118d6c0..8f6dd047 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -106,10 +106,12 @@ class MasternodeStatusCommand extends BaseCommand { } let PoSePenalty; - if (masternodeStatus.dmnState.PoSePenalty === 0) { - PoSePenalty = chalk.green(masternodeStatus.dmnState.PoSePenalty); - } else { - PoSePenalty = chalk.red(masternodeStatus.dmnState.PoSePenalty); + if (masternodeStatus.state === 'READY') { + if (masternodeStatus.dmnState.PoSePenalty === 0) { + PoSePenalty = chalk.green(masternodeStatus.dmnState.PoSePenalty); + } else { + PoSePenalty = chalk.red(masternodeStatus.dmnState.PoSePenalty); + } } // Build table From 961e590a0903d68832947562dcb8e1cafde7b006 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 24 Nov 2020 11:07:05 -0800 Subject: [PATCH 40/44] fix: add some yellow statuses --- src/commands/status/core.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index afe726da..92b7f895 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -87,7 +87,7 @@ class CoreStatusCommand extends BaseCommand { // Apply colors if (status === 'running') { status = chalk.green(status); - } else if (status.includes('syncing')) { + } else if (status.startsWith('syncing')) { status = chalk.yellow(status); } else { status = chalk.red(status); @@ -95,6 +95,8 @@ class CoreStatusCommand extends BaseCommand { if (coreVersion.substring(coreVersion.indexOf(':') + 1) === latestVersion.tag_name.substring(1)) { coreVersion = chalk.green(coreVersion); + } else if (coreVersion.match(/(?<=:)\d+.\d+/)[0] === latestVersion.tag_name.match(/(?<=v)\d+.\d+/)[0]) { + coreVersion = chalk.yellow(coreVersion); } else { coreVersion = chalk.red(coreVersion); } @@ -109,6 +111,8 @@ class CoreStatusCommand extends BaseCommand { if (blockchainInfo.blocks === blockchainInfo.headers || blockchainInfo.blocks >= insightBlockHeight.info.blocks) { blocks = chalk.green(blockchainInfo.blocks); + } else if ((insightBlockHeight.info.blocks - blockchainInfo.blocks) < 3) { + blocks = chalk.yellow(blockchainInfo.blocks); } else { blocks = chalk.red(blockchainInfo.blocks); } From 586e107ca315202bf29da04c3bf2402a06833325 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 24 Nov 2020 11:22:13 -0800 Subject: [PATCH 41/44] fix: don't use insight on local config --- src/commands/status/core.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/commands/status/core.js b/src/commands/status/core.js index 92b7f895..bb8e5206 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -49,11 +49,15 @@ class CoreStatusCommand extends BaseCommand { const { result: peerInfo } = await coreService.getRpcClient().getPeerInfo(); const latestVersionRes = await fetch('https://api.github.com/repos/dashpay/dash/releases/latest'); const latestVersion = await latestVersionRes.json(); - const insightBlockHeightRes = await fetch(`${insightURLs[config.options.network]}/status`); - const insightBlockHeight = await insightBlockHeightRes.json(); const corePortStateRes = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`); let corePortState = await corePortStateRes.text(); let coreVersion = networkInfo.subversion.replace(/\/|\(.*?\)/g, ''); + let insightBlockHeightRes; + let insightBlockHeight; + if (insightURLs[config.options.network]) { + insightBlockHeightRes = await fetch(`${insightURLs[config.options.network]}/status`); + insightBlockHeight = await insightBlockHeightRes.json(); + } const sentinelVersion = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', @@ -135,7 +139,9 @@ class CoreStatusCommand extends BaseCommand { rows.push(['RPC service', `127.0.0.1:${config.options.core.rpc.port}`]); rows.push(['Block height', blocks]); rows.push(['Header height', blockchainInfo.headers]); - rows.push(['Remote block height', insightBlockHeight.info.blocks]); + if (insightURLs[config.options.network]) { + rows.push(['Remote block height', insightBlockHeight.info.blocks]); + } rows.push(['Difficulty', blockchainInfo.difficulty]); rows.push(['Sentinel version', sentinelVersion]); rows.push(['Sentinel status', (sentinelState)]); From 27d06fa137699f5c1e9e4c85408f1ba45c991f93 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 24 Nov 2020 19:43:18 -0800 Subject: [PATCH 42/44] refactor: util functions and destructuring assignment --- src/commands/status/core.js | 62 ++++++----- src/commands/status/index.js | 154 ++++++++++++++-------------- src/commands/status/masternode.js | 89 ++++++++-------- src/commands/status/platform.js | 69 +++++++++---- src/util/getPaymentQueuePosition.js | 19 ++++ 5 files changed, 230 insertions(+), 163 deletions(-) create mode 100644 src/util/getPaymentQueuePosition.js diff --git a/src/commands/status/core.js b/src/commands/status/core.js index bb8e5206..56661048 100644 --- a/src/commands/status/core.js +++ b/src/commands/status/core.js @@ -43,26 +43,41 @@ class CoreStatusCommand extends BaseCommand { }; // Collect data - const { result: blockchainInfo } = await coreService.getRpcClient().getBlockchainInfo(); + const { + result: { + blocks: coreBlocks, + chain: coreChain, + difficulty: coreDifficulty, + headers: coreHeaders, + verificationprogress: coreVerificationProgress, + }, + } = await coreService.getRpcClient().getBlockchainInfo(); const { result: networkInfo } = await coreService.getRpcClient().getNetworkInfo(); const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); const { result: peerInfo } = await coreService.getRpcClient().getPeerInfo(); const latestVersionRes = await fetch('https://api.github.com/repos/dashpay/dash/releases/latest'); - const latestVersion = await latestVersionRes.json(); + let { + tag_name: latestVersion, + } = await latestVersionRes.json(); + latestVersion = latestVersion.substring(1); const corePortStateRes = await fetch(`https://mnowatch.org/${config.options.core.p2p.port}/`); let corePortState = await corePortStateRes.text(); - let coreVersion = networkInfo.subversion.replace(/\/|\(.*?\)/g, ''); - let insightBlockHeightRes; - let insightBlockHeight; + let coreVersion = networkInfo.subversion.replace(/\/|\(.*?\)|Dash Core:/g, ''); + let explorerBlockHeightRes; + let explorerBlockHeight; if (insightURLs[config.options.network]) { - insightBlockHeightRes = await fetch(`${insightURLs[config.options.network]}/status`); - insightBlockHeight = await insightBlockHeightRes.json(); + explorerBlockHeightRes = await fetch(`${insightURLs[config.options.network]}/status`); + ({ + info: { + blocks: explorerBlockHeight, + }, + } = await explorerBlockHeightRes.json()); } const sentinelVersion = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', 'python bin/sentinel.py -v', - )).out.split('\n')[0]; + )).out.split('\n')[0].replace(/Dash Sentinel v/, ''); let sentinelState = (await dockerCompose.execCommand( config.toEnvs(), 'sentinel', @@ -82,10 +97,8 @@ class CoreStatusCommand extends BaseCommand { status = 'not started'; } } - if (status === 'running') { - if (mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { - status = `syncing ${(blockchainInfo.verificationprogress * 100).toFixed(2)}%`; - } + if (status === 'running' && mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { + status = `syncing ${(coreVerificationProgress * 100).toFixed(2)}%`; } // Apply colors @@ -97,9 +110,9 @@ class CoreStatusCommand extends BaseCommand { status = chalk.red(status); } - if (coreVersion.substring(coreVersion.indexOf(':') + 1) === latestVersion.tag_name.substring(1)) { + if (coreVersion === latestVersion) { coreVersion = chalk.green(coreVersion); - } else if (coreVersion.match(/(?<=:)\d+.\d+/)[0] === latestVersion.tag_name.match(/(?<=v)\d+.\d+/)[0]) { + } else if (coreVersion.match(/\d+.\d+/)[0] === latestVersion.match(/\d+.\d+/)[0]) { coreVersion = chalk.yellow(coreVersion); } else { coreVersion = chalk.red(coreVersion); @@ -112,13 +125,12 @@ class CoreStatusCommand extends BaseCommand { } let blocks; - if (blockchainInfo.blocks === blockchainInfo.headers - || blockchainInfo.blocks >= insightBlockHeight.info.blocks) { - blocks = chalk.green(blockchainInfo.blocks); - } else if ((insightBlockHeight.info.blocks - blockchainInfo.blocks) < 3) { - blocks = chalk.yellow(blockchainInfo.blocks); + if (coreBlocks === coreHeaders || coreBlocks >= explorerBlockHeight) { + blocks = chalk.green(coreBlocks); + } else if ((explorerBlockHeight - coreBlocks) < 3) { + blocks = chalk.yellow(coreBlocks); } else { - blocks = chalk.red(blockchainInfo.blocks); + blocks = chalk.red(coreBlocks); } if (sentinelState === '') { @@ -129,8 +141,8 @@ class CoreStatusCommand extends BaseCommand { // Build table rows.push(['Version', coreVersion]); - rows.push(['Latest version', latestVersion.tag_name]); - rows.push(['Network', blockchainInfo.chain]); + rows.push(['Latest version', latestVersion]); + rows.push(['Network', coreChain]); rows.push(['Status', status]); rows.push(['Sync asset', mnsyncStatus.AssetName]); rows.push(['Peer count', peerInfo.length]); @@ -138,11 +150,11 @@ class CoreStatusCommand extends BaseCommand { rows.push(['P2P port', `${config.options.core.p2p.port} ${corePortState}`]); rows.push(['RPC service', `127.0.0.1:${config.options.core.rpc.port}`]); rows.push(['Block height', blocks]); - rows.push(['Header height', blockchainInfo.headers]); + rows.push(['Header height', coreHeaders]); if (insightURLs[config.options.network]) { - rows.push(['Remote block height', insightBlockHeight.info.blocks]); + rows.push(['Remote block height', explorerBlockHeight]); } - rows.push(['Difficulty', blockchainInfo.difficulty]); + rows.push(['Difficulty', coreDifficulty]); rows.push(['Sentinel version', sentinelVersion]); rows.push(['Sentinel status', (sentinelState)]); diff --git a/src/commands/status/index.js b/src/commands/status/index.js index 4243e1d4..0a45fa40 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -7,6 +7,7 @@ const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPr const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); const blocksToTime = require('../../util/blocksToTime'); +const getPaymentQueuePosition = require('../../util/getPaymentQueuePosition'); class StatusCommand extends BaseCommand { /** @@ -37,13 +38,21 @@ class StatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); - // Collect data - const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); + // Collect core data const { + result: { + AssetName: coreSyncAsset, + IsSynced: coreIsSynced, + }, + } = await coreService.getRpcClient().mnsync('status'); + + let { result: { subversion: coreVersion, }, } = await coreService.getRpcClient().getNetworkInfo(); + coreVersion = coreVersion.replace(/\/|\(.*?\)|Dash Core:/g, ''); + const { result: { blocks: coreBlocks, @@ -52,21 +61,14 @@ class StatusCommand extends BaseCommand { }, } = await coreService.getRpcClient().getBlockchainInfo(); + // Collect masternode data + let masternodeState; let masternodeStatus; - let masternodePoSeRevivedHeight; - let masternodeLastPaidHeight; - let masternodeRegisteredHeight; let masternodeEnabledCount; - let masternodePoSePenalty; if (config.options.core.masternode.enable === true) { ({ result: { - dmnState: { - lastPaidHeight: masternodeLastPaidHeight, - registeredHeight: masternodeRegisteredHeight, - PoSeRevivedHeight: masternodePoSeRevivedHeight, - PoSePenalty: masternodePoSePenalty, - }, + dmnState: masternodeState, status: masternodeStatus, }, } = await coreService.getRpcClient().masternode('status')); @@ -77,27 +79,26 @@ class StatusCommand extends BaseCommand { } = await coreService.getRpcClient().masternode('count')); } - // Platform status - let tendermintVersion; - let tendermintBlockHeight; - let tendermintCatchingUp; - if (config.options.network !== 'testnet') { - // curl fails if tendermint has not started yet because abci is waiting for core to sync - if (mnsyncStatus.IsSynced === true) { - const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`); - ({ - result: { - node_info: { - version: tendermintVersion, - }, - sync_info: { - latest_block_height: tendermintBlockHeight, - catching_up: tendermintCatchingUp, - }, + // Collect platform data + let platformVersion; + let platformBlockHeight; + let platformCatchingUp; + // Collecting platform data fails if Tenderdash is waiting for core to sync + if (config.options.network !== 'testnet' && coreIsSynced === true) { + const platformStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`); + ({ + result: { + node_info: { + version: platformVersion, }, - } = await tendermintStatusRes.json()); - } + sync_info: { + latest_block_height: platformBlockHeight, + catching_up: platformCatchingUp, + }, + }, + } = await platformStatusRes.json()); } + const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status'); const { result: { @@ -120,47 +121,36 @@ class StatusCommand extends BaseCommand { coreStatus = 'not started'; } } - if (coreStatus === 'running') { - if (mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { - coreStatus = `syncing ${(coreVerificationProgress * 100).toFixed(2)}%`; - } + if (coreStatus === 'running' && coreSyncAsset !== 'MASTERNODE_SYNC_FINISHED') { + coreStatus = `syncing ${(coreVerificationProgress * 100).toFixed(2)}%`; } let platformStatus; - try { - ({ - State: { - Status: platformStatus, - }, - } = await dockerCompose.inspectService(config.toEnvs(), 'drive_tendermint')); - } catch (e) { - if (e instanceof ContainerIsNotPresentError) { - platformStatus = 'not started'; + if (config.options.network !== 'testnet') { + try { + ({ + State: { + Status: platformStatus, + }, + } = await dockerCompose.inspectService(config.toEnvs(), 'drive_tendermint')); + } catch (e) { + if (e instanceof ContainerIsNotPresentError) { + platformStatus = 'not started'; + } + } + if (platformStatus === 'running' && coreIsSynced === false) { + platformStatus = 'waiting for core sync'; + } else if (platformStatus === 'running' && platformCatchingUp === true) { + platformStatus = `syncing ${((platformBlockHeight / explorerBlockHeight) * 100).toFixed(2)}%`; } - } - if (platformStatus === 'running' && mnsyncStatus.IsSynced === false) { - platformStatus = 'waiting for core sync'; - } else if (platformStatus === 'running' && tendermintCatchingUp === true) { - platformStatus = `syncing ${((tendermintBlockHeight / explorerBlockHeight) * 100).toFixed(2)}%`; } + // Determine payment queue position let paymentQueuePosition; - if (config.options.core.masternode.enable === true) { - if (masternodeStatus === 'Ready') { - if (masternodePoSeRevivedHeight > 0) { - paymentQueuePosition = masternodePoSeRevivedHeight - + masternodeEnabledCount - - coreBlocks; - } else if (masternodeLastPaidHeight === 0) { - paymentQueuePosition = masternodeRegisteredHeight - + masternodeEnabledCount - - coreBlocks; - } else { - paymentQueuePosition = masternodeLastPaidHeight - + masternodeEnabledCount - - coreBlocks; - } - } + if (config.options.core.masternode.enable === true && masternodeStatus === 'Ready') { + paymentQueuePosition = getPaymentQueuePosition( + masternodeState, masternodeEnabledCount, coreBlocks, + ); } // Apply colors @@ -172,12 +162,20 @@ class StatusCommand extends BaseCommand { coreStatus = chalk.red(coreStatus); } - if (platformStatus === 'running') { - platformStatus = chalk.green(platformStatus); - } else if (platformStatus.includes('syncing')) { - platformStatus = chalk.yellow(platformStatus); + if (config.options.network !== 'testnet') { + if (platformStatus === 'running') { + platformStatus = chalk.green(platformStatus); + } else if (platformStatus.startsWith('syncing')) { + platformStatus = chalk.yellow(platformStatus); + } else { + platformStatus = chalk.red(platformStatus); + } + } + + if (masternodeStatus === 'Ready') { + masternodeStatus = chalk.green(masternodeStatus); } else { - platformStatus = chalk.red(platformStatus); + masternodeStatus = chalk.red(masternodeStatus); } // Build table @@ -185,17 +183,19 @@ class StatusCommand extends BaseCommand { rows.push(['Core Version', coreVersion.replace(/\/|\(.*?\)/g, '')]); rows.push(['Core Status', coreStatus]); if (config.options.core.masternode.enable === true) { - rows.push(['Masternode Status', (masternodeStatus === 'Ready' ? chalk.green : chalk.red)(masternodeStatus)]); + rows.push(['Masternode Status', (masternodeStatus)]); } - if (config.options.network !== 'testnet' && mnsyncStatus.IsSynced === true) { - rows.push(['Platform Version', tendermintVersion]); + if (config.options.network !== 'testnet') { + if (coreIsSynced === true) { + rows.push(['Platform Version', platformVersion]); + } + rows.push(['Platform Status', platformStatus]); } - rows.push(['Platform Status', platformStatus]); if (config.options.core.masternode.enable === true) { if (masternodeStatus === 'Ready') { - rows.push(['PoSe Penalty', masternodePoSePenalty]); - rows.push(['Last paid block', masternodeLastPaidHeight]); - rows.push(['Last paid time', `${blocksToTime(coreBlocks - masternodeLastPaidHeight)} ago`]); + rows.push(['PoSe Penalty', masternodeState.PoSePenalty]); + rows.push(['Last paid block', masternodeState.lastPaidHeight]); + rows.push(['Last paid time', `${blocksToTime(coreBlocks - masternodeState.lastPaidHeight)} ago`]); rows.push(['Payment queue position', `${paymentQueuePosition}/${masternodeEnabledCount}`]); rows.push(['Next payment time', `in ${blocksToTime(paymentQueuePosition)}`]); } diff --git a/src/commands/status/masternode.js b/src/commands/status/masternode.js index 8f6dd047..e9e1d577 100644 --- a/src/commands/status/masternode.js +++ b/src/commands/status/masternode.js @@ -4,6 +4,7 @@ const chalk = require('chalk'); const BaseCommand = require('../../oclif/command/BaseCommand'); const CoreService = require('../../core/CoreService'); const blocksToTime = require('../../util/blocksToTime'); +const getPaymentQueuePosition = require('../../util/getPaymentQueuePosition'); const ContainerIsNotPresentError = require('../../docker/errors/ContainerIsNotPresentError'); @@ -44,9 +45,32 @@ class MasternodeStatusCommand extends BaseCommand { // Collect data const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); - const { result: blockchainInfo } = await coreService.getRpcClient().getBlockchainInfo(); - const { result: masternodeStatus } = await coreService.getRpcClient().masternode('status'); - const { result: masternodeCount } = await coreService.getRpcClient().masternode('count'); + const { + result: { + blocks: coreBlocks, + verificationprogress: coreVerificationProgress, + }, + } = await coreService.getRpcClient().getBlockchainInfo(); + + const { + result: { + enabled: masternodeEnabledCount, + }, + } = await coreService.getRpcClient().masternode('count'); + + const { + result: { + dmnState: masternodeState, + status: masternodeStatus, + proTxHash: masternodeProTxHash, + }, + } = await coreService.getRpcClient().masternode('status'); + + let sentinelState = (await dockerCompose.execCommand( + config.toEnvs(), + 'sentinel', + 'python bin/sentinel.py', + )).out.split('\n')[0]; // Determine status let status; @@ -61,39 +85,22 @@ class MasternodeStatusCommand extends BaseCommand { status = 'not started'; } } - if (status === 'running') { - if (mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { - status = `syncing ${(blockchainInfo.verificationprogress * 100).toFixed(2)}%`; - } + if (status === 'running' && mnsyncStatus.AssetName !== 'MASTERNODE_SYNC_FINISHED') { + status = `syncing ${(coreVerificationProgress * 100).toFixed(2)}%`; } + // Determine payment queue position let paymentQueuePosition; - if (masternodeStatus.state === 'READY') { - if (masternodeStatus.dmnState.PoSeRevivedHeight > 0) { - paymentQueuePosition = masternodeStatus.dmnState.PoSeRevivedHeight - + masternodeCount.enabled - - blockchainInfo.blocks; - } else if (masternodeStatus.dmnState.lastPaidHeight === 0) { - paymentQueuePosition = masternodeStatus.dmnState.registeredHeight - + masternodeCount.enabled - - blockchainInfo.blocks; - } else { - paymentQueuePosition = masternodeStatus.dmnState.lastPaidHeight - + masternodeCount.enabled - - blockchainInfo.blocks; - } + if (masternodeStatus === 'Ready' && masternodeState.PoSeRevivedHeight > 0) { + paymentQueuePosition = getPaymentQueuePosition( + masternodeState, masternodeEnabledCount, coreBlocks, + ); } - let sentinelState = (await dockerCompose.execCommand( - config.toEnvs(), - 'sentinel', - 'python bin/sentinel.py', - )).out.split('\n')[0]; - // Apply colors if (status === 'running') { status = chalk.green(status); - } else if (status.includes('syncing')) { + } else if (status.startsWith('syncing')) { status = chalk.yellow(status); } else { status = chalk.red(status); @@ -105,24 +112,26 @@ class MasternodeStatusCommand extends BaseCommand { sentinelState = chalk.red(sentinelState); } - let PoSePenalty; - if (masternodeStatus.state === 'READY') { - if (masternodeStatus.dmnState.PoSePenalty === 0) { - PoSePenalty = chalk.green(masternodeStatus.dmnState.PoSePenalty); + let masternodePoSePenalty; + if (masternodeStatus === 'Ready') { + if (masternodeState.PoSePenalty === 0) { + masternodePoSePenalty = chalk.green(masternodeState.PoSePenalty); + } else if (masternodeState.PoSePenalty < masternodeEnabledCount) { + masternodePoSePenalty = chalk.yellow(masternodeState.PoSePenalty); } else { - PoSePenalty = chalk.red(masternodeStatus.dmnState.PoSePenalty); + masternodePoSePenalty = chalk.red(masternodeState.PoSePenalty); } } // Build table - rows.push(['Masternode status', status]); + rows.push(['Masternode status', (masternodeStatus === 'Ready' ? chalk.green : chalk.red)(masternodeStatus)]); rows.push(['Sentinel status', (sentinelState !== '' ? sentinelState : 'No errors')]); - if (masternodeStatus.state === 'READY') { - rows.push(['ProTx Hash', masternodeStatus.proTxHash]); - rows.push(['PoSe Penalty', PoSePenalty]); - rows.push(['Last paid block', masternodeStatus.dmnState.lastPaidHeight]); - rows.push(['Last paid time', `${blocksToTime(blockchainInfo.blocks - masternodeStatus.dmnState.lastPaidHeight)} ago`]); - rows.push(['Payment queue position', `${paymentQueuePosition}/${masternodeCount.enabled}`]); + if (masternodeStatus === 'Ready') { + rows.push(['ProTx Hash', masternodeProTxHash]); + rows.push(['PoSe Penalty', masternodePoSePenalty]); + rows.push(['Last paid block', masternodeState.lastPaidHeight]); + rows.push(['Last paid time', `${blocksToTime(coreBlocks - masternodeState.lastPaidHeight)} ago`]); + rows.push(['Payment queue position', `${paymentQueuePosition}/${masternodeEnabledCount}`]); rows.push(['Next payment time', `in ${blocksToTime(paymentQueuePosition)}`]); } diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index bf095844..b625da34 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -42,23 +42,53 @@ class CoreStatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); - // Collect data - const { result: mnsyncStatus } = await coreService.getRpcClient().mnsync('status'); - - // curl fails if tendermint has not started yet because abci is waiting for core to sync - if (mnsyncStatus.IsSynced === false) { + // Collect core data + const { + result: { + IsSynced: coreIsSynced, + }, + } = await coreService.getRpcClient().mnsync('status'); + + // Collecting platform data fails if Tenderdash is waiting for core to sync + if (coreIsSynced === false) { // eslint-disable-next-line no-console console.log('Platform status is not available until core sync is complete!'); this.exit(); } + // Collect platform data const tendermintStatusRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/status`); - const tendermintStatus = await tendermintStatusRes.json(); + const { + result: { + node_info: { + version: platformVersion, + network: platformNetwork, + }, + sync_info: { + catching_up: platformCatchingUp, + latest_app_hash: platformLatestAppHash, + latest_block_height: platformLatestBlockHeight, + }, + }, + } = await tendermintStatusRes.json(); + const tendermintNetInfoRes = await fetch(`http://localhost:${config.options.platform.drive.tendermint.rpc.port}/net_info`); - const tendermintNetInfo = await tendermintNetInfoRes.json(); + const { + result: { + n_peers: platformPeers, + }, + } = await tendermintNetInfoRes.json(); + const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status'); - const explorerBlockHeight = await explorerBlockHeightRes.json(); + const { + result: { + sync_info: { + latest_block_height: explorerLatestBlockHeight, + }, + }, + } = await explorerBlockHeightRes.json(); + // Check ports const httpPortStateRes = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`); let httpPortState = await httpPortStateRes.text(); const gRpcPortStateRes = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.grpc.port}/`); @@ -79,10 +109,8 @@ class CoreStatusCommand extends BaseCommand { status = 'not started'; } } - if (status === 'running' && tendermintStatus.result.sync_info.catching_up === true) { - status = `syncing ${((tendermintStatus.result.sync_info.latest_block_height - / explorerBlockHeight.result.sync_info.latest_block_height) - * 100).toFixed(2)}%`; + if (status === 'running' && platformCatchingUp === true) { + status = `syncing ${((platformLatestBlockHeight / explorerLatestBlockHeight) * 100).toFixed(2)}%`; } // Apply colors @@ -95,11 +123,10 @@ class CoreStatusCommand extends BaseCommand { } let blocks; - if (tendermintStatus.result.sync_info.latest_block_height - >= explorerBlockHeight.result.sync_info.latest_block_height) { - blocks = chalk.green(tendermintStatus.result.sync_info.latest_block_height); + if (platformLatestBlockHeight >= explorerLatestBlockHeight) { + blocks = chalk.green(platformLatestBlockHeight); } else { - blocks = chalk.red(tendermintStatus.result.sync_info.latest_block_height); + blocks = chalk.red(platformLatestBlockHeight); } if (httpPortState === 'OPEN') { @@ -119,13 +146,13 @@ class CoreStatusCommand extends BaseCommand { } // Build table - rows.push(['Tenderdash Version', tendermintStatus.result.node_info.version]); - rows.push(['Network', tendermintStatus.result.node_info.network]); + rows.push(['Tenderdash Version', platformVersion]); + rows.push(['Network', platformNetwork]); rows.push(['Status', status]); rows.push(['Block height', blocks]); - rows.push(['Remote block height', explorerBlockHeight.result.sync_info.latest_block_height]); - rows.push(['Peer count', tendermintNetInfo.result.n_peers]); - rows.push(['App hash', tendermintStatus.result.sync_info.latest_app_hash]); + rows.push(['Remote block height', explorerLatestBlockHeight]); + rows.push(['Peer count', platformPeers]); + rows.push(['App hash', platformLatestAppHash]); rows.push(['HTTP service', `${config.options.externalIp}:${config.options.platform.dapi.nginx.http.port}`]); rows.push(['HTTP port', `${config.options.platform.dapi.nginx.http.port} ${httpPortState}`]); rows.push(['gRPC service', `${config.options.externalIp}:${config.options.platform.dapi.nginx.grpc.port}`]); diff --git a/src/util/getPaymentQueuePosition.js b/src/util/getPaymentQueuePosition.js new file mode 100644 index 00000000..a4b2ff24 --- /dev/null +++ b/src/util/getPaymentQueuePosition.js @@ -0,0 +1,19 @@ +function getPaymentQueuePosition(masternodeState, masternodeEnabledCount, coreBlocks) { + let paymentQueuePosition; + if (masternodeState.PoSeRevivedHeight > coreBlocks) { + paymentQueuePosition = masternodeState.PoSeRevivedHeight + + masternodeEnabledCount + - coreBlocks; + } else if (masternodeState.lastPaidHeight === 0) { + paymentQueuePosition = masternodeState.registeredHeight + + masternodeEnabledCount + - coreBlocks; + } else { + paymentQueuePosition = masternodeState.lastPaidHeight + + masternodeEnabledCount + - coreBlocks; + } + return paymentQueuePosition; +} + +module.exports = getPaymentQueuePosition; From c71129d9daf60b0b1d825dd9cd37058d731d7af2 Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 15 Dec 2020 18:41:20 -0800 Subject: [PATCH 43/44] fix: check platform explorer exists before query --- src/commands/status/platform.js | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index b625da34..e14f6a83 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -42,6 +42,10 @@ class CoreStatusCommand extends BaseCommand { dockerCompose.docker.getContainer('core'), ); + const explorerURLs = { + evonet: 'https://rpc.cloudwheels.net:26657/status', + }; + // Collect core data const { result: { @@ -79,14 +83,17 @@ class CoreStatusCommand extends BaseCommand { }, } = await tendermintNetInfoRes.json(); - const explorerBlockHeightRes = await fetch('https://rpc.cloudwheels.net:26657/status'); - const { - result: { - sync_info: { - latest_block_height: explorerLatestBlockHeight, + let explorerLatestBlockHeight; + if (explorerURLs[config.options.network]) { + const explorerBlockHeightRes = await fetch(explorerURLs[config.options.network]); + ({ + result: { + sync_info: { + latest_block_height: explorerLatestBlockHeight, + }, }, - }, - } = await explorerBlockHeightRes.json(); + } = await explorerBlockHeightRes.json()); + } // Check ports const httpPortStateRes = await fetch(`https://mnowatch.org/${config.options.platform.dapi.nginx.http.port}/`); @@ -150,7 +157,9 @@ class CoreStatusCommand extends BaseCommand { rows.push(['Network', platformNetwork]); rows.push(['Status', status]); rows.push(['Block height', blocks]); - rows.push(['Remote block height', explorerLatestBlockHeight]); + if (explorerURLs[config.options.network]) { + rows.push(['Remote block height', explorerLatestBlockHeight]); + } rows.push(['Peer count', platformPeers]); rows.push(['App hash', platformLatestAppHash]); rows.push(['HTTP service', `${config.options.externalIp}:${config.options.platform.dapi.nginx.http.port}`]); From d586a52eff368edb5e4fd1b47af3bb4c8e3c695b Mon Sep 17 00:00:00 2001 From: Leon White Date: Tue, 15 Dec 2020 18:47:59 -0800 Subject: [PATCH 44/44] fix: conditional checks for remote platform explorer --- src/commands/status/platform.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/commands/status/platform.js b/src/commands/status/platform.js index e14f6a83..9ef31a36 100644 --- a/src/commands/status/platform.js +++ b/src/commands/status/platform.js @@ -116,7 +116,7 @@ class CoreStatusCommand extends BaseCommand { status = 'not started'; } } - if (status === 'running' && platformCatchingUp === true) { + if (status === 'running' && platformCatchingUp === true && explorerURLs[config.options.network]) { status = `syncing ${((platformLatestBlockHeight / explorerLatestBlockHeight) * 100).toFixed(2)}%`; } @@ -130,10 +130,14 @@ class CoreStatusCommand extends BaseCommand { } let blocks; - if (platformLatestBlockHeight >= explorerLatestBlockHeight) { - blocks = chalk.green(platformLatestBlockHeight); + if (explorerURLs[config.options.network]) { + if (platformLatestBlockHeight >= explorerLatestBlockHeight) { + blocks = chalk.green(platformLatestBlockHeight); + } else { + blocks = chalk.red(platformLatestBlockHeight); + } } else { - blocks = chalk.red(platformLatestBlockHeight); + blocks = platformLatestBlockHeight; } if (httpPortState === 'OPEN') {