@constellation-network/node-pilot 0.0.6 → 0.0.8

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 (42) hide show
  1. package/README.md +14 -13
  2. package/dist/checks/check-dependencies.d.ts +1 -0
  3. package/dist/checks/check-dependencies.js +44 -0
  4. package/dist/checks/check-initial-setup.js +6 -4
  5. package/dist/checks/check-network.d.ts +1 -0
  6. package/dist/checks/check-network.js +48 -0
  7. package/dist/checks/check-node-ctl.d.ts +5 -0
  8. package/dist/checks/check-node-ctl.js +88 -0
  9. package/dist/checks/check-project.js +22 -7
  10. package/dist/clm.js +1 -1
  11. package/dist/commands/logs.d.ts +1 -0
  12. package/dist/commands/logs.js +5 -3
  13. package/dist/commands/status.js +4 -0
  14. package/dist/commands/test.d.ts +1 -0
  15. package/dist/commands/test.js +27 -5
  16. package/dist/config-store.d.ts +8 -5
  17. package/dist/config-store.js +10 -0
  18. package/dist/helpers/docker-helper.js +18 -5
  19. package/dist/helpers/env-templates.js +7 -7
  20. package/dist/helpers/key-file-helper.js +1 -1
  21. package/dist/helpers/project-helper.d.ts +1 -0
  22. package/dist/helpers/project-helper.js +52 -0
  23. package/dist/helpers/prompt-helper.d.ts +0 -1
  24. package/dist/helpers/prompt-helper.js +0 -51
  25. package/dist/services/cluster-service.d.ts +2 -1
  26. package/dist/services/cluster-service.js +10 -0
  27. package/dist/services/fastforward-service.js +9 -3
  28. package/dist/services/get-random-node.d.ts +2 -0
  29. package/dist/services/get-random-node.js +16 -0
  30. package/dist/services/node-service.d.ts +4 -0
  31. package/dist/services/node-service.js +15 -0
  32. package/dist/services/shell-service.d.ts +3 -1
  33. package/dist/services/shell-service.js +32 -6
  34. package/dist/types.d.ts +36 -3
  35. package/install-dependencies.sh +100 -0
  36. package/oclif.manifest.json +9 -1
  37. package/package.json +5 -2
  38. package/projects/hypergraph/networks/integrationnet.env +16 -8
  39. package/projects/hypergraph/networks/mainnet.env +16 -7
  40. package/projects/hypergraph/networks/testnet.env +16 -8
  41. package/projects/hypergraph/scripts/install-dependencies.sh +3 -3
  42. package/projects/hypergraph/scripts/install.sh +4 -6
@@ -6,4 +6,5 @@ export declare const projectHelper: {
6
6
  installEmbedded(name: string): Promise<void>;
7
7
  installFromGithub(_repo: string): Promise<never>;
8
8
  installHypergraph(): Promise<void>;
9
+ selectProject(): Promise<void>;
9
10
  };
@@ -1,3 +1,5 @@
1
+ import { input, select } from "@inquirer/prompts";
2
+ import chalk from "chalk";
1
3
  import fs from "node:fs";
2
4
  import path from "node:path";
3
5
  import { fileURLToPath } from 'node:url';
@@ -5,6 +7,7 @@ import { clm } from "../clm.js";
5
7
  import { configStore } from "../config-store.js";
6
8
  import { configHelper } from "./config-helper.js";
7
9
  import { getLayerEnvFileContent } from "./env-templates.js";
10
+ import { githubHelper } from "./github-helper.js";
8
11
  export const projectHelper = {
9
12
  async generateLayerEnvFiles(layers) {
10
13
  const { layersToRun, projectDir } = configStore.getProjectInfo();
@@ -81,5 +84,54 @@ export const projectHelper = {
81
84
  });
82
85
  await this.importNetworkEnvFiles();
83
86
  await this.importLayerEnvFiles();
87
+ },
88
+ async selectProject() {
89
+ // prompt user to install hypergraph or metagraph
90
+ const networkType = await select({
91
+ choices: [
92
+ { name: 'Hypergraph (Global layer)', value: 'hypergraph' },
93
+ { disabled: true, name: 'Metagraph (Dor, Pacaswap, and more)', value: 'metagraph' },
94
+ ],
95
+ message: 'Select network:'
96
+ });
97
+ if (networkType === 'hypergraph') {
98
+ await this.installHypergraph();
99
+ }
100
+ else if (networkType === 'metagraph') {
101
+ const project = await select({
102
+ choices: [
103
+ { name: 'Dor', value: 'dor' },
104
+ { name: 'Custom (Enter repo)', value: 'custom' },
105
+ ],
106
+ message: 'Select metagraph:'
107
+ });
108
+ const ghRepoRegex = /^https?:\/\/(?:www\.)?github\.com\/([A-Za-z0-9](?:-?[A-Za-z0-9]){0,38})\/([A-Za-z0-9._-]+)(?:\.git)?\/?$/;
109
+ if (project === 'dor') {
110
+ await this.installEmbedded('dor');
111
+ }
112
+ else if (project === 'custom') {
113
+ let repo = await input({
114
+ message: `Enter Github repository URL:`,
115
+ validate(value) {
116
+ const m = value.trim().match(ghRepoRegex);
117
+ if (m)
118
+ return true;
119
+ return 'Please enter a valid Github repo URL (e.g., https://github.com/user/repo or .git)';
120
+ }
121
+ });
122
+ if (repo.endsWith('.git'))
123
+ repo = repo.slice(0, -4);
124
+ const m = repo.trim().match(ghRepoRegex);
125
+ const userRepo = `${m[1]}/${m[2]}`; // owner/repo
126
+ clm.preStep(`Installing from Github repository: ${chalk.cyan(userRepo)}`);
127
+ if (await githubHelper.hasAssetInRelease('node-pilot', userRepo)) {
128
+ await this.installFromGithub(userRepo);
129
+ }
130
+ else {
131
+ clm.warn(`The repository ${repo} does not contain a release asset with the name "node-pilot"`);
132
+ await this.selectProject();
133
+ }
134
+ }
135
+ }
84
136
  }
85
137
  };
@@ -4,5 +4,4 @@ export declare const promptHelper: {
4
4
  doYouWishToContinue(defaultAnswer?: "n" | "y"): Promise<void>;
5
5
  selectLayers(): Promise<void>;
6
6
  selectNetwork(): Promise<void>;
7
- selectProject(): Promise<void>;
8
7
  };
@@ -2,8 +2,6 @@ import { checkbox, input, number, select } 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 { githubHelper } from "./github-helper.js";
6
- import { projectHelper } from "./project-helper.js";
7
5
  export const promptHelper = {
8
6
  async configureAutoRestart() {
9
7
  const answer = await input({
@@ -82,54 +80,5 @@ export const promptHelper = {
82
80
  });
83
81
  configStore.setNetworkInfo({ type: networkType, version: "latest" });
84
82
  configStore.setEnvCommonInfo(configStore.getNetworkEnvInfo(networkType));
85
- },
86
- async selectProject() {
87
- // prompt user to install hypergraph or metagraph
88
- const networkType = await select({
89
- choices: [
90
- { name: 'Hypergraph (Global layer)', value: 'hypergraph' },
91
- { disabled: true, name: 'Metagraph (Dor, Pacaswap, and more)', value: 'metagraph' },
92
- ],
93
- message: 'Select network:'
94
- });
95
- if (networkType === 'hypergraph') {
96
- await projectHelper.installHypergraph();
97
- }
98
- else if (networkType === 'metagraph') {
99
- const project = await select({
100
- choices: [
101
- { name: 'Dor', value: 'dor' },
102
- { name: 'Custom (Enter repo)', value: 'custom' },
103
- ],
104
- message: 'Select metagraph:'
105
- });
106
- const ghRepoRegex = /^https?:\/\/(?:www\.)?github\.com\/([A-Za-z0-9](?:-?[A-Za-z0-9]){0,38})\/([A-Za-z0-9._-]+)(?:\.git)?\/?$/;
107
- if (project === 'dor') {
108
- await projectHelper.installEmbedded('dor');
109
- }
110
- else if (project === 'custom') {
111
- let repo = await input({
112
- message: `Enter Github repository URL:`,
113
- validate(value) {
114
- const m = value.trim().match(ghRepoRegex);
115
- if (m)
116
- return true;
117
- return 'Please enter a valid Github repo URL (e.g., https://github.com/user/repo or .git)';
118
- }
119
- });
120
- if (repo.endsWith('.git'))
121
- repo = repo.slice(0, -4);
122
- const m = repo.trim().match(ghRepoRegex);
123
- const userRepo = `${m[1]}/${m[2]}`; // owner/repo
124
- clm.preStep(`Installing from Github repository: ${chalk.cyan(userRepo)}`);
125
- if (await githubHelper.hasAssetInRelease('node-pilot', userRepo)) {
126
- await projectHelper.installFromGithub(userRepo);
127
- }
128
- else {
129
- clm.warn(`The repository ${repo} does not contain a release asset with the name "node-pilot"`);
130
- await this.selectProject();
131
- }
132
- }
133
- }
134
83
  }
135
84
  };
@@ -1,7 +1,8 @@
1
- import { ClusterInfo, NodeInfo } from "../types.js";
1
+ import { ClusterConsensusInfo, ClusterInfo, NodeInfo } from "../types.js";
2
2
  export declare const clusterService: {
3
3
  fastForwardSnapshot(): Promise<void>;
4
4
  getClusterInfo(): Promise<ClusterInfo[]>;
5
+ getLatestConsensus(): Promise<ClusterConsensusInfo>;
5
6
  getLatestOrdinal(): Promise<any>;
6
7
  getNodeInfo(): Promise<NodeInfo>;
7
8
  getReleaseVersion(): Promise<string>;
@@ -32,6 +32,16 @@ export const clusterService = {
32
32
  })
33
33
  .catch(() => []);
34
34
  },
35
+ async getLatestConsensus() {
36
+ const { type } = configStore.getNetworkInfo();
37
+ return fetch(`https://l0-lb-${type}.constellationnetwork.io/consensus/latest/peers`)
38
+ .then(res => {
39
+ if (res.ok)
40
+ return res.json();
41
+ return 0;
42
+ })
43
+ .catch(() => 0);
44
+ },
35
45
  async getLatestOrdinal() {
36
46
  const { type } = configStore.getNetworkInfo();
37
47
  return fetch(`https://l0-lb-${type}.constellationnetwork.io/global-snapshots/latest`)
@@ -43,12 +43,18 @@ export class FastforwardService {
43
43
  async fetchLatestSnapshot() {
44
44
  const url = `${this.lbUrl}/global-snapshots/latest/combined`;
45
45
  clm.debug('Fetching latest snapshot ordinal from: ' + chalk.cyan(url));
46
- return fetch(url).then(res => res.json()
46
+ return fetch(url)
47
+ .then(res => {
48
+ if (!res.ok) {
49
+ throw new Error(`Failed to fetch latest snapshot ordinal: ${res.statusText}`);
50
+ }
51
+ return res.json();
52
+ })
47
53
  .then(data => {
48
54
  const { ordinal } = data[0].value;
49
55
  clm.debug('fetchLatestSnapshot - ' + chalk.cyan(ordinal));
50
56
  return [ordinal, data[0], data[1]];
51
- }));
57
+ });
52
58
  }
53
59
  async fetchSnapshot(ordinal) {
54
60
  const url = `${this.lbUrl}/global-snapshots/${ordinal}`;
@@ -57,7 +63,7 @@ export class FastforwardService {
57
63
  }
58
64
  async fetchSnapshotHash(ordinal) {
59
65
  const url = `${this.lbUrl}/global-snapshots/${ordinal}/hash`;
60
- const hash = await fetch(url).then(res => res.text().then(t => t.replace(/^"(.*)"$/, '$1')));
66
+ const hash = await fetch(url).then(res => res.json());
61
67
  clm.debug('fetchLatestSnapshotHash: ' + chalk.cyan(hash));
62
68
  return hash;
63
69
  }
@@ -0,0 +1,2 @@
1
+ import { NodeInfo } from "../types.js";
2
+ export declare const getRandomNode: (nodes: Pick<NodeInfo, "host" | "id" | "publicPort">[]) => Promise<NodeInfo>;
@@ -0,0 +1,16 @@
1
+ export const getRandomNode = (nodes) => {
2
+ const randomNodeIndex = Math.floor(Math.random() * nodes.length);
3
+ const node = nodes[randomNodeIndex];
4
+ console.log(`Getting random node from ${nodes.length} nodes: ${node.host}`);
5
+ return fetch(`http://${node.host}:${node.publicPort}/node/info`)
6
+ .then(async (res) => {
7
+ if (res.ok)
8
+ return res.json();
9
+ throw new Error(`Failed`);
10
+ })
11
+ .catch(() => {
12
+ if (nodes.length === 1)
13
+ throw new Error(`Failed to get random node. All nodes are offline.`);
14
+ return getRandomNode(nodes.toSpliced(randomNodeIndex, 1));
15
+ });
16
+ };
@@ -2,6 +2,10 @@ import { NodeInfo, TessellationLayer } from "../types.js";
2
2
  export declare const nodeService: {
3
3
  getNodeInfo(layer: "first" | TessellationLayer): Promise<NodeInfo>;
4
4
  getSnapshotHash(ipAddr: string, ordinal: number): Promise<string>;
5
+ getStatusInfo(layer: TessellationLayer): Promise<TessellationLayer>;
6
+ isPortExposed(port: number): Promise<boolean>;
7
+ isPortInUse(port: number): Promise<boolean>;
8
+ isPortOpen(port: number): Promise<boolean>;
5
9
  joinCluster(layer: TessellationLayer): Promise<void>;
6
10
  leaveCluster(layer: TessellationLayer): Promise<boolean>;
7
11
  leaveClusterAllLayers(): Promise<boolean>;
@@ -26,6 +26,21 @@ export const nodeService = {
26
26
  })
27
27
  .catch(() => (''));
28
28
  },
29
+ async getStatusInfo(layer) {
30
+ return layer;
31
+ },
32
+ async isPortExposed(port) {
33
+ const command = configStore.getSystemInfo().platform === 'linux' ? `ss -tuln | grep 0.0.0.0:${port}` : `netstat -an | grep '*.${port}'`;
34
+ return shellService.runCommandWithOutput(command).then(o => o.length > 0);
35
+ },
36
+ async isPortInUse(port) {
37
+ clm.preStep('Making a sudo call to check if a port is in use...');
38
+ return shellService.runCommandWithOutput(`sudo lsof -i :${port}`).then(Boolean).catch(() => false);
39
+ },
40
+ async isPortOpen(port) {
41
+ const command = configStore.getSystemInfo().platform === 'linux' ? `ss -tuln | grep :${port}` : `netstat -an | grep '.${port}'`;
42
+ return shellService.runCommandWithOutput(command).then(o => o.length > 0);
43
+ },
29
44
  async joinCluster(layer) {
30
45
  const { state } = await this.getNodeInfo(layer);
31
46
  if (state !== "ReadyToJoin") {
@@ -2,8 +2,10 @@ import shell from "shelljs";
2
2
  export declare const shellService: {
3
3
  checkCommandAvailable(cmd: string): Promise<boolean>;
4
4
  execDockerShell(serviceName: string, command: string): Promise<string>;
5
- existsScript(filePath: string): boolean;
5
+ existsProjectScript(filePath: string): boolean;
6
6
  resolvePath(keyPath: string): string;
7
7
  runCommand(command: string, env?: object, silent?: boolean): Promise<shell.ShellString>;
8
8
  runCommandWithOutput(command: string, env?: object): Promise<string>;
9
+ runProjectCommand(command: string, env?: object, silent?: boolean): Promise<string>;
10
+ runProjectCommandWithOutput(command: string, env?: object): Promise<string>;
9
11
  };
@@ -6,9 +6,13 @@ import { clm } from "../clm.js";
6
6
  import { configStore } from "../config-store.js";
7
7
  export const shellService = {
8
8
  async checkCommandAvailable(cmd) {
9
- return this.runCommand(`command -v ${cmd}`, undefined, true)
9
+ clm.debug(`Checking if command ${cmd} is available...`);
10
+ return this.runCommand(`command -v ${cmd}`)
10
11
  .then(() => true)
11
- .catch(() => false);
12
+ .catch((error) => {
13
+ clm.debug(`Run command error: ${error}`);
14
+ return false;
15
+ });
12
16
  },
13
17
  async execDockerShell(serviceName, command) {
14
18
  const { projectDir } = configStore.getProjectInfo();
@@ -19,7 +23,7 @@ export const shellService = {
19
23
  }
20
24
  return result.stdout;
21
25
  },
22
- existsScript(filePath) {
26
+ existsProjectScript(filePath) {
23
27
  const { projectDir } = configStore.getProjectInfo();
24
28
  return fs.existsSync(path.join(projectDir, filePath));
25
29
  },
@@ -33,13 +37,12 @@ export const shellService = {
33
37
  return path.resolve(process.cwd(), keyPath);
34
38
  },
35
39
  async runCommand(command, env, silent = false) {
36
- const { projectDir } = configStore.getProjectInfo();
40
+ clm.debug(`START Running command: "${command}"`);
37
41
  let nodeEnv;
38
42
  if (env) {
39
43
  nodeEnv = { ...env, ...process.env };
40
44
  }
41
- clm.debug(`START Running command: "${command}" in directory: "${projectDir}"`);
42
- const result = shell.exec(command, { cwd: projectDir, env: nodeEnv, silent });
45
+ const result = shell.exec(command, { env: nodeEnv, silent });
43
46
  clm.debug(`END ${command}. Exit code: ${result.code}`);
44
47
  if (result.code > 0) {
45
48
  throw new Error(`Failed running command: ${result.stderr}`);
@@ -49,5 +52,28 @@ export const shellService = {
49
52
  async runCommandWithOutput(command, env) {
50
53
  const result = await this.runCommand(command, env, true);
51
54
  return result.stdout.trim();
55
+ },
56
+ async runProjectCommand(command, env, silent = false) {
57
+ const { projectDir } = configStore.getProjectInfo();
58
+ let nodeEnv;
59
+ if (env) {
60
+ nodeEnv = { ...env, ...process.env };
61
+ }
62
+ clm.debug(`START Running command: "${command}" in directory: "${projectDir}"`);
63
+ return new Promise((resolve, reject) => {
64
+ shell.exec(command, { async: true, cwd: projectDir, env: nodeEnv, silent }, (code, stdout, stderr) => {
65
+ if (code === 0) {
66
+ clm.debug(`END ${command}.`);
67
+ resolve(stdout);
68
+ }
69
+ else {
70
+ reject(new Error(`Command failed with code ${code}: ${stderr}`));
71
+ }
72
+ });
73
+ });
74
+ },
75
+ async runProjectCommandWithOutput(command, env) {
76
+ const stdout = await this.runProjectCommand(command, env, true);
77
+ return stdout.trim();
52
78
  }
53
79
  };
package/dist/types.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  export type TessellationLayer = 'cl1' | 'dl1' | 'gl0' | 'gl1' | 'ml0';
2
2
  export type NodeInfo = {
3
- clusterSession: number;
3
+ clusterSession: number | string;
4
4
  host: string;
5
5
  id: string;
6
6
  layer: TessellationLayer;
7
7
  p2pPort: number;
8
- publicPort: number;
9
- session: number;
8
+ publicPort: number | string;
9
+ session: number | string;
10
10
  state: string;
11
11
  version: string;
12
12
  };
@@ -20,3 +20,36 @@ export type ClusterInfo = {
20
20
  session: string;
21
21
  state: 'DownloadInProgress' | 'GenesisReady' | 'Initial' | 'Leaving' | 'LoadingGenesis' | 'Offline' | 'Ready' | 'ReadyToJoin' | 'SessionStarted' | 'StartingSession' | 'Unavailable' | 'WaitingForDownload';
22
22
  };
23
+ export type ClusterConsensusInfo = {
24
+ key: number;
25
+ peers: {
26
+ clusterSession: string;
27
+ id: string;
28
+ ip: string;
29
+ p2pPort: number;
30
+ publicPort: number;
31
+ session: string;
32
+ state: 'Ready';
33
+ }[];
34
+ };
35
+ export type NodeStatusInfo = {
36
+ clusterSession: string;
37
+ id: string;
38
+ inConsensus: boolean;
39
+ inNetwork: boolean;
40
+ ip: string;
41
+ session: string;
42
+ };
43
+ export type NodeDiagnosticInfo = {
44
+ collateral: number;
45
+ hasCollateral: boolean;
46
+ hasHealthyState: boolean;
47
+ hasLatestVersion: boolean;
48
+ hasOpenP2PPort: boolean;
49
+ hasOpenPublicPort: boolean;
50
+ inSeedList: boolean;
51
+ p2pPort: number;
52
+ publicPort: number;
53
+ state: string;
54
+ version: string;
55
+ };
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Break on any error
4
+ set -e
5
+
6
+ # Check and install curl
7
+ check_curl() {
8
+ # echo "Checking for curl..."
9
+ if command -v curl >/dev/null 2>&1; then
10
+ echo "✅ curl is already installed."
11
+ return 0
12
+ fi
13
+
14
+ echo "⚠️ curl not found. Will attempt to install curl."
15
+
16
+ case "$(uname)" in
17
+ Linux)
18
+ if command -v apt >/dev/null 2>&1; then
19
+ echo "Installing curl using apt..."
20
+ sudo apt update
21
+ sudo apt install -y curl
22
+ elif command -v yum >/dev/null 2>&1; then
23
+ echo "Installing curl using yum..."
24
+ sudo yum install -y curl
25
+ else
26
+ echo "⚠️ Unsupported Linux distribution. Please install curl manually."
27
+ return 1
28
+ fi
29
+ ;;
30
+ Darwin)
31
+ if command -v brew >/dev/null 2>&1; then
32
+ echo "Installing curl using Homebrew..."
33
+ brew install curl
34
+ else
35
+ echo "⚠️ Homebrew not found. Please install curl manually."
36
+ return 1
37
+ fi
38
+ ;;
39
+ MINGW*|MSYS*|CYGWIN*)
40
+ echo "On Windows, please install curl manually."
41
+ return 1
42
+ ;;
43
+ *)
44
+ echo "⚠️ Unsupported OS: $(uname). Please install curl manually."
45
+ return 1
46
+ ;;
47
+ esac
48
+
49
+ echo "✅ curl installation complete."
50
+ return 0
51
+ }
52
+
53
+ # Check and install Docker Engine
54
+ check_docker() {
55
+ # echo "Checking for Docker..."
56
+ if command -v docker >/dev/null 2>&1; then
57
+ echo "✅ Docker is already installed."
58
+ return 0
59
+ fi
60
+
61
+ echo "⚠️ Docker not found. Will attempt to install Docker."
62
+
63
+ # curl -fsSL https://raw.githubusercontent.com/Constellation-Labs/node-pilot/refs/heads/main/install.sh -o install-node-pilot.sh; source install-node-pilot.sh
64
+
65
+ case "$(uname)" in
66
+ Linux)
67
+ if command -v apt >/dev/null 2>&1; then
68
+ echo "Installing Docker using script..."
69
+ curl -fsSL https://get.docker.com -o get-docker.sh
70
+ sudo sh ./get-docker.sh
71
+ sudo usermod -aG docker $USER
72
+ echo "Docker installed. You may need to log out and back in for group changes to take effect."
73
+ else
74
+ echo "⚠️ Unsupported Linux distribution. Please install Docker manually."
75
+ return 1
76
+ fi
77
+ ;;
78
+ Darwin)
79
+ echo "Please install Docker Desktop manually from https://www.docker.com/products/docker-desktop"
80
+ return 1
81
+ ;;
82
+ MINGW*|MSYS*|CYGWIN*)
83
+ echo "On Windows, please install Docker Desktop manually from https://www.docker.com/products/docker-desktop"
84
+ return 1
85
+ ;;
86
+ *)
87
+ echo "⚠️ Unsupported OS: $(uname). Please install Docker manually."
88
+ return 1
89
+ ;;
90
+ esac
91
+
92
+ echo "✅ Docker installation complete."
93
+ return 0
94
+ }
95
+
96
+
97
+ # Run all checks
98
+ echo "🔍 Checking and installing required dependencies..."
99
+ check_curl
100
+ check_docker
@@ -65,6 +65,14 @@
65
65
  "name": "follow",
66
66
  "allowNo": false,
67
67
  "type": "boolean"
68
+ },
69
+ "numOfLines": {
70
+ "char": "n",
71
+ "description": "number of lines at the end of the log to display",
72
+ "name": "numOfLines",
73
+ "hasDynamicHelp": false,
74
+ "multiple": false,
75
+ "type": "option"
68
76
  }
69
77
  },
70
78
  "hasDynamicHelp": false,
@@ -237,5 +245,5 @@
237
245
  ]
238
246
  }
239
247
  },
240
- "version": "0.0.6"
248
+ "version": "0.0.8"
241
249
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@constellation-network/node-pilot",
3
3
  "description": "An easy deployment and monitoring tool for Constellation nodes.",
4
- "version": "0.0.6",
4
+ "version": "0.0.8",
5
5
  "author": "Frank Fox",
6
6
  "bin": {
7
7
  "cpilot": "bin/run.js"
@@ -38,8 +38,10 @@
38
38
  "js-sha256": "^0.11.1",
39
39
  "json-bigint-patch": "^0.0.8",
40
40
  "node-localstorage": "^3.0.5",
41
+ "ora": "^8.2.0",
41
42
  "shelljs": "^0.10.0",
42
- "tty-table": "^4.2.3"
43
+ "tty-table": "^4.2.3",
44
+ "yaml": "^2.8.1"
43
45
  },
44
46
  "devDependencies": {
45
47
  "@eslint/compat": "^1",
@@ -64,6 +66,7 @@
64
66
  "./bin",
65
67
  "./dist",
66
68
  "./oclif.manifest.json",
69
+ "./install-dependencies.sh",
67
70
  "./projects",
68
71
  "./README.md",
69
72
  "./LICENSE"
@@ -1,9 +1,17 @@
1
- CL_APP_ENV="integrationnet"
1
+ CL_APP_ENV=integrationnet
2
2
  CL_COLLATERAL=0
3
- CL_L0_PEER_HTTP_PORT="9000"
4
- CL_L0_PEER_HTTP_HOST="13.52.205.240"
5
- CL_L0_PEER_ID="e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714"
6
- CL_GLOBAL_L0_PEER_HTTP_PORT="9000"
7
- CL_GLOBAL_L0_PEER_HOST="13.52.205.240"
8
- CL_GLOBAL_L0_PEER_ID="e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714"
9
-
3
+ CL_L0_PEER_HTTP_PORT=9000
4
+ CL_L0_PEER_HTTP_HOST=13.52.205.240
5
+ CL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
6
+ CL_GLOBAL_L0_PEER_HTTP_PORT=9000
7
+ CL_GLOBAL_L0_PEER_HOST=13.52.205.240
8
+ CL_GLOBAL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
9
+ SOURCE_NODE_1_PORT=9000
10
+ SOURCE_NODE_1_HOST=13.52.205.240
11
+ SOURCE_NODE_1_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
12
+ SOURCE_NODE_2_PORT=9000
13
+ SOURCE_NODE_2_HOST=50.18.155.22
14
+ SOURCE_NODE_2_ID=3458a688925a4bd89f2ac2c695362e44d2e0c2903bdbb41b341a4d39283b22d8c85b487bd33cc5d36dbe5e31b5b00a10a6eab802718ead4ed7192ade5a5d1941
15
+ SOURCE_NODE_3_PORT=9000
16
+ SOURCE_NODE_3_HOST=52.9.216.57
17
+ SOURCE_NODE_3_ID=46daea11ca239cb8c0c8cdeb27db9dbe9c03744908a8a389a60d14df2ddde409260a93334d74957331eec1af323f458b12b3a6c3b8e05885608aae7e3a77eac7
@@ -1,8 +1,17 @@
1
- CL_APP_ENV="mainnet"
1
+ CL_APP_ENV=mainnet
2
2
  CL_COLLATERAL=25000000000000
3
- CL_L0_PEER_HTTP_PORT="9000"
4
- CL_L0_PEER_HTTP_HOST="52.53.46.33"
5
- CL_L0_PEER_ID="e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925"
6
- CL_GLOBAL_L0_PEER_HTTP_PORT="9000"
7
- CL_GLOBAL_L0_PEER_HOST="52.53.46.33"
8
- CL_GLOBAL_L0_PEER_ID="e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925"
3
+ CL_L0_PEER_HTTP_PORT=9000
4
+ CL_L0_PEER_HTTP_HOST=52.53.46.33
5
+ CL_L0_PEER_ID=e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925
6
+ CL_GLOBAL_L0_PEER_HTTP_PORT=9000
7
+ CL_GLOBAL_L0_PEER_HOST=52.53.46.33
8
+ CL_GLOBAL_L0_PEER_ID=e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925
9
+ SOURCE_NODE_1_PORT=9000
10
+ SOURCE_NODE_1_HOST=52.53.46.33
11
+ SOURCE_NODE_1_ID=e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925
12
+ SOURCE_NODE_2_PORT=9000
13
+ SOURCE_NODE_2_HOST=54.215.18.98
14
+ SOURCE_NODE_2_ID=629880a5b8d4cc6d12aec26f24230a463825c429723153aeaff29475b29e39d2406af0f8b034ba7798ae598dbd5f513d642bcbbeef088290abeadac61a0445d6
15
+ SOURCE_NODE_3_PORT=9000
16
+ SOURCE_NODE_3_HOST=54.151.19.111
17
+ SOURCE_NODE_3_ID=710b3dc521b805aea7a798d61f5d4dae39601124f1f34fac9738a78047adeff60931ba522250226b87a2194d3b7d39da8d2cbffa35d6502c70f1a7e97132a4b0
@@ -1,9 +1,17 @@
1
- CL_APP_ENV="testnet"
1
+ CL_APP_ENV=testnet
2
2
  CL_COLLATERAL=0
3
- CL_L0_PEER_HTTP_PORT="9000"
4
- CL_L0_PEER_HTTP_HOST="52.8.132.193"
5
- CL_L0_PEER_ID="e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714"
6
- CL_GLOBAL_L0_PEER_HTTP_PORT="9000"
7
- CL_GLOBAL_L0_PEER_HOST="52.8.132.193"
8
- CL_GLOBAL_L0_PEER_ID="e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714"
9
-
3
+ CL_L0_PEER_HTTP_PORT=9000
4
+ CL_L0_PEER_HTTP_HOST=52.8.132.193
5
+ CL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
6
+ CL_GLOBAL_L0_PEER_HTTP_PORT=9000
7
+ CL_GLOBAL_L0_PEER_HOST=52.8.132.193
8
+ CL_GLOBAL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
9
+ SOURCE_NODE_1_PORT=9000
10
+ SOURCE_NODE_1_HOST=52.8.132.193
11
+ SOURCE_NODE_1_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
12
+ SOURCE_NODE_2_PORT=9000
13
+ SOURCE_NODE_2_HOST=13.57.110.45
14
+ SOURCE_NODE_2_ID=3458a688925a4bd89f2ac2c695362e44d2e0c2903bdbb41b341a4d39283b22d8c85b487bd33cc5d36dbe5e31b5b00a10a6eab802718ead4ed7192ade5a5d1941
15
+ SOURCE_NODE_3_PORT=9000
16
+ SOURCE_NODE_3_HOST=54.153.23.79
17
+ SOURCE_NODE_3_ID=46daea11ca239cb8c0c8cdeb27db9dbe9c03744908a8a389a60d14df2ddde409260a93334d74957331eec1af323f458b12b3a6c3b8e05885608aae7e3a77eac7
@@ -1,4 +1,4 @@
1
- #!/scripts/bash
1
+ #!/usr/bin/env bash
2
2
 
3
3
  # Break on any error
4
4
  set -e
@@ -270,7 +270,7 @@ check_node() {
270
270
  Linux)
271
271
  echo "Installing Node.js using nvm..."
272
272
  # NPM
273
- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
273
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
274
274
 
275
275
  # Load nvm without needing to open a new terminal
276
276
  export NVM_DIR="$HOME/.nvm"
@@ -278,7 +278,7 @@ check_node() {
278
278
  [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
279
279
 
280
280
  # Install node
281
- nvm install node
281
+ nvm install 22
282
282
 
283
283
  # Verify installation
284
284
  echo "Node version: $(node -v)"