@constellation-network/node-pilot 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +26 -15
  2. package/bin/dev.js +1 -6
  3. package/bin/run.js +1 -1
  4. package/dist/base-command.d.ts +9 -0
  5. package/dist/base-command.js +20 -0
  6. package/dist/checks/check-hardware.js +3 -3
  7. package/dist/checks/check-initial-setup.js +2 -0
  8. package/dist/checks/check-layers.js +7 -7
  9. package/dist/checks/check-network.d.ts +2 -0
  10. package/dist/checks/check-network.js +46 -11
  11. package/dist/checks/check-node-ctl.js +4 -4
  12. package/dist/checks/check-project.d.ts +1 -0
  13. package/dist/checks/check-project.js +15 -4
  14. package/dist/checks/check-wallet.d.ts +3 -0
  15. package/dist/checks/check-wallet.js +37 -0
  16. package/dist/clm.d.ts +1 -0
  17. package/dist/clm.js +3 -0
  18. package/dist/commands/config/get.d.ts +6 -0
  19. package/dist/commands/config/get.js +57 -11
  20. package/dist/commands/config/set.d.ts +0 -1
  21. package/dist/commands/config/set.js +13 -11
  22. package/dist/commands/config.js +17 -22
  23. package/dist/commands/info.js +3 -2
  24. package/dist/commands/logs.d.ts +1 -1
  25. package/dist/commands/logs.js +7 -3
  26. package/dist/commands/restart.d.ts +10 -2
  27. package/dist/commands/restart.js +65 -9
  28. package/dist/commands/shutdown.js +3 -3
  29. package/dist/commands/status.js +4 -0
  30. package/dist/commands/test.js +10 -3
  31. package/dist/config-store.d.ts +47 -31
  32. package/dist/config-store.js +98 -42
  33. package/dist/helpers/config-helper.js +2 -2
  34. package/dist/helpers/env-templates.d.ts +4 -3
  35. package/dist/helpers/env-templates.js +28 -20
  36. package/dist/helpers/key-file-helper.d.ts +2 -0
  37. package/dist/helpers/key-file-helper.js +51 -16
  38. package/dist/helpers/project-helper.d.ts +2 -2
  39. package/dist/helpers/project-helper.js +37 -38
  40. package/dist/helpers/prompt-helper.d.ts +0 -1
  41. package/dist/helpers/prompt-helper.js +15 -15
  42. package/dist/services/archiver-service.d.ts +17 -0
  43. package/dist/services/archiver-service.js +104 -0
  44. package/dist/services/cluster-service.d.ts +10 -6
  45. package/dist/services/cluster-service.js +45 -45
  46. package/dist/services/docker-service.d.ts +9 -0
  47. package/dist/{helpers/docker-helper.js → services/docker-service.js} +11 -9
  48. package/dist/services/fastforward-service.js +3 -3
  49. package/dist/services/get-random-node.js +1 -1
  50. package/dist/{helpers/github-helper.d.ts → services/github-service.d.ts} +1 -1
  51. package/dist/{helpers/github-helper.js → services/github-service.js} +1 -1
  52. package/dist/services/node-service.js +14 -14
  53. package/dist/services/notify-service.d.ts +1 -0
  54. package/dist/services/notify-service.js +1 -0
  55. package/dist/services/systemd-service.d.ts +3 -0
  56. package/dist/services/systemd-service.js +45 -0
  57. package/dist/test.d.ts +1 -0
  58. package/dist/test.js +50 -0
  59. package/dist/types.d.ts +6 -0
  60. package/install-dependencies.sh +0 -2
  61. package/oclif.manifest.json +33 -4
  62. package/package.json +9 -8
  63. package/projects/custom/pilot.json +9 -0
  64. package/projects/hypergraph/Dockerfile +24 -18
  65. package/projects/hypergraph/docker-compose.yml +14 -14
  66. package/projects/hypergraph/networks/integrationnet/gl0.env +4 -0
  67. package/projects/hypergraph/networks/integrationnet/gl1.env +4 -0
  68. package/projects/hypergraph/networks/integrationnet/network.env +8 -0
  69. package/projects/hypergraph/networks/{integrationnet.env → integrationnet/source-nodes.env} +1 -9
  70. package/projects/hypergraph/networks/mainnet/gl0.env +4 -0
  71. package/projects/hypergraph/networks/mainnet/gl1.env +4 -0
  72. package/projects/hypergraph/networks/mainnet/network.env +8 -0
  73. package/projects/hypergraph/networks/{mainnet.env → mainnet/source-nodes.env} +0 -8
  74. package/projects/hypergraph/networks/testnet/gl0.env +5 -0
  75. package/projects/hypergraph/networks/testnet/gl1.env +4 -0
  76. package/projects/hypergraph/networks/testnet/network.env +8 -0
  77. package/projects/hypergraph/networks/{testnet.env → testnet/source-nodes.env} +0 -8
  78. package/projects/hypergraph/scripts/check-version.sh +31 -0
  79. package/projects/hypergraph/scripts/install.sh +30 -25
  80. package/projects/hypergraph/seedlist +268 -0
  81. package/scripts/autoheal.sh +8 -0
  82. package/scripts/restart_logger.sh +3 -0
  83. package/scripts/services/io.constellationnetwork.nodepilot.Updater.plist +16 -0
  84. package/scripts/services/node-pilot-autoheal.service +12 -0
  85. package/scripts/services/node-pilot-restarter.service +11 -0
  86. package/scripts/services/node-pilot-updater.service +13 -0
  87. package/scripts/update_logger.sh +3 -0
  88. package/dist/helpers/docker-helper.d.ts +0 -7
  89. package/projects/hypergraph/layers/gl1.env +0 -3
  90. package/projects/scripts/docker-cleanup.sh +0 -64
package/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @constellation-network/node-pilot
21
21
  $ cpilot COMMAND
22
22
  running command...
23
23
  $ cpilot (--version|-v)
24
- @constellation-network/node-pilot/0.0.8 darwin-arm64 node-v22.15.0
24
+ @constellation-network/node-pilot/0.0.10 darwin-arm64 node-v22.15.0
25
25
  $ cpilot --help [COMMAND]
26
26
  USAGE
27
27
  $ cpilot COMMAND
@@ -42,8 +42,8 @@ If no command is entered, node-pilot will automatically perform a series of chec
42
42
  * [`cpilot config set NAME VALUE`](#cpilot-config-set-name-value)
43
43
  * [`cpilot help [COMMAND]`](#cpilot-help-command)
44
44
  * [`cpilot info`](#cpilot-info)
45
- * [`cpilot logs [LAYER]`](#cpilot-logs-layer)
46
- * [`cpilot restart`](#cpilot-restart)
45
+ * [`cpilot logs LAYER`](#cpilot-logs-layer)
46
+ * [`cpilot restart [LAYER]`](#cpilot-restart-layer)
47
47
  * [`cpilot shutdown`](#cpilot-shutdown)
48
48
  * [`cpilot status`](#cpilot-status)
49
49
 
@@ -62,7 +62,7 @@ EXAMPLES
62
62
  $ cpilot config
63
63
  ```
64
64
 
65
- _See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/config.ts)_
65
+ _See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.10/src/commands/config.ts)_
66
66
 
67
67
  ## `cpilot config get [NAME]`
68
68
 
@@ -86,7 +86,7 @@ EXAMPLES
86
86
  $ cpilot config get gl0:CL_PUBLIC_HTTP_PORT
87
87
  ```
88
88
 
89
- _See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/config/get.ts)_
89
+ _See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.10/src/commands/config/get.ts)_
90
90
 
91
91
  ## `cpilot config set NAME VALUE`
92
92
 
@@ -109,7 +109,7 @@ EXAMPLES
109
109
  $ cpilot config set gl0:CL_PUBLIC_HTTP_PORT 9000
110
110
  ```
111
111
 
112
- _See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/config/set.ts)_
112
+ _See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.10/src/commands/config/set.ts)_
113
113
 
114
114
  ## `cpilot help [COMMAND]`
115
115
 
@@ -146,15 +146,15 @@ EXAMPLES
146
146
  $ cpilot info
147
147
  ```
148
148
 
149
- _See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/info.ts)_
149
+ _See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.10/src/commands/info.ts)_
150
150
 
151
- ## `cpilot logs [LAYER]`
151
+ ## `cpilot logs LAYER`
152
152
 
153
153
  view validator node runtime logs
154
154
 
155
155
  ```
156
156
  USAGE
157
- $ cpilot logs [LAYER] [-f] [-n <value>]
157
+ $ cpilot logs LAYER [-f] [-n <value>]
158
158
 
159
159
  ARGUMENTS
160
160
  LAYER network layer to view. e.g. gl0
@@ -170,15 +170,26 @@ EXAMPLES
170
170
  $ cpilot logs
171
171
  ```
172
172
 
173
- _See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/logs.ts)_
173
+ _See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.10/src/commands/logs.ts)_
174
174
 
175
- ## `cpilot restart`
175
+ ## `cpilot restart [LAYER]`
176
176
 
177
177
  A full shutdown of the validator node, then restart
178
178
 
179
179
  ```
180
180
  USAGE
181
- $ cpilot restart
181
+ $ cpilot restart [LAYER] [-p ] [--autostart] [--update]
182
+
183
+ ARGUMENTS
184
+ LAYER network layer to restart. e.g. gl0
185
+
186
+ FLAGS
187
+ --autostart restart each running project if it has been stopped
188
+ --update update each project if a new version is available
189
+
190
+ GLOBAL FLAGS
191
+ -p, --project=<option> Specify the project name to use
192
+ <options: >
182
193
 
183
194
  DESCRIPTION
184
195
  A full shutdown of the validator node, then restart
@@ -187,7 +198,7 @@ EXAMPLES
187
198
  $ cpilot restart
188
199
  ```
189
200
 
190
- _See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/restart.ts)_
201
+ _See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.10/src/commands/restart.ts)_
191
202
 
192
203
  ## `cpilot shutdown`
193
204
 
@@ -204,7 +215,7 @@ EXAMPLES
204
215
  $ cpilot shutdown
205
216
  ```
206
217
 
207
- _See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/shutdown.ts)_
218
+ _See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.10/src/commands/shutdown.ts)_
208
219
 
209
220
  ## `cpilot status`
210
221
 
@@ -218,5 +229,5 @@ DESCRIPTION
218
229
  Display node status and configuration settings
219
230
  ```
220
231
 
221
- _See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/status.ts)_
232
+ _See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.10/src/commands/status.ts)_
222
233
  <!-- commandsstop -->
package/bin/dev.js CHANGED
@@ -5,15 +5,10 @@ const skipDefaultCommand = {
5
5
  if (process.argv.length === 2) {
6
6
  process.argv[2] = 'status';
7
7
  }
8
- else if (process.argv.length > 2 && process.argv[2].startsWith('-') && !skipDefaultCommand[process.argv[2]]) {
8
+ else if (process.argv.length > 2 && process.argv.every(a => a.startsWith('-')) && !skipDefaultCommand[process.argv[2]]) {
9
9
  process.argv.splice(2, 0 , 'status');
10
10
  }
11
11
 
12
12
  import {execute} from '@oclif/core'
13
13
 
14
14
  await execute({development: true, dir: import.meta.url})
15
-
16
- // eslint-disable-next-line no-warning-comments
17
- // TODO
18
- // cpilot config set project pacaswap-metagraph
19
- // cpilot config --project pacaswap-metagraph
package/bin/run.js CHANGED
@@ -6,7 +6,7 @@ const skipDefaultCommand = {
6
6
  if (process.argv.length === 2) {
7
7
  process.argv[2] = 'status';
8
8
  }
9
- else if (process.argv.length > 2 && process.argv[2].startsWith('-') && !skipDefaultCommand[process.argv[2]]) {
9
+ else if (process.argv.length > 2 && process.argv.every(a => a.startsWith('-')) && !skipDefaultCommand[process.argv[2]]) {
10
10
  process.argv.splice(2, 0 , 'status');
11
11
  }
12
12
 
@@ -0,0 +1,9 @@
1
+ import { Command } from '@oclif/core';
2
+ export declare abstract class BaseCommand extends Command {
3
+ static baseFlags: {
4
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
5
+ };
6
+ checkProject(flags: {
7
+ project?: string;
8
+ }): void;
9
+ }
@@ -0,0 +1,20 @@
1
+ // src/base.ts
2
+ import { Command, Flags } from '@oclif/core';
3
+ import { configStore } from "./config-store.js";
4
+ import { configHelper } from "./helpers/config-helper.js";
5
+ export class BaseCommand extends Command {
6
+ static baseFlags = {
7
+ project: Flags.string({
8
+ char: 'p',
9
+ description: 'Specify the project name to use',
10
+ helpGroup: 'GLOBAL', // Optional: Group this flag in the help output
11
+ options: configStore.getProjects()
12
+ })
13
+ };
14
+ checkProject(flags) {
15
+ configHelper.assertProject('No project found. ');
16
+ if (flags.project) {
17
+ configStore.setActiveProject(flags.project);
18
+ }
19
+ }
20
+ }
@@ -20,7 +20,7 @@ export const checkHardware = {
20
20
  const numOfCores = os.availableParallelism();
21
21
  let allPassed = true;
22
22
  const formatActual = (value, recommended, units = '') => {
23
- const passed = Number(value) >= recommended;
23
+ const passed = Math.ceil(Number(value)) >= recommended;
24
24
  allPassed = allPassed && passed;
25
25
  return passed ? chalk.greenBright(value + units) : chalk.redBright(value + units);
26
26
  };
@@ -32,8 +32,8 @@ export const checkHardware = {
32
32
  { headerColor: 'white', value: 'ACTUAL' },
33
33
  ];
34
34
  const rows = [
35
- [fc("Disk size"), fc("320 GB"), formatActual(totalSpaceGB, 320, " GB")],
36
- [fc("System memory"), fc("8 GB"), formatActual(totalMemoryGB, 8, " GB")],
35
+ [fc("Disk size"), fc("240 GB"), formatActual(totalSpaceGB, 240, " GB")],
36
+ [fc("System memory"), fc("16 GB"), formatActual(totalMemoryGB, 16, " GB")],
37
37
  [fc("CPU cores"), fc("8 cores"), formatActual(numOfCores, 8, " cores")],
38
38
  ];
39
39
  clm.echo(ttyTable(header, rows).render() + "\n");
@@ -1,5 +1,6 @@
1
1
  import chalk from "chalk";
2
2
  import { configStore } from "../config-store.js";
3
+ import { systemdService } from "../services/systemd-service.js";
3
4
  import { checkDependencies } from "./check-dependencies.js";
4
5
  import { checkHardware } from "./check-hardware.js";
5
6
  export const checkInitialSetup = {
@@ -13,5 +14,6 @@ export const checkInitialSetup = {
13
14
  console.log(" " + chalk.whiteBright("NODE PILOT") + " ");
14
15
  console.log(chalk.whiteBright(" ****************************************"));
15
16
  await checkHardware.systemRequirements();
17
+ await systemdService.install();
16
18
  },
17
19
  };
@@ -2,7 +2,7 @@ import { input } from "@inquirer/prompts";
2
2
  import chalk from "chalk";
3
3
  import { clm } from "../clm.js";
4
4
  import { configStore } from "../config-store.js";
5
- import { dockerHelper } from "../helpers/docker-helper.js";
5
+ import { dockerService } from "../services/docker-service.js";
6
6
  import { nodeService } from "../services/node-service.js";
7
7
  export const checkLayers = {
8
8
  async layersReadyToJoin() {
@@ -27,9 +27,9 @@ export const checkLayers = {
27
27
  }
28
28
  await input({ default: 'y', message: 'Would you like to start the validator(s)? (y/n): ' }).then(async (answer) => {
29
29
  if (answer.toLowerCase() === 'y') {
30
- await dockerHelper.dockerBuild();
30
+ await dockerService.dockerBuild();
31
31
  clm.preStep('Starting the node...');
32
- await dockerHelper.dockerUp();
32
+ await dockerService.dockerUp();
33
33
  await nodeService.pollForLayersState(layersToRun);
34
34
  }
35
35
  else {
@@ -40,11 +40,11 @@ export const checkLayers = {
40
40
  else if (notRunningLayers.length > 0) {
41
41
  const layersNotRunning = notRunningLayers.map(r => r.layer);
42
42
  clm.preStep('The following Validator Node layers are not running: ' + chalk.cyan(layersNotRunning.join(', ')));
43
- await input({ default: 'y', message: 'Would you like to restart the docker containers? (y/n): ' }).then(async (answer) => {
43
+ await input({ default: 'y', message: 'Would you like to start the validator(s)? (y/n): ' }).then(async (answer) => {
44
44
  if (answer.toLowerCase() === 'y') {
45
- clm.preStep('Restarting docker containers...');
46
- await dockerHelper.dockerUp();
47
- await nodeService.pollForLayersState(layersToRun);
45
+ clm.preStep('Starting docker containers...');
46
+ await dockerService.dockerStartLayers(layersNotRunning);
47
+ await nodeService.pollForLayersState(layersNotRunning);
48
48
  }
49
49
  else {
50
50
  clm.echo('Node not started.');
@@ -1,7 +1,9 @@
1
1
  export declare const checkNetwork: {
2
+ checkForExistingNodeIdInCluster(): Promise<void>;
2
3
  checkSeedList(): Promise<void>;
3
4
  configureIpAddress(): Promise<void>;
4
5
  detectExternalIpAddress(): Promise<void>;
5
6
  enterIpAddressManually(): Promise<string>;
6
7
  fetchIPAddress(): Promise<string>;
8
+ isNetworkConnectable(): Promise<boolean>;
7
9
  };
@@ -4,7 +4,27 @@ import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import { clm } from "../clm.js";
6
6
  import { configStore } from "../config-store.js";
7
+ import { clusterService } from "../services/cluster-service.js";
8
+ import { dockerService } from "../services/docker-service.js";
9
+ import { shellService } from "../services/shell-service.js";
7
10
  export const checkNetwork = {
11
+ async checkForExistingNodeIdInCluster() {
12
+ if (configStore.hasProjectFlag('duplicateNodeIdChecked')) {
13
+ return;
14
+ }
15
+ clm.preStep('Checking for existing Node ID in cluster...');
16
+ const { nodeId } = configStore.getProjectInfo();
17
+ const clusterInfo = await clusterService.getClusterInfo();
18
+ const found = clusterInfo.some(node => node.id === nodeId);
19
+ const isDockerRunning = await dockerService.isRunning();
20
+ if (!isDockerRunning && found) {
21
+ clm.warn('Node ID already exists in the cluster.');
22
+ clm.warn('You need to shutdown your node from a previous installation before continuing.');
23
+ clm.error(`Or to change the node ID, configure the Key File: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Key File')}`);
24
+ }
25
+ configStore.setProjectFlag('duplicateNodeIdChecked', true);
26
+ clm.postStep('No duplicate Node found.');
27
+ },
8
28
  async checkSeedList() {
9
29
  if (configStore.hasProjectFlag('seedListChecked')) {
10
30
  return;
@@ -23,10 +43,11 @@ export const checkNetwork = {
23
43
  }
24
44
  const printNotFoundError = () => {
25
45
  clm.warn(`Node ID not found in ${type.toUpperCase()} seed list. You may try again later.`);
26
- clm.error(`To change the Key File: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Key File')}`);
46
+ clm.warn(`To change the Key File: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Key File')}`);
47
+ clm.error(`To change the Network: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Network')}`);
27
48
  };
28
49
  if (type === 'mainnet') {
29
- // the mainnet seed list comed from a network release files
50
+ // the mainnet seed list comed from a network release
30
51
  printNotFoundError();
31
52
  }
32
53
  else {
@@ -52,11 +73,11 @@ export const checkNetwork = {
52
73
  }
53
74
  },
54
75
  async configureIpAddress() {
55
- const { CL_EXTERNAL_IP: currentIpAddress } = configStore.getEnvCommonInfo();
76
+ const { CL_EXTERNAL_IP: currentIpAddress } = configStore.getEnvInfo();
56
77
  const detectedIpAddress = await checkNetwork.fetchIPAddress().catch(() => '');
57
78
  if (!currentIpAddress && !detectedIpAddress) {
58
79
  const newIpAddress = await checkNetwork.enterIpAddressManually();
59
- configStore.setEnvCommonInfo({ CL_EXTERNAL_IP: newIpAddress });
80
+ configStore.setEnvInfo({ CL_EXTERNAL_IP: newIpAddress });
60
81
  return;
61
82
  }
62
83
  if (currentIpAddress) {
@@ -85,7 +106,7 @@ export const checkNetwork = {
85
106
  else if (answer === 'manual') {
86
107
  selectedIpAddress = await checkNetwork.enterIpAddressManually();
87
108
  }
88
- configStore.setEnvCommonInfo({ CL_EXTERNAL_IP: selectedIpAddress });
109
+ configStore.setEnvInfo({ CL_EXTERNAL_IP: selectedIpAddress });
89
110
  },
90
111
  async detectExternalIpAddress() {
91
112
  const externalIp = await this.fetchIPAddress()
@@ -94,7 +115,7 @@ export const checkNetwork = {
94
115
  return this.enterIpAddressManually();
95
116
  });
96
117
  clm.postStep("\nExternal IP address: " + chalk.cyan(externalIp) + "\n");
97
- configStore.setEnvCommonInfo({ CL_EXTERNAL_IP: externalIp });
118
+ configStore.setEnvInfo({ CL_EXTERNAL_IP: externalIp });
98
119
  },
99
120
  async enterIpAddressManually() {
100
121
  return input({
@@ -110,11 +131,25 @@ export const checkNetwork = {
110
131
  });
111
132
  },
112
133
  async fetchIPAddress() {
113
- return fetch('https://ifconfig.me/ip')
114
- .then(res => {
115
- if (res.ok)
116
- return res.text();
117
- throw new Error('Failed to fetch IP address');
134
+ return shellService.runCommandWithOutput('curl -4 https://ifconfig.me/ip');
135
+ },
136
+ async isNetworkConnectable() {
137
+ return clusterService.getClusterInfo()
138
+ .then(async (nodes) => {
139
+ const someAreReady = nodes.some(node => node.state === 'Ready');
140
+ if (!someAreReady) {
141
+ if (nodes.length > 0) {
142
+ clm.warn(`Found ${nodes.length} nodes in the cluster, but none are READY.`);
143
+ }
144
+ throw new Error(`Network is not connectable.`);
145
+ }
146
+ clm.debug(`Network is live. Found ${nodes.length} nodes in the cluster.`);
147
+ configStore.setClusterStats({ total: nodes.length });
148
+ return true;
149
+ })
150
+ .catch(() => {
151
+ clm.error(`Network is not in service. Please try again later.`);
152
+ return false;
118
153
  });
119
154
  }
120
155
  };
@@ -5,11 +5,11 @@ import path from "node:path";
5
5
  import yaml from "yaml";
6
6
  import { clm } from "../clm.js";
7
7
  import { configStore } from "../config-store.js";
8
- import { dockerHelper } from "../helpers/docker-helper.js";
9
8
  import { keyFileHelper } from "../helpers/key-file-helper.js";
10
9
  import { promptHelper } from "../helpers/prompt-helper.js";
11
- import { shellService } from "../services/shell-service.js";
10
+ import { dockerService } from "../services/docker-service.js";
12
11
  import { nodeService } from "../services/node-service.js";
12
+ import { shellService } from "../services/shell-service.js";
13
13
  export const checkNodeCtl = {
14
14
  async check4Migration() {
15
15
  if (configStore.hasProjectFlag('nodeCtlChecked')) {
@@ -22,7 +22,7 @@ export const checkNodeCtl = {
22
22
  }
23
23
  const hasNodeAdminUser = fs.existsSync('/home/nodeadmin');
24
24
  if (hasNodeAdminUser) {
25
- const isDockerRunning = await dockerHelper.isRunning();
25
+ const isDockerRunning = await dockerService.isRunning();
26
26
  const isPortOpen = await nodeService.isPortInUse(9000);
27
27
  clm.step(chalk.bold('NODECTL has been detected.'));
28
28
  if (!isDockerRunning && isPortOpen) {
@@ -71,7 +71,7 @@ export const checkNodeCtl = {
71
71
  // prompt for password
72
72
  const keyPassword = await password({ message: 'Enter the key file password:' });
73
73
  const keyAlias = await input({ message: 'Enter the key file alias:' });
74
- configStore.setEnvCommonInfo({ CL_KEYALIAS: keyAlias, CL_KEYSTORE: pilotKeyPath, CL_PASSWORD: keyPassword });
74
+ configStore.setEnvInfo({ CL_KEYALIAS: keyAlias, CL_KEYSTORE: pilotKeyPath, CL_PASSWORD: keyPassword });
75
75
  try {
76
76
  const dagAddress = await keyFileHelper.getAddress();
77
77
  const nodeId = await keyFileHelper.getId();
@@ -1,4 +1,5 @@
1
1
  export declare const checkProject: {
2
+ hasVersionChanged(): Promise<boolean>;
2
3
  projectInstallation(): Promise<void>;
3
4
  releaseVersion(): Promise<void>;
4
5
  runInstall(): Promise<boolean>;
@@ -1,15 +1,21 @@
1
1
  import { input, select } from "@inquirer/prompts";
2
+ import chalk from "chalk";
2
3
  import ora from 'ora';
3
4
  import { clm } from "../clm.js";
4
5
  import { configStore } from "../config-store.js";
5
6
  import { configHelper } from "../helpers/config-helper.js";
6
- import { dockerHelper } from "../helpers/docker-helper.js";
7
7
  import { projectHelper } from "../helpers/project-helper.js";
8
8
  import { promptHelper } from "../helpers/prompt-helper.js";
9
9
  import { clusterService } from "../services/cluster-service.js";
10
+ import { dockerService } from "../services/docker-service.js";
10
11
  import { shellService } from "../services/shell-service.js";
11
12
  import { checkNetwork } from "./check-network.js";
12
13
  export const checkProject = {
14
+ async hasVersionChanged() {
15
+ const clusterVersion = await clusterService.getReleaseVersion();
16
+ const rInfo = await configHelper.getReleaseInfo();
17
+ return !rInfo || (rInfo.version !== clusterVersion);
18
+ },
13
19
  async projectInstallation() {
14
20
  let updateNetworkType = false;
15
21
  let updateLayers = false;
@@ -86,9 +92,9 @@ export const checkProject = {
86
92
  clm.postStep(`Network files are already installed for ${nInfo.type} version ${clusterVersion}`);
87
93
  return false;
88
94
  }
89
- const isRunning = await dockerHelper.isRunning();
95
+ const isRunning = await dockerService.isRunning();
90
96
  if (isRunning) {
91
- await dockerHelper.dockerDown();
97
+ await dockerService.dockerDown();
92
98
  }
93
99
  const silent = !process.env.DEBUG;
94
100
  const spinner = ora('Running install script...');
@@ -99,10 +105,15 @@ export const checkProject = {
99
105
  else {
100
106
  clm.preStep('Running install script...');
101
107
  }
108
+ // const node = await clusterService.getClusterNodeInfo();
109
+ // const NODE_URL = `http://${node.host}:${node.publicPort}`;
102
110
  // NOTE: may be different for metagraphs
103
111
  await shellService.runProjectCommand(`scripts/install.sh ${nInfo.type}`, undefined, silent)
104
112
  .catch(() => {
105
113
  spinner.stop();
114
+ if (silent) {
115
+ clm.error(`Install script failed. run: ${chalk.cyan("DEBUG=true cpilot")} for more details`);
116
+ }
106
117
  clm.error('Install script failed. Please run cpilot again after correcting the error');
107
118
  });
108
119
  if (silent) {
@@ -118,7 +129,7 @@ export const checkProject = {
118
129
  async runUpgrade() {
119
130
  const changed = await this.runInstall();
120
131
  if (changed) {
121
- await dockerHelper.dockerBuild();
132
+ await dockerService.dockerBuild();
122
133
  }
123
134
  }
124
135
  };
@@ -0,0 +1,3 @@
1
+ export declare const checkWallet: {
2
+ checkCollateral(): Promise<void>;
3
+ };
@@ -0,0 +1,37 @@
1
+ import chalk from "chalk";
2
+ import { clm } from "../clm.js";
3
+ import { configStore } from "../config-store.js";
4
+ import { promptHelper } from "../helpers/prompt-helper.js";
5
+ export const checkWallet = {
6
+ async checkCollateral() {
7
+ const { type } = configStore.getNetworkInfo();
8
+ if (type !== 'mainnet')
9
+ return;
10
+ const skipCollateralCheck = configStore.hasProjectFlag('skipCollateralCheck');
11
+ if (skipCollateralCheck)
12
+ return;
13
+ clm.preStep('Checking for required collateral...');
14
+ const { dagAddress } = configStore.getProjectInfo();
15
+ const url = `https://be-mainnet.constellationnetwork.io/addresses/${dagAddress}/balance`;
16
+ let hasError = false;
17
+ const balance = await fetch(url)
18
+ .then(res => res.json())
19
+ .then(i => i.data.balance)
20
+ .catch(() => {
21
+ clm.warn(`Failed to fetch balance from ${url}`);
22
+ hasError = true;
23
+ });
24
+ if (!hasError && balance < 25_000_000_000_000) {
25
+ clm.warn(`You need at least 250k DAG to run a validator node. Your account ${chalk.cyan(dagAddress)} has a balance of ${chalk.cyan(balance)} DAG.`);
26
+ hasError = true;
27
+ }
28
+ if (hasError) {
29
+ clm.echo('You may continue and skip this check in the future');
30
+ await promptHelper.doYouWishToContinue();
31
+ }
32
+ else {
33
+ clm.postStep('Collateral check PASSED');
34
+ }
35
+ configStore.setProjectFlag('skipCollateralCheck', true);
36
+ }
37
+ };
package/dist/clm.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export declare const clm: {
2
2
  debug(msg: string): void;
3
3
  echo(msg: string): void;
4
+ echoRepeatLine(char: string): void;
4
5
  error(msg: string, silent?: boolean): never;
5
6
  postStep(s: string): void;
6
7
  preStep(s: string): void;
package/dist/clm.js CHANGED
@@ -11,6 +11,9 @@ export const clm = {
11
11
  echo(msg) {
12
12
  console.log(msg);
13
13
  },
14
+ echoRepeatLine(char) {
15
+ process.stdout.write('\r' + char);
16
+ },
14
17
  error(msg, silent = true) {
15
18
  console.error(chalk.red(msg));
16
19
  process.exit(silent ? 0 : 1);
@@ -5,5 +5,11 @@ export default class ConfigGet extends Command {
5
5
  };
6
6
  static description: string;
7
7
  static examples: string[];
8
+ getKeyInfo(): {
9
+ KEY_ALIAS: string;
10
+ KEY_FILE: string;
11
+ NODE_ADDRESS: string;
12
+ NODE_ID: string;
13
+ };
8
14
  run(): Promise<void>;
9
15
  }
@@ -1,5 +1,6 @@
1
1
  import { Args, Command } from '@oclif/core';
2
- import { commonEnvNames, configStore, layerEnvNames } from "../../config-store.js";
2
+ import { clm } from "../../clm.js";
3
+ import { configStore, layerEnvNames, networkEnvNames } from "../../config-store.js";
3
4
  import { configHelper } from "../../helpers/config-helper.js";
4
5
  export default class ConfigGet extends Command {
5
6
  static args = {
@@ -11,27 +12,72 @@ export default class ConfigGet extends Command {
11
12
  '<%= config.bin %> <%= command.id %> CL_EXTERNAL_IP',
12
13
  '<%= config.bin %> <%= command.id %> gl0:CL_PUBLIC_HTTP_PORT',
13
14
  ];
15
+ getKeyInfo() {
16
+ const { dagAddress, nodeId } = configStore.getProjectInfo();
17
+ const { CL_KEYALIAS, CL_KEYSTORE } = configStore.getEnvInfo();
18
+ return {
19
+ KEY_ALIAS: CL_KEYALIAS,
20
+ KEY_FILE: CL_KEYSTORE,
21
+ NODE_ADDRESS: dagAddress,
22
+ NODE_ID: nodeId,
23
+ };
24
+ }
14
25
  async run() {
15
26
  configHelper.assertProject('No configuration found. ');
16
27
  const { args } = await this.parse(ConfigGet);
17
- const info = configStore.getEnvInfo();
28
+ // const info = configStore.getEnvInfo();
18
29
  const { layersToRun } = configStore.getProjectInfo();
19
- const common = info.common;
20
- const layers = info.layers;
30
+ const { type: network } = configStore.getNetworkInfo();
31
+ const networkEnv = configStore.getEnvNetworkInfo(network);
32
+ // const networkProp = info.network as Record<string, string>;
33
+ // const layers = info.layers as Record<string, Record<string, string>>;
34
+ const gl = (l) => configStore.getEnvLayerInfo(network, l);
21
35
  if (Object.keys(args).length === 0 || args.name === undefined) {
22
- const commonsList = Object.keys(commonEnvNames).sort().map(k => ({ name: k, value: common[k] }));
23
- const layersList = layersToRun.map(l => (Object.keys(layerEnvNames).map(k => ({ name: `${l}:${k}`, value: layers[l][k] }))));
24
- // const layersList = layersToRun.map(l => (Object.keys(layerEnvNames).map(k => `${l}:${k}="${green(layers[l][k] || '')}"`)))
25
- configHelper.showEnvInfoList(commonsList);
36
+ const networkList = Object.keys(networkEnvNames).sort().map(k => ({ name: k, value: networkEnv[k] }));
37
+ const layersList = layersToRun.map(l => (Object.keys(layerEnvNames).map(k => ({ name: `${l}:${k}`, value: gl(l)[k] }))));
38
+ const keyInfo = this.getKeyInfo();
39
+ const keyInfoList = Object.keys(keyInfo).map(k => ({ name: 'key:' + k, value: keyInfo[k] }));
40
+ configHelper.showEnvInfoList(networkList);
41
+ configHelper.showEnvInfoList(keyInfoList);
26
42
  configHelper.showEnvInfoList(layersList.flat());
27
43
  }
28
44
  else if (args.name.includes(':')) {
29
45
  const [layer, name] = args.name.split(':');
30
- configHelper.showEnvInfo(args.name, layers[layer][name]);
46
+ if (layer === 'key') {
47
+ const keyInfo = this.getKeyInfo();
48
+ if (Object.hasOwn(keyInfo, name)) {
49
+ configHelper.showEnvInfo(args.name, keyInfo[name]);
50
+ }
51
+ else {
52
+ clm.warn('Invalid key property. Valid properties are: ' + Object.keys(keyInfo).join(', '));
53
+ }
54
+ }
55
+ else if (!layersToRun.includes(layer)) {
56
+ clm.warn(`Layer ${layer} is not running. Valid layers are: ` + layersToRun.join(', '));
57
+ }
58
+ else if (Object.hasOwn(layerEnvNames, name)) {
59
+ configHelper.showEnvInfo(args.name, gl(layer)[name]);
60
+ }
61
+ else {
62
+ clm.warn('Invalid layer property. Valid properties are: ' + Object.keys(layerEnvNames).join(', '));
63
+ }
64
+ }
65
+ else if (args.name === 'key') {
66
+ const keyInfo = this.getKeyInfo();
67
+ const keyInfoList = Object.keys(keyInfo).map(k => ({ name: 'key:' + k, value: keyInfo[k] }));
68
+ configHelper.showEnvInfoList(keyInfoList);
69
+ }
70
+ else if (layersToRun.includes(args.name)) {
71
+ const layer = args.name;
72
+ const list = Object.keys(layerEnvNames).map(k => ({ name: `${layer}:${k}`, value: gl(layer)[k] }));
73
+ configHelper.showEnvInfoList(list);
31
74
  }
32
75
  else {
33
- // const props = keyof EnvCommonInfo
34
- configHelper.showEnvInfo(args.name, common[args.name]);
76
+ if (!Object.hasOwn(networkEnvNames, args.name)) {
77
+ clm.warn('Invalid network-wide property. Valid properties are: ' + Object.keys(networkEnvNames).join(', '));
78
+ return;
79
+ }
80
+ configHelper.showEnvInfo(args.name, networkEnv[args.name]);
35
81
  }
36
82
  }
37
83
  }
@@ -6,6 +6,5 @@ export default class ConfigSet extends Command {
6
6
  };
7
7
  static description: string;
8
8
  static examples: string[];
9
- logErrorAndExit(message: string): void;
10
9
  run(): Promise<void>;
11
10
  }