@constellation-network/node-pilot 0.0.7 → 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.
- package/README.md +14 -13
- package/dist/checks/check-dependencies.d.ts +1 -0
- package/dist/checks/check-dependencies.js +44 -0
- package/dist/checks/check-initial-setup.js +6 -4
- package/dist/checks/check-network.d.ts +1 -0
- package/dist/checks/check-network.js +48 -0
- package/dist/checks/check-node-ctl.d.ts +5 -0
- package/dist/checks/check-node-ctl.js +88 -0
- package/dist/checks/check-project.js +22 -7
- package/dist/clm.js +1 -1
- package/dist/commands/logs.d.ts +1 -0
- package/dist/commands/logs.js +5 -3
- package/dist/commands/status.js +4 -0
- package/dist/commands/test.d.ts +1 -0
- package/dist/commands/test.js +27 -5
- package/dist/config-store.d.ts +8 -5
- package/dist/config-store.js +10 -0
- package/dist/helpers/docker-helper.js +18 -5
- package/dist/helpers/key-file-helper.js +1 -1
- package/dist/helpers/project-helper.d.ts +1 -0
- package/dist/helpers/project-helper.js +52 -0
- package/dist/helpers/prompt-helper.d.ts +0 -1
- package/dist/helpers/prompt-helper.js +0 -51
- package/dist/services/cluster-service.d.ts +2 -1
- package/dist/services/cluster-service.js +10 -0
- package/dist/services/fastforward-service.js +9 -3
- package/dist/services/get-random-node.d.ts +2 -0
- package/dist/services/get-random-node.js +16 -0
- package/dist/services/node-service.d.ts +4 -0
- package/dist/services/node-service.js +15 -0
- package/dist/services/shell-service.d.ts +3 -1
- package/dist/services/shell-service.js +32 -6
- package/dist/types.d.ts +36 -3
- package/install-dependencies.sh +100 -0
- package/oclif.manifest.json +9 -1
- package/package.json +5 -2
- package/projects/hypergraph/networks/integrationnet.env +16 -8
- package/projects/hypergraph/networks/mainnet.env +16 -7
- package/projects/hypergraph/networks/testnet.env +16 -8
- package/projects/hypergraph/scripts/install-dependencies.sh +3 -3
- package/projects/hypergraph/scripts/install.sh +4 -6
@@ -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
|
};
|
@@ -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)
|
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.
|
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,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
|
-
|
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
|
-
|
9
|
+
clm.debug(`Checking if command ${cmd} is available...`);
|
10
|
+
return this.runCommand(`command -v ${cmd}`)
|
10
11
|
.then(() => true)
|
11
|
-
.catch(() =>
|
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
|
-
|
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
|
-
|
40
|
+
clm.debug(`START Running command: "${command}"`);
|
37
41
|
let nodeEnv;
|
38
42
|
if (env) {
|
39
43
|
nodeEnv = { ...env, ...process.env };
|
40
44
|
}
|
41
|
-
|
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
|
package/oclif.manifest.json
CHANGED
@@ -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.
|
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.
|
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=
|
1
|
+
CL_APP_ENV=integrationnet
|
2
2
|
CL_COLLATERAL=0
|
3
|
-
CL_L0_PEER_HTTP_PORT=
|
4
|
-
CL_L0_PEER_HTTP_HOST=
|
5
|
-
CL_L0_PEER_ID=
|
6
|
-
CL_GLOBAL_L0_PEER_HTTP_PORT=
|
7
|
-
CL_GLOBAL_L0_PEER_HOST=
|
8
|
-
CL_GLOBAL_L0_PEER_ID=
|
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=
|
1
|
+
CL_APP_ENV=mainnet
|
2
2
|
CL_COLLATERAL=25000000000000
|
3
|
-
CL_L0_PEER_HTTP_PORT=
|
4
|
-
CL_L0_PEER_HTTP_HOST=
|
5
|
-
CL_L0_PEER_ID=
|
6
|
-
CL_GLOBAL_L0_PEER_HTTP_PORT=
|
7
|
-
CL_GLOBAL_L0_PEER_HOST=
|
8
|
-
CL_GLOBAL_L0_PEER_ID=
|
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=
|
1
|
+
CL_APP_ENV=testnet
|
2
2
|
CL_COLLATERAL=0
|
3
|
-
CL_L0_PEER_HTTP_PORT=
|
4
|
-
CL_L0_PEER_HTTP_HOST=
|
5
|
-
CL_L0_PEER_ID=
|
6
|
-
CL_GLOBAL_L0_PEER_HTTP_PORT=
|
7
|
-
CL_GLOBAL_L0_PEER_HOST=
|
8
|
-
CL_GLOBAL_L0_PEER_ID=
|
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
|
-
#!/
|
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.
|
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
|
281
|
+
nvm install 22
|
282
282
|
|
283
283
|
# Verify installation
|
284
284
|
echo "Node version: $(node -v)"
|