@constellation-network/node-pilot 0.0.7 → 0.0.9

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 (96) hide show
  1. package/README.md +26 -18
  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-dependencies.d.ts +1 -0
  7. package/dist/checks/check-dependencies.js +44 -0
  8. package/dist/checks/check-hardware.js +3 -3
  9. package/dist/checks/check-initial-setup.js +6 -4
  10. package/dist/checks/check-layers.js +7 -7
  11. package/dist/checks/check-network.d.ts +3 -0
  12. package/dist/checks/check-network.js +92 -9
  13. package/dist/checks/check-node-ctl.d.ts +5 -0
  14. package/dist/checks/check-node-ctl.js +88 -0
  15. package/dist/checks/check-project.js +33 -13
  16. package/dist/checks/check-wallet.d.ts +3 -0
  17. package/dist/checks/check-wallet.js +37 -0
  18. package/dist/clm.d.ts +1 -0
  19. package/dist/clm.js +4 -1
  20. package/dist/commands/config/get.d.ts +6 -0
  21. package/dist/commands/config/get.js +57 -11
  22. package/dist/commands/config/set.d.ts +0 -1
  23. package/dist/commands/config/set.js +13 -11
  24. package/dist/commands/config.js +17 -22
  25. package/dist/commands/info.js +3 -2
  26. package/dist/commands/logs.d.ts +2 -1
  27. package/dist/commands/logs.js +12 -6
  28. package/dist/commands/restart.d.ts +5 -2
  29. package/dist/commands/restart.js +25 -5
  30. package/dist/commands/shutdown.js +3 -3
  31. package/dist/commands/status.js +8 -0
  32. package/dist/commands/test.d.ts +1 -0
  33. package/dist/commands/test.js +35 -5
  34. package/dist/config-store.d.ts +50 -34
  35. package/dist/config-store.js +80 -32
  36. package/dist/helpers/config-helper.js +2 -2
  37. package/dist/helpers/env-templates.d.ts +4 -3
  38. package/dist/helpers/env-templates.js +28 -20
  39. package/dist/helpers/key-file-helper.d.ts +2 -0
  40. package/dist/helpers/key-file-helper.js +52 -17
  41. package/dist/helpers/project-helper.d.ts +3 -2
  42. package/dist/helpers/project-helper.js +86 -35
  43. package/dist/helpers/prompt-helper.d.ts +0 -2
  44. package/dist/helpers/prompt-helper.js +15 -66
  45. package/dist/services/archiver-service.d.ts +17 -0
  46. package/dist/services/archiver-service.js +104 -0
  47. package/dist/services/cluster-service.d.ts +10 -5
  48. package/dist/services/cluster-service.js +46 -36
  49. package/dist/services/docker-service.d.ts +9 -0
  50. package/dist/services/docker-service.js +53 -0
  51. package/dist/services/fastforward-service.js +12 -6
  52. package/dist/services/get-random-node.d.ts +2 -0
  53. package/dist/services/get-random-node.js +16 -0
  54. package/dist/{helpers/github-helper.d.ts → services/github-service.d.ts} +1 -1
  55. package/dist/{helpers/github-helper.js → services/github-service.js} +1 -1
  56. package/dist/services/node-service.d.ts +4 -0
  57. package/dist/services/node-service.js +29 -14
  58. package/dist/services/shell-service.d.ts +3 -1
  59. package/dist/services/shell-service.js +32 -6
  60. package/dist/test.d.ts +1 -0
  61. package/dist/test.js +50 -0
  62. package/dist/types.d.ts +42 -3
  63. package/install-dependencies.sh +98 -0
  64. package/oclif.manifest.json +31 -4
  65. package/package.json +12 -8
  66. package/projects/hypergraph/Dockerfile +27 -18
  67. package/projects/hypergraph/docker-compose.yml +14 -12
  68. package/projects/hypergraph/networks/integrationnet/gl0.env +4 -0
  69. package/projects/hypergraph/networks/integrationnet/gl1.env +4 -0
  70. package/projects/hypergraph/networks/integrationnet/network.env +8 -0
  71. package/projects/hypergraph/networks/integrationnet/source-nodes.env +9 -0
  72. package/projects/hypergraph/networks/mainnet/gl0.env +4 -0
  73. package/projects/hypergraph/networks/mainnet/gl1.env +4 -0
  74. package/projects/hypergraph/networks/mainnet/network.env +8 -0
  75. package/projects/hypergraph/networks/mainnet/source-nodes.env +9 -0
  76. package/projects/hypergraph/networks/testnet/gl0.env +5 -0
  77. package/projects/hypergraph/networks/testnet/gl1.env +4 -0
  78. package/projects/hypergraph/networks/testnet/network.env +8 -0
  79. package/projects/hypergraph/networks/testnet/source-nodes.env +9 -0
  80. package/projects/hypergraph/scripts/check-version.sh +31 -0
  81. package/projects/hypergraph/scripts/docker-build.sh +12 -1
  82. package/projects/hypergraph/scripts/install-dependencies.sh +3 -3
  83. package/projects/hypergraph/scripts/install.sh +34 -31
  84. package/projects/hypergraph/seedlist +268 -0
  85. package/scripts/autoheal.sh +8 -0
  86. package/scripts/services/io.constellationnetwork.nodepilot.Updater.plist +16 -0
  87. package/scripts/services/node-pilot-autoheal.service +14 -0
  88. package/scripts/services/node-pilot-updater-hypergraph.service +15 -0
  89. package/scripts/updater.sh +13 -0
  90. package/dist/helpers/docker-helper.d.ts +0 -7
  91. package/dist/helpers/docker-helper.js +0 -37
  92. package/projects/hypergraph/layers/gl1.env +0 -3
  93. package/projects/hypergraph/networks/integrationnet.env +0 -9
  94. package/projects/hypergraph/networks/mainnet.env +0 -8
  95. package/projects/hypergraph/networks/testnet.env +0 -9
  96. package/projects/scripts/docker-cleanup.sh +0 -64
@@ -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}:${node.publicPort}`);
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
+ };
@@ -1,3 +1,3 @@
1
- export declare const githubHelper: {
1
+ export declare const githubService: {
2
2
  hasAssetInRelease(assetName: string, repo: string): Promise<boolean>;
3
3
  };
@@ -1,4 +1,4 @@
1
- export const githubHelper = {
1
+ export const githubService = {
2
2
  hasAssetInRelease(assetName, repo) {
3
3
  return fetch(`https://api.github.com/repos/${repo}/releases/latest`)
4
4
  .then(async (res) => {
@@ -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>;
@@ -1,3 +1,4 @@
1
+ import chalk from "chalk";
1
2
  import { clm } from "../clm.js";
2
3
  import { configStore } from "../config-store.js";
3
4
  import { clusterService } from "./cluster-service.js";
@@ -26,6 +27,21 @@ export const nodeService = {
26
27
  })
27
28
  .catch(() => (''));
28
29
  },
30
+ async getStatusInfo(layer) {
31
+ return layer;
32
+ },
33
+ async isPortExposed(port) {
34
+ const command = configStore.getSystemInfo().platform === 'linux' ? `ss -tuln | grep 0.0.0.0:${port}` : `netstat -an | grep '*.${port}'`;
35
+ return shellService.runCommandWithOutput(command).then(o => o.length > 0);
36
+ },
37
+ async isPortInUse(port) {
38
+ clm.preStep('Making a sudo call to check if a port is in use...');
39
+ return shellService.runCommandWithOutput(`sudo lsof -i :${port}`).then(Boolean).catch(() => false);
40
+ },
41
+ async isPortOpen(port) {
42
+ const command = configStore.getSystemInfo().platform === 'linux' ? `ss -tuln | grep :${port}` : `netstat -an | grep '.${port}'`;
43
+ return shellService.runCommandWithOutput(command).then(o => o.length > 0);
44
+ },
29
45
  async joinCluster(layer) {
30
46
  const { state } = await this.getNodeInfo(layer);
31
47
  if (state !== "ReadyToJoin") {
@@ -33,7 +49,7 @@ export const nodeService = {
33
49
  return;
34
50
  }
35
51
  const layerPortInfo = configStore.getLayerPortInfo(layer);
36
- const peerInfo = await clusterService.getSourceNodeInfo();
52
+ const peerInfo = await clusterService.getClusterNodeInfo(layer);
37
53
  const nodeId = peerInfo.id;
38
54
  const nodeIp = peerInfo.host;
39
55
  const cliPort = layerPortInfo.CLI;
@@ -90,25 +106,24 @@ export const nodeService = {
90
106
  for (let i = 1; i <= 60; i++) {
91
107
  // eslint-disable-next-line no-await-in-loop
92
108
  const { state } = await this.getNodeInfo(layer);
93
- if (state === "Unavailable" || state === "ReadyToJoin") {
94
- if (expectedState === 'Offline')
95
- return true;
96
- clm.echo(` Validator Node is not running.`);
97
- }
98
- if (layer === 'gl0' && expectedState === 'Ready' && state === "WaitingForDownload") {
99
- clm.echo(` [${layer}] Attempt ${i}: Current state is "${state}"`);
100
- }
101
- else {
102
- clm.echo(` [${layer}] Attempt ${i}: Current state is "${state}"`);
103
- }
109
+ if (expectedState === 'Offline' && (state === "Unavailable" || state === "ReadyToJoin" || state === "SessionStarted"))
110
+ return true;
111
+ clm.echoRepeatLine(`[${layer}] ${chalk.bgGray.cyan('Attempt ' + i)}: Current state is "${state}" `);
112
+ // eslint-disable-next-line no-await-in-loop
113
+ await sleep(0.5);
114
+ clm.echoRepeatLine(`[${layer}] Attempt ${i}: Current state is "${state}" `);
104
115
  if (state === expectedState) {
105
- clm.postStep(` ${layer} is ${expectedState}`);
116
+ clm.postStep(`${layer} is ${expectedState}`);
106
117
  return true;
107
118
  }
119
+ if (state === "Unavailable" && i > 2) {
120
+ clm.warn(`${layer} is not connectable. Please try again later.`);
121
+ return false;
122
+ }
108
123
  // eslint-disable-next-line no-await-in-loop
109
124
  await sleep(5);
110
125
  }
111
- clm.warn(` ${layer} is not ${expectedState} after 5 minutes`);
126
+ clm.warn(`${layer} is not ${expectedState} after 5 minutes`);
112
127
  return false;
113
128
  }
114
129
  };
@@ -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/test.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/test.js ADDED
@@ -0,0 +1,50 @@
1
+ import * as crypto from "node:crypto";
2
+ // convert base64 to hex
3
+ const val = 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgeYLAOmnJ6FYQ3Uddr6lq5PEVgoiAdWIJ89x6fx3n8JihRANCAASNoaVq/vT5k5Akdzjv8ifybl9icGnMKRpeyZhOxTMnwxGjxANTuKLfUGWUOEngV6HaWGxgkXTU/VXRma+mu0hD';
4
+ // const val = 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgKy/2tKuoO5V0iXJmTlaWPl9PeDo8TO5ZD+JmD3pOlzihRANCAASffXYMsILTOYSM4pEuBiYO1RR/hfuO+k4WvnNup21HT7CGThWfRjIemS3QDMHncK0Shsy43nb6kD9Fo8DTKpI6';
5
+ const der = Buffer.from(val, 'base64').toString('hex');
6
+ console.log(der);
7
+ // convert DER to PEM
8
+ const ecKey = crypto.createPrivateKey({
9
+ encoding: "base64",
10
+ format: "der",
11
+ key: val,
12
+ type: "pkcs8",
13
+ });
14
+ console.log(ecKey.export({ 'format': 'jwk' }));
15
+ // Generate an RSA key pair
16
+ const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
17
+ modulusLength: 2048, // Recommended key size
18
+ privateKeyEncoding: {
19
+ format: 'der', // DER encoding for binary output
20
+ type: 'pkcs8' // PKCS#8 format
21
+ },
22
+ publicKeyEncoding: {
23
+ format: 'der',
24
+ type: 'spki' // SubjectPublicKeyInfo
25
+ }
26
+ });
27
+ // The 'privateKey' variable now holds a Buffer containing the PKCS#8 DER private key.
28
+ // To get the Base64 encoded string:
29
+ const privateKeyBase64 = privateKey.toString('base64');
30
+ console.log('PKCS#8 DER Private Key (Base64):');
31
+ console.log(privateKeyBase64);
32
+ // openssl pkcs8 -inform DER -in privatekey.der -outform PEM -out privatekey.pem
33
+ // openssl pkcs8 -inform DER -in privatekey.der -nocrypt -out privatekey.pem -traditional
34
+ async function createP256Pkcs8DerBase64PrivateKey() {
35
+ // Generate an ECDSA key pair with the P-256 named curve
36
+ const keyPair = await crypto.subtle.generateKey({
37
+ name: 'ECDSA',
38
+ namedCurve: 'P-256',
39
+ }, true, // extractable
40
+ ['sign', 'verify']);
41
+ // Export the private key in PKCS#8 DER format
42
+ const privateKeyDerBuffer = await crypto.subtle.exportKey('pkcs8', // format
43
+ keyPair.privateKey);
44
+ console.log('PKCS#8 DER Private Key (DER Buffer): ' + Buffer.from(privateKeyDerBuffer).toString('hex'));
45
+ // Convert the DER buffer to a Base64 encoded string
46
+ const privateKeyBase64 = Buffer.from(privateKeyDerBuffer).toString('base64');
47
+ console.log('PKCS#8 DER Private Key (Base64):' + privateKeyBase64);
48
+ return privateKeyBase64;
49
+ }
50
+ await createP256Pkcs8DerBase64PrivateKey();
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,42 @@ 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 ClusterStats = {
36
+ ordinal: number;
37
+ ready: number;
38
+ startTime: string;
39
+ total: number;
40
+ };
41
+ export type NodeStatusInfo = {
42
+ clusterSession: string;
43
+ id: string;
44
+ inConsensus: boolean;
45
+ inNetwork: boolean;
46
+ ip: string;
47
+ session: string;
48
+ };
49
+ export type NodeDiagnosticInfo = {
50
+ collateral: number;
51
+ hasCollateral: boolean;
52
+ hasHealthyState: boolean;
53
+ hasLatestVersion: boolean;
54
+ hasOpenP2PPort: boolean;
55
+ hasOpenPublicPort: boolean;
56
+ inSeedList: boolean;
57
+ p2pPort: number;
58
+ publicPort: number;
59
+ state: string;
60
+ version: string;
61
+ };
@@ -0,0 +1,98 @@
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
+ case "$(uname)" in
64
+ Linux)
65
+ if command -v apt >/dev/null 2>&1; then
66
+ echo "Installing Docker using script..."
67
+ curl -fsSL https://get.docker.com -o get-docker.sh
68
+ sudo sh ./get-docker.sh
69
+ sudo usermod -aG docker $USER
70
+ echo "Docker installed. You may need to log out and back in for group changes to take effect."
71
+ else
72
+ echo "⚠️ Unsupported Linux distribution. Please install Docker manually."
73
+ return 1
74
+ fi
75
+ ;;
76
+ Darwin)
77
+ echo "Please install Docker Desktop manually from https://www.docker.com/products/docker-desktop"
78
+ return 1
79
+ ;;
80
+ MINGW*|MSYS*|CYGWIN*)
81
+ echo "On Windows, please install Docker Desktop manually from https://www.docker.com/products/docker-desktop"
82
+ return 1
83
+ ;;
84
+ *)
85
+ echo "⚠️ Unsupported OS: $(uname). Please install Docker manually."
86
+ return 1
87
+ ;;
88
+ esac
89
+
90
+ echo "✅ Docker installation complete."
91
+ return 0
92
+ }
93
+
94
+
95
+ # Run all checks
96
+ echo "🔍 Checking and installing required dependencies..."
97
+ check_curl
98
+ check_docker
@@ -51,7 +51,8 @@
51
51
  "args": {
52
52
  "layer": {
53
53
  "description": "network layer to view. e.g. gl0",
54
- "name": "layer"
54
+ "name": "layer",
55
+ "required": true
55
56
  }
56
57
  },
57
58
  "description": "view validator node runtime logs",
@@ -65,6 +66,14 @@
65
66
  "name": "follow",
66
67
  "allowNo": false,
67
68
  "type": "boolean"
69
+ },
70
+ "numOfLines": {
71
+ "char": "n",
72
+ "description": "number of lines at the end of the log to display",
73
+ "name": "numOfLines",
74
+ "hasDynamicHelp": false,
75
+ "multiple": false,
76
+ "type": "option"
68
77
  }
69
78
  },
70
79
  "hasDynamicHelp": false,
@@ -84,12 +93,30 @@
84
93
  },
85
94
  "restart": {
86
95
  "aliases": [],
87
- "args": {},
96
+ "args": {
97
+ "layer": {
98
+ "description": "network layer to view. e.g. gl0",
99
+ "name": "layer"
100
+ }
101
+ },
88
102
  "description": "A full shutdown of the validator node, then restart",
89
103
  "examples": [
90
104
  "<%= config.bin %> <%= command.id %>"
91
105
  ],
92
- "flags": {},
106
+ "flags": {
107
+ "project": {
108
+ "char": "p",
109
+ "description": "Specify the project name to use",
110
+ "helpGroup": "GLOBAL",
111
+ "name": "project",
112
+ "hasDynamicHelp": false,
113
+ "multiple": false,
114
+ "options": [
115
+ "hypergraph"
116
+ ],
117
+ "type": "option"
118
+ }
119
+ },
93
120
  "hasDynamicHelp": false,
94
121
  "hiddenAliases": [],
95
122
  "id": "restart",
@@ -237,5 +264,5 @@
237
264
  ]
238
265
  }
239
266
  },
240
- "version": "0.0.7"
267
+ "version": "0.0.9"
241
268
  }
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.7",
4
+ "version": "0.0.9",
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",
@@ -61,12 +63,14 @@
61
63
  "typescript": "^5"
62
64
  },
63
65
  "files": [
64
- "./bin",
65
- "./dist",
66
- "./oclif.manifest.json",
67
- "./projects",
68
- "./README.md",
69
- "./LICENSE"
66
+ "bin",
67
+ "dist",
68
+ "oclif.manifest.json",
69
+ "install-dependencies.sh",
70
+ "projects",
71
+ "scripts",
72
+ "README.md",
73
+ "LICENSE"
70
74
  ],
71
75
  "homepage": "https://github.com/Constellation-Labs/node-pilot",
72
76
  "keywords": [
@@ -5,23 +5,28 @@ RUN apt update && apt install -y openjdk-11-jre
5
5
  RUN apt install -y curl jq wget
6
6
 
7
7
  # Install necessary dependencies for adding NodeSource repository
8
- #RUN apt-get update && apt-get install -y gnupg ca-certificates
9
- #
10
- ## Import the NodeSource GPG key
11
- #RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
12
- #
13
- ## Add the NodeSource repository for Node.js 22
14
- #ENV NODE_MAJOR=22
15
- #RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
16
- #
17
- ## Update package lists and install Node.js and npm
18
- #RUN apt-get update && apt-get install -y nodejs
19
- #
20
- ## Verify the installation
21
- #RUN node -v
22
- #RUN npm -v
8
+ RUN apt-get update && apt-get install -y gnupg ca-certificates
23
9
 
10
+ # Import the NodeSource GPG key
11
+ RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
24
12
 
13
+ # Add the NodeSource repository for Node.js 22
14
+ ENV NODE_MAJOR=22
15
+ RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
16
+
17
+ # Update package lists and install Node.js and npm
18
+ RUN apt-get update && apt-get install -y nodejs
19
+
20
+ # Verify the installation
21
+ RUN node -v
22
+ RUN npm -v
23
+
24
+ # Create a directory for global npm packages
25
+ RUN mkdir -p /home/node/.npm-global
26
+ ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
27
+ ENV PATH=$PATH:/home/node/.npm-global/bin
28
+
29
+ # Add app JARS
25
30
  RUN mkdir -p /app/jars
26
31
 
27
32
  COPY dist/keytool.jar /app/jars/keytool.jar
@@ -30,10 +35,14 @@ COPY dist/wallet.jar /app/jars/wallet.jar
30
35
  COPY dist/gl1.jar /app/jars/gl1.jar
31
36
  COPY dist/gl0.jar /app/jars/gl0.jar
32
37
 
33
- COPY ./entrypoint.sh /app/entrypoint.sh
34
-
35
- #COPY ../apps/health-check /health-check
38
+ # Add health-check
39
+ #COPY ./health-check /health-check
40
+ #RUN chmod +x /health-check/bin/run.sh
41
+ #RUN chmod +x /health-check/bin/hydrate.sh
42
+ RUN npm install -g "@constellation-network/node-pilot-health-check"
36
43
 
44
+ # Add entrypoint
45
+ COPY ./entrypoint.sh /app/entrypoint.sh
37
46
  RUN chmod +x /app/entrypoint.sh
38
47
 
39
48
  WORKDIR /app
@@ -3,12 +3,16 @@ networks:
3
3
  driver: bridge
4
4
 
5
5
  services:
6
+ autoheal:
7
+ image: willfarrell/autoheal
8
+ volumes:
9
+ - /var/run/docker.sock:/var/run/docker.sock
6
10
  gl0:
7
11
  image: constellationnetwork/tessellation${CL_DOCKER_CORE_REPO:-}:${DOCKER_IMAGE_VERSION:-latest}
8
12
  container_name: gl0
9
13
  networks:
10
14
  - tessellation-network
11
- # restart: unless-stopped
15
+ restart: unless-stopped
12
16
  env_file:
13
17
  - gl0.env
14
18
  ports:
@@ -19,18 +23,19 @@ services:
19
23
  - ./seedlist:/app/seedlist:ro
20
24
  - ./app-data/gl0-logs:/app/logs
21
25
  - ./app-data/gl0-data:/app/data
22
- - ${CL_DOCKER_PRIORITY_SEEDLIST:-/dev/null}:/app/priority-seedlist:ro
23
- # healthcheck:
24
- # test: ["CMD", "/app/internal-health-check.sh"]
25
- # interval: 15s
26
- # timeout: 5s
27
- # start_period: 30s
26
+ healthcheck:
27
+ test: ["CMD", "cpilotHC"]
28
+ interval: 15s
29
+ retries: 1
30
+ timeout: 15s
31
+ start_period: 30s
28
32
  profiles: ["gl0"]
29
- # user: ${DOCKER_USER_ID:-}
33
+ labels:
34
+ autoheal: "true"
30
35
  gl1:
31
36
  image: constellationnetwork/tessellation${CL_DOCKER_CORE_REPO:-}:${DOCKER_IMAGE_VERSION:-latest}
32
37
  container_name: gl1
33
- # restart: unless-stopped
38
+ restart: unless-stopped
34
39
  networks:
35
40
  - tessellation-network
36
41
  env_file:
@@ -40,10 +45,8 @@ services:
40
45
  - "9011:9011" # P2P HTTP
41
46
  volumes:
42
47
  - ./key.p12:/app/key.p12:ro
43
- - ./seedlist:/app/seedlist:ro
44
48
  - ./app-data/gl1-logs:/app/logs
45
49
  - ./app-data/gl1-data:/app/data
46
- - ${CL_DOCKER_PRIORITY_SEEDLIST:-/dev/null}:/app/priority-seedlist:ro
47
50
  # healthcheck:
48
51
  # test: ["CMD", "/app/internal-health-check.sh"]
49
52
  # interval: 3s
@@ -51,4 +54,3 @@ services:
51
54
  # retries: 5
52
55
  # start_period: 10s
53
56
  profiles: ["gl1"]
54
- # user: ${DOCKER_USER_ID:-}
@@ -0,0 +1,4 @@
1
+ CL_LB=https://l0-lb-integrationnet.constellationnetwork.io
2
+ CL_PUBLIC_HTTP_PORT=9000
3
+ CL_P2P_HTTP_PORT=9001
4
+ CL_CLI_HTTP_PORT=9002
@@ -0,0 +1,4 @@
1
+ CL_LB=https://l1-lb-integrationnet.constellationnetwork.io
2
+ CL_PUBLIC_HTTP_PORT=9010
3
+ CL_P2P_HTTP_PORT=9011
4
+ CL_CLI_HTTP_PORT=9012
@@ -0,0 +1,8 @@
1
+ CL_APP_ENV=integrationnet
2
+ CL_COLLATERAL=0
3
+ CL_L0_PEER_HTTP_HOST=13.52.205.240
4
+ CL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
5
+ CL_L0_PEER_HTTP_PORT=9000
6
+ CL_GLOBAL_L0_PEER_HOST=13.52.205.240
7
+ CL_GLOBAL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
8
+ CL_GLOBAL_L0_PEER_HTTP_PORT=9000
@@ -0,0 +1,9 @@
1
+ SOURCE_NODE_1_PORT=9000
2
+ SOURCE_NODE_1_HOST=13.52.205.240
3
+ SOURCE_NODE_1_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
4
+ SOURCE_NODE_2_PORT=9000
5
+ SOURCE_NODE_2_HOST=50.18.155.22
6
+ SOURCE_NODE_2_ID=3458a688925a4bd89f2ac2c695362e44d2e0c2903bdbb41b341a4d39283b22d8c85b487bd33cc5d36dbe5e31b5b00a10a6eab802718ead4ed7192ade5a5d1941
7
+ SOURCE_NODE_3_PORT=9000
8
+ SOURCE_NODE_3_HOST=52.9.216.57
9
+ SOURCE_NODE_3_ID=46daea11ca239cb8c0c8cdeb27db9dbe9c03744908a8a389a60d14df2ddde409260a93334d74957331eec1af323f458b12b3a6c3b8e05885608aae7e3a77eac7