genlayer 0.18.0 → 0.18.2-beta.0
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/CHANGELOG.md +9 -0
- package/dist/index.js +25711 -12445
- package/package.json +2 -2
- package/src/commands/contracts/call.ts +7 -49
- package/src/commands/contracts/deploy.ts +17 -13
- package/src/commands/contracts/index.ts +36 -11
- package/src/commands/contracts/write.ts +49 -0
- package/src/commands/general/init.ts +15 -20
- package/src/commands/general/start.ts +14 -10
- package/src/commands/keygen/create.ts +2 -2
- package/src/commands/network/index.ts +14 -0
- package/src/commands/network/setNetwork.ts +60 -0
- package/src/index.ts +9 -7
- package/src/lib/actions/BaseAction.ts +20 -18
- package/tests/actions/call.test.ts +22 -86
- package/tests/actions/create.test.ts +8 -8
- package/tests/actions/deploy.test.ts +72 -60
- package/tests/actions/init.test.ts +173 -102
- package/tests/actions/setNetwork.test.ts +199 -0
- package/tests/actions/start.test.ts +48 -24
- package/tests/actions/write.test.ts +102 -0
- package/tests/commands/network.test.ts +60 -0
- package/tests/commands/write.test.ts +76 -0
- package/tests/index.test.ts +5 -2
- package/tests/libs/baseAction.test.ts +37 -26
- package/tests/services/simulator.test.ts +98 -102
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genlayer",
|
|
3
|
-
"version": "0.18.0",
|
|
3
|
+
"version": "0.18.2-beta.0",
|
|
4
4
|
"description": "GenLayer Command Line Tool",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"dotenv": "^16.4.5",
|
|
65
65
|
"ethers": "^6.13.4",
|
|
66
66
|
"fs-extra": "^11.3.0",
|
|
67
|
-
"genlayer-js": "^0.
|
|
67
|
+
"genlayer-js": "^0.11.0",
|
|
68
68
|
"inquirer": "^12.0.0",
|
|
69
69
|
"node-fetch": "^3.0.0",
|
|
70
70
|
"open": "^10.1.0",
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { GenLayerClient } from "genlayer-js/types";
|
|
3
|
-
import { BaseAction } from "../../lib/actions/BaseAction";
|
|
1
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
4
2
|
|
|
5
3
|
export interface CallOptions {
|
|
6
4
|
args: any[];
|
|
7
5
|
rpc?: string;
|
|
8
6
|
}
|
|
9
7
|
|
|
10
|
-
export class CallAction extends BaseAction{
|
|
8
|
+
export class CallAction extends BaseAction {
|
|
11
9
|
constructor() {
|
|
12
10
|
super();
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
async call({
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
contractAddress,
|
|
15
|
+
method,
|
|
16
|
+
args,
|
|
17
|
+
rpc,
|
|
18
|
+
}: {
|
|
21
19
|
contractAddress: string;
|
|
22
20
|
method: string;
|
|
23
21
|
args: any[];
|
|
@@ -27,26 +25,7 @@ export class CallAction extends BaseAction{
|
|
|
27
25
|
await client.initializeConsensusSmartContract();
|
|
28
26
|
this.startSpinner(`Calling method ${method} on contract at ${contractAddress}...`);
|
|
29
27
|
|
|
30
|
-
const contractSchema = await client.getContractSchema(contractAddress);
|
|
31
|
-
|
|
32
|
-
if(!contractSchema.methods.hasOwnProperty(method)){
|
|
33
|
-
this.failSpinner(`method ${method} not found.`);
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const readonly = contractSchema.methods[method as any].readonly;
|
|
38
|
-
|
|
39
|
-
if (readonly) {
|
|
40
|
-
await this.executeRead(contractAddress, method, args);
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
await this.executeWrite(contractAddress, method, args);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private async executeRead(contractAddress: string, method: string, args: any[]): Promise<void> {
|
|
48
28
|
try {
|
|
49
|
-
const client = await this.getClient();
|
|
50
29
|
const result = await client.readContract({
|
|
51
30
|
address: contractAddress as any,
|
|
52
31
|
functionName: method,
|
|
@@ -57,25 +36,4 @@ export class CallAction extends BaseAction{
|
|
|
57
36
|
this.failSpinner("Error during read operation", error);
|
|
58
37
|
}
|
|
59
38
|
}
|
|
60
|
-
|
|
61
|
-
private async executeWrite(contractAddress: string, method: string, args: any[]): Promise<void> {
|
|
62
|
-
try {
|
|
63
|
-
const client = await this.getClient();
|
|
64
|
-
const hash = await client.writeContract({
|
|
65
|
-
address: contractAddress as any,
|
|
66
|
-
functionName: method,
|
|
67
|
-
args,
|
|
68
|
-
value: 0n,
|
|
69
|
-
});
|
|
70
|
-
const result = await client.waitForTransactionReceipt({
|
|
71
|
-
hash,
|
|
72
|
-
retries: 15,
|
|
73
|
-
interval: 2000,
|
|
74
|
-
});
|
|
75
|
-
this.log("Write transaction hash:", hash);
|
|
76
|
-
this.succeedSpinner("Write operation successfully executed", result);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
this.failSpinner("Error during write operation", error);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
39
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { TransactionStatus } from "genlayer-js/types";
|
|
8
|
-
import { buildSync } from "esbuild";
|
|
3
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
4
|
+
import {pathToFileURL} from "url";
|
|
5
|
+
import {TransactionStatus} from "genlayer-js/types";
|
|
6
|
+
import {buildSync} from "esbuild";
|
|
9
7
|
|
|
10
8
|
export interface DeployOptions {
|
|
11
9
|
contract?: string;
|
|
@@ -44,7 +42,7 @@ export class DeployAction extends BaseAction {
|
|
|
44
42
|
target: "es2020",
|
|
45
43
|
sourcemap: false,
|
|
46
44
|
});
|
|
47
|
-
|
|
45
|
+
await this.executeJsScript(filePath, outFile, rpcUrl);
|
|
48
46
|
} catch (error) {
|
|
49
47
|
this.failSpinner(`Error executing: ${filePath}`, error);
|
|
50
48
|
} finally {
|
|
@@ -52,13 +50,17 @@ export class DeployAction extends BaseAction {
|
|
|
52
50
|
}
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
private async executeJsScript(
|
|
53
|
+
private async executeJsScript(
|
|
54
|
+
filePath: string,
|
|
55
|
+
transpiledFilePath?: string,
|
|
56
|
+
rpcUrl?: string,
|
|
57
|
+
): Promise<void> {
|
|
56
58
|
this.startSpinner(`Executing file: ${filePath}`);
|
|
57
59
|
try {
|
|
58
60
|
const module = await import(pathToFileURL(transpiledFilePath || filePath).href);
|
|
59
61
|
if (!module.default || typeof module.default !== "function") {
|
|
60
62
|
this.failSpinner(`No "default" function found in: ${filePath}`);
|
|
61
|
-
return
|
|
63
|
+
return;
|
|
62
64
|
}
|
|
63
65
|
const client = await this.getClient(rpcUrl);
|
|
64
66
|
await module.default(client);
|
|
@@ -74,7 +76,8 @@ export class DeployAction extends BaseAction {
|
|
|
74
76
|
this.failSpinner("No deploy folder found.");
|
|
75
77
|
return;
|
|
76
78
|
}
|
|
77
|
-
const files = fs
|
|
79
|
+
const files = fs
|
|
80
|
+
.readdirSync(this.deployDir)
|
|
78
81
|
.filter(file => file.endsWith(".ts") || file.endsWith(".js"))
|
|
79
82
|
.sort((a, b) => {
|
|
80
83
|
const numA = parseInt(a.split("_")[0]);
|
|
@@ -127,16 +130,17 @@ export class DeployAction extends BaseAction {
|
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
const leaderOnly = false;
|
|
130
|
-
const deployParams: any = {
|
|
133
|
+
const deployParams: any = {code: contractCode, args: options.args, leaderOnly};
|
|
131
134
|
|
|
132
135
|
this.setSpinnerText("Starting contract deployment...");
|
|
133
136
|
this.log("Deployment Parameters:", deployParams);
|
|
134
137
|
|
|
135
138
|
const hash = (await client.deployContract(deployParams)) as any;
|
|
139
|
+
this.log("Deployment Transaction Hash:", hash);
|
|
136
140
|
const result = await client.waitForTransactionReceipt({
|
|
137
141
|
hash,
|
|
138
|
-
retries:
|
|
139
|
-
interval:
|
|
142
|
+
retries: 50,
|
|
143
|
+
interval: 5000,
|
|
140
144
|
status: TransactionStatus.ACCEPTED,
|
|
141
145
|
});
|
|
142
146
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import {Command} from "commander";
|
|
2
|
+
import {DeployAction, DeployOptions, DeployScriptsOptions} from "./deploy";
|
|
3
|
+
import {CallAction, CallOptions} from "./call";
|
|
4
|
+
import {WriteAction, WriteOptions} from "./write";
|
|
4
5
|
|
|
5
6
|
function parseArg(value: string, previous: any[] = []): any[] {
|
|
6
7
|
if (value === "true") return [...previous, true];
|
|
@@ -10,31 +11,55 @@ function parseArg(value: string, previous: any[] = []): any[] {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export function initializeContractsCommands(program: Command) {
|
|
13
|
-
|
|
14
14
|
program
|
|
15
15
|
.command("deploy")
|
|
16
16
|
.description("Deploy intelligent contracts")
|
|
17
17
|
.option("--contract <contractPath>", "Path to the smart contract to deploy")
|
|
18
18
|
.option("--rpc <rpcUrl>", "RPC URL for the network")
|
|
19
|
-
.option(
|
|
19
|
+
.option(
|
|
20
|
+
"--args <args...>",
|
|
21
|
+
"Positional arguments for the contract (space-separated, use quotes for multi-word arguments)",
|
|
22
|
+
parseArg,
|
|
23
|
+
[],
|
|
24
|
+
)
|
|
20
25
|
.action(async (options: DeployOptions) => {
|
|
21
26
|
const deployer = new DeployAction();
|
|
22
|
-
if(options.contract){
|
|
27
|
+
if (options.contract) {
|
|
23
28
|
await deployer.deploy(options);
|
|
24
|
-
}else {
|
|
25
|
-
const deployScriptsOptions: DeployScriptsOptions = {
|
|
29
|
+
} else {
|
|
30
|
+
const deployScriptsOptions: DeployScriptsOptions = {rpc: options.rpc};
|
|
26
31
|
await deployer.deployScripts(deployScriptsOptions);
|
|
27
32
|
}
|
|
28
33
|
});
|
|
29
34
|
|
|
30
35
|
program
|
|
31
36
|
.command("call <contractAddress> <method>")
|
|
32
|
-
.description("Call a contract method")
|
|
37
|
+
.description("Call a contract method without sending a transaction or changing the state")
|
|
33
38
|
.option("--rpc <rpcUrl>", "RPC URL for the network")
|
|
34
|
-
.option(
|
|
39
|
+
.option(
|
|
40
|
+
"--args <args...>",
|
|
41
|
+
"Positional arguments for the method (space-separated, use quotes for multi-word arguments)",
|
|
42
|
+
parseArg,
|
|
43
|
+
[],
|
|
44
|
+
)
|
|
35
45
|
.action(async (contractAddress: string, method: string, options: CallOptions) => {
|
|
36
46
|
const caller = new CallAction();
|
|
37
|
-
await caller.call({
|
|
47
|
+
await caller.call({contractAddress, method, ...options});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
program
|
|
51
|
+
.command("write <contractAddress> <method>")
|
|
52
|
+
.description("Sends a transaction to a contract method that modifies the state")
|
|
53
|
+
.option("--rpc <rpcUrl>", "RPC URL for the network")
|
|
54
|
+
.option(
|
|
55
|
+
"--args <args...>",
|
|
56
|
+
"Positional arguments for the method (space-separated, use quotes for multi-word arguments)",
|
|
57
|
+
parseArg,
|
|
58
|
+
[],
|
|
59
|
+
)
|
|
60
|
+
.action(async (contractAddress: string, method: string, options: WriteOptions) => {
|
|
61
|
+
const writer = new WriteAction();
|
|
62
|
+
await writer.write({contractAddress, method, ...options});
|
|
38
63
|
});
|
|
39
64
|
|
|
40
65
|
return program;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// import {simulator} from "genlayer-js/chains";
|
|
2
|
+
// import type {GenLayerClient} from "genlayer-js/types";
|
|
3
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
4
|
+
|
|
5
|
+
export interface WriteOptions {
|
|
6
|
+
args: any[];
|
|
7
|
+
rpc?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class WriteAction extends BaseAction {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async write({
|
|
16
|
+
contractAddress,
|
|
17
|
+
method,
|
|
18
|
+
args,
|
|
19
|
+
rpc,
|
|
20
|
+
}: {
|
|
21
|
+
contractAddress: string;
|
|
22
|
+
method: string;
|
|
23
|
+
args: any[];
|
|
24
|
+
rpc?: string;
|
|
25
|
+
}): Promise<void> {
|
|
26
|
+
const client = await this.getClient(rpc);
|
|
27
|
+
await client.initializeConsensusSmartContract();
|
|
28
|
+
this.startSpinner(`Calling write method ${method} on contract at ${contractAddress}...`);
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const hash = await client.writeContract({
|
|
32
|
+
address: contractAddress as any,
|
|
33
|
+
functionName: method,
|
|
34
|
+
args,
|
|
35
|
+
value: 0n,
|
|
36
|
+
});
|
|
37
|
+
this.log("Write Transaction Hash:", hash);
|
|
38
|
+
|
|
39
|
+
const result = await client.waitForTransactionReceipt({
|
|
40
|
+
hash,
|
|
41
|
+
retries: 100,
|
|
42
|
+
interval: 5000,
|
|
43
|
+
});
|
|
44
|
+
this.succeedSpinner("Write operation successfully executed", result);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
this.failSpinner("Error during write operation", error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import inquirer from "inquirer";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import {DistinctQuestion} from "inquirer";
|
|
3
|
+
import {ISimulatorService} from "../../lib/interfaces/ISimulatorService";
|
|
4
|
+
import {AI_PROVIDERS_CONFIG, AiProviders} from "../../lib/config/simulator";
|
|
5
|
+
import {OllamaAction} from "../update/ollama";
|
|
6
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
7
|
+
import {SimulatorService} from "../../lib/services/simulator";
|
|
8
8
|
|
|
9
9
|
export interface InitActionOptions {
|
|
10
10
|
numValidators: number;
|
|
@@ -14,14 +14,14 @@ export interface InitActionOptions {
|
|
|
14
14
|
ollama: boolean;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
function getRequirementsErrorMessage({
|
|
17
|
+
function getRequirementsErrorMessage({docker}: Record<string, boolean>): string {
|
|
18
18
|
if (!docker) {
|
|
19
19
|
return "Docker is not installed. Please install Docker and try again.\n";
|
|
20
20
|
}
|
|
21
21
|
return "";
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
function getVersionErrorMessage({
|
|
24
|
+
function getVersionErrorMessage({docker, node}: Record<string, string>): string {
|
|
25
25
|
let message = "";
|
|
26
26
|
|
|
27
27
|
if (docker) {
|
|
@@ -73,7 +73,7 @@ export class InitAction extends BaseAction {
|
|
|
73
73
|
const confirmMessage = isRunning
|
|
74
74
|
? `GenLayer Localnet is already running and this command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?`
|
|
75
75
|
: `This command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?`;
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
await this.confirmPrompt(confirmMessage);
|
|
78
78
|
|
|
79
79
|
this.logInfo(`Initializing GenLayer CLI with ${options.numValidators} validators`);
|
|
@@ -90,8 +90,7 @@ export class InitAction extends BaseAction {
|
|
|
90
90
|
name: "selectedLlmProviders",
|
|
91
91
|
message: "Select which LLM providers do you want to use:",
|
|
92
92
|
choices: this.simulatorService.getAiProvidersOptions(true, options.ollama ? [] : ["ollama"]),
|
|
93
|
-
validate: (answer)
|
|
94
|
-
answer.length < 1 ? "You must choose at least one option." : true,
|
|
93
|
+
validate: answer => (answer.length < 1 ? "You must choose at least one option." : true),
|
|
95
94
|
},
|
|
96
95
|
];
|
|
97
96
|
const llmProvidersAnswer = await inquirer.prompt(llmQuestions);
|
|
@@ -100,7 +99,7 @@ export class InitAction extends BaseAction {
|
|
|
100
99
|
let defaultOllamaModel = this.getConfig().defaultOllamaModel;
|
|
101
100
|
const aiProvidersEnvVars: Record<string, string> = {};
|
|
102
101
|
const configurableAiProviders = selectedLlmProviders.filter(
|
|
103
|
-
(provider: AiProviders) => AI_PROVIDERS_CONFIG[provider].envVar
|
|
102
|
+
(provider: AiProviders) => AI_PROVIDERS_CONFIG[provider].envVar,
|
|
104
103
|
);
|
|
105
104
|
for (const provider of configurableAiProviders) {
|
|
106
105
|
const providerConfig = AI_PROVIDERS_CONFIG[provider];
|
|
@@ -119,14 +118,13 @@ export class InitAction extends BaseAction {
|
|
|
119
118
|
|
|
120
119
|
this.startSpinner("Configuring GenLayer Localnet environment...");
|
|
121
120
|
this.simulatorService.addConfigToEnvFile(aiProvidersEnvVars);
|
|
122
|
-
this.simulatorService.addConfigToEnvFile({
|
|
121
|
+
this.simulatorService.addConfigToEnvFile({LOCALNETVERSION: localnetVersion});
|
|
123
122
|
|
|
124
123
|
this.setSpinnerText("Running GenLayer Localnet...");
|
|
125
124
|
await this.simulatorService.runSimulator();
|
|
126
125
|
|
|
127
126
|
this.setSpinnerText("Waiting for localnet to be ready...");
|
|
128
|
-
const {
|
|
129
|
-
await this.simulatorService.waitForSimulatorToBeReady();
|
|
127
|
+
const {initialized, errorCode, errorMessage} = await this.simulatorService.waitForSimulatorToBeReady();
|
|
130
128
|
if (!initialized) {
|
|
131
129
|
if (errorCode === "ERROR") {
|
|
132
130
|
this.failSpinner(`Unable to initialize the GenLayer Localnet: ${errorMessage}`);
|
|
@@ -134,7 +132,7 @@ export class InitAction extends BaseAction {
|
|
|
134
132
|
}
|
|
135
133
|
if (errorCode === "TIMEOUT") {
|
|
136
134
|
this.failSpinner(
|
|
137
|
-
"The localnet is taking too long to initialize. Please try again after the localnet is ready."
|
|
135
|
+
"The localnet is taking too long to initialize. Please try again after the localnet is ready.",
|
|
138
136
|
);
|
|
139
137
|
return;
|
|
140
138
|
}
|
|
@@ -153,10 +151,7 @@ export class InitAction extends BaseAction {
|
|
|
153
151
|
|
|
154
152
|
this.startSpinner("Initializing validators...");
|
|
155
153
|
await this.simulatorService.deleteAllValidators();
|
|
156
|
-
await this.simulatorService.createRandomValidators(
|
|
157
|
-
Number(options.numValidators),
|
|
158
|
-
selectedLlmProviders
|
|
159
|
-
);
|
|
154
|
+
await this.simulatorService.createRandomValidators(Number(options.numValidators), selectedLlmProviders);
|
|
160
155
|
|
|
161
156
|
if (options.resetDb) {
|
|
162
157
|
this.setSpinnerText("Cleaning database...");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import inquirer from "inquirer";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import {ISimulatorService} from "../../lib/interfaces/ISimulatorService";
|
|
3
|
+
import {DistinctQuestion} from "inquirer";
|
|
4
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
5
|
+
import {SimulatorService} from "../../lib/services/simulator";
|
|
6
6
|
|
|
7
7
|
export interface StartActionOptions {
|
|
8
8
|
resetValidators: boolean;
|
|
@@ -21,7 +21,7 @@ export class StartAction extends BaseAction {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
async execute(options: StartActionOptions) {
|
|
24
|
-
const {
|
|
24
|
+
const {resetValidators, numValidators, headless, resetDb, ollama} = options;
|
|
25
25
|
|
|
26
26
|
this.simulatorService.setComposeOptions(headless, ollama);
|
|
27
27
|
this.startSpinner("Checking CLI version...");
|
|
@@ -49,7 +49,7 @@ export class StartAction extends BaseAction {
|
|
|
49
49
|
|
|
50
50
|
try {
|
|
51
51
|
this.setSpinnerText("Waiting for the simulator to be ready...");
|
|
52
|
-
const {
|
|
52
|
+
const {initialized, errorCode, errorMessage} = await this.simulatorService.waitForSimulatorToBeReady();
|
|
53
53
|
|
|
54
54
|
if (!initialized) {
|
|
55
55
|
if (errorCode === "ERROR") {
|
|
@@ -61,7 +61,6 @@ export class StartAction extends BaseAction {
|
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
|
|
65
64
|
} catch (error) {
|
|
66
65
|
this.failSpinner("Error waiting for the simulator to be ready", error);
|
|
67
66
|
return;
|
|
@@ -83,12 +82,15 @@ export class StartAction extends BaseAction {
|
|
|
83
82
|
name: "selectedLlmProviders",
|
|
84
83
|
message: "Select which LLM providers do you want to use:",
|
|
85
84
|
choices: this.simulatorService.getAiProvidersOptions(false, ollama ? [] : ["ollama"]),
|
|
86
|
-
validate:
|
|
85
|
+
validate: answer => (answer.length < 1 ? "You must choose at least one option." : true),
|
|
87
86
|
},
|
|
88
87
|
];
|
|
89
88
|
|
|
90
89
|
const llmProvidersAnswer = await inquirer.prompt(questions);
|
|
91
|
-
await this.simulatorService.createRandomValidators(
|
|
90
|
+
await this.simulatorService.createRandomValidators(
|
|
91
|
+
numValidators,
|
|
92
|
+
llmProvidersAnswer.selectedLlmProviders,
|
|
93
|
+
);
|
|
92
94
|
} catch (error) {
|
|
93
95
|
this.failSpinner("Unable to initialize the validators", error);
|
|
94
96
|
return;
|
|
@@ -96,7 +98,9 @@ export class StartAction extends BaseAction {
|
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
let successMessage = "GenLayer simulator initialized successfully! ";
|
|
99
|
-
successMessage += headless
|
|
101
|
+
successMessage += headless
|
|
102
|
+
? ""
|
|
103
|
+
: `Go to ${this.simulatorService.getFrontendUrl()} in your browser to access it.`;
|
|
100
104
|
this.succeedSpinner(successMessage);
|
|
101
105
|
|
|
102
106
|
if (!headless) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
2
2
|
|
|
3
3
|
export interface CreateKeypairOptions {
|
|
4
4
|
output: string;
|
|
@@ -19,4 +19,4 @@ export class KeypairCreator extends BaseAction {
|
|
|
19
19
|
this.failSpinner("Failed to generate keypair", error);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {Command} from "commander";
|
|
2
|
+
import {NetworkActions} from "./setNetwork";
|
|
3
|
+
|
|
4
|
+
export function initializeNetworkCommands(program: Command) {
|
|
5
|
+
const networkActions = new NetworkActions();
|
|
6
|
+
|
|
7
|
+
program
|
|
8
|
+
.command("network")
|
|
9
|
+
.description("Set the network to use")
|
|
10
|
+
.argument("[network]", "The network to use")
|
|
11
|
+
.action((networkName?: string) => networkActions.setNetwork(networkName));
|
|
12
|
+
|
|
13
|
+
return program;
|
|
14
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {AiProviders} from "@/lib/config/simulator";
|
|
2
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
3
|
+
import inquirer, {DistinctQuestion} from "inquirer";
|
|
4
|
+
import {localnet, studionet, testnetAsimov} from "genlayer-js/chains";
|
|
5
|
+
import {} from "genlayer-js/chains";
|
|
6
|
+
|
|
7
|
+
const networks = [
|
|
8
|
+
{
|
|
9
|
+
name: localnet.name,
|
|
10
|
+
alias: "localnet",
|
|
11
|
+
value: localnet,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: studionet.name,
|
|
15
|
+
alias: "studionet",
|
|
16
|
+
value: studionet,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: testnetAsimov.name,
|
|
20
|
+
alias: "testnet-asimov",
|
|
21
|
+
value: testnetAsimov,
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export class NetworkActions extends BaseAction {
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async setNetwork(networkName?: string): Promise<void> {
|
|
31
|
+
if (networkName || networkName === "") {
|
|
32
|
+
if (!networks.some(n => n.name === networkName || n.alias === networkName)) {
|
|
33
|
+
this.failSpinner(`Network ${networkName} not found`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const selectedNetwork = networks.find(n => n.name === networkName || n.alias === networkName);
|
|
37
|
+
if (!selectedNetwork) {
|
|
38
|
+
this.failSpinner(`Network ${networkName} not found`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.writeConfig("network", JSON.stringify(selectedNetwork.value));
|
|
42
|
+
this.succeedSpinner(`Network successfully set to ${selectedNetwork.name}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const networkQuestions: DistinctQuestion[] = [
|
|
47
|
+
{
|
|
48
|
+
type: "list",
|
|
49
|
+
name: "selectedNetwork",
|
|
50
|
+
message: "Select which network do you want to use:",
|
|
51
|
+
choices: networks,
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
const networkAnswer = await inquirer.prompt(networkQuestions);
|
|
55
|
+
const selectedNetwork = networkAnswer.selectedNetwork;
|
|
56
|
+
|
|
57
|
+
this.writeConfig("network", JSON.stringify(selectedNetwork));
|
|
58
|
+
this.succeedSpinner(`Network successfully set to ${selectedNetwork.name}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
import {program} from "commander";
|
|
3
3
|
import {version} from "../package.json";
|
|
4
4
|
import {CLI_DESCRIPTION} from "../src/lib/config/text";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import {initializeGeneralCommands} from "../src/commands/general";
|
|
6
|
+
import {initializeKeygenCommands} from "../src/commands/keygen";
|
|
7
|
+
import {initializeContractsCommands} from "../src/commands/contracts";
|
|
8
|
+
import {initializeConfigCommands} from "../src/commands/config";
|
|
9
9
|
import {initializeValidatorCommands} from "../src/commands/validators";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import {initializeUpdateCommands} from "../src/commands/update";
|
|
11
|
+
import {initializeScaffoldCommands} from "../src/commands/scaffold";
|
|
12
|
+
import {initializeNetworkCommands} from "../src/commands/network";
|
|
12
13
|
|
|
13
14
|
export function initializeCLI() {
|
|
14
15
|
program.version(version).description(CLI_DESCRIPTION);
|
|
@@ -16,9 +17,10 @@ export function initializeCLI() {
|
|
|
16
17
|
initializeKeygenCommands(program);
|
|
17
18
|
initializeContractsCommands(program);
|
|
18
19
|
initializeConfigCommands(program);
|
|
19
|
-
initializeUpdateCommands(program)
|
|
20
|
+
initializeUpdateCommands(program);
|
|
20
21
|
initializeValidatorCommands(program);
|
|
21
22
|
initializeScaffoldCommands(program);
|
|
23
|
+
initializeNetworkCommands(program);
|
|
22
24
|
program.parse(process.argv);
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import ora, {
|
|
1
|
+
import {ConfigFileManager} from "../../lib/config/ConfigFileManager";
|
|
2
|
+
import ora, {Ora} from "ora";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import inquirer from "inquirer";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import type {
|
|
5
|
+
import {KeypairManager} from "../accounts/KeypairManager";
|
|
6
|
+
import {createClient, createAccount} from "genlayer-js";
|
|
7
|
+
import {localnet} from "genlayer-js/chains";
|
|
8
|
+
import type {GenLayerClient, GenLayerChain} from "genlayer-js/types";
|
|
9
9
|
|
|
10
10
|
export class BaseAction extends ConfigFileManager {
|
|
11
11
|
protected keypairManager: KeypairManager;
|
|
12
12
|
private spinner: Ora;
|
|
13
|
-
private _genlayerClient: GenLayerClient<
|
|
13
|
+
private _genlayerClient: GenLayerClient<GenLayerChain> | null = null;
|
|
14
14
|
|
|
15
15
|
constructor() {
|
|
16
|
-
super()
|
|
17
|
-
this.spinner = ora({
|
|
16
|
+
super();
|
|
17
|
+
this.spinner = ora({text: "", spinner: "dots"});
|
|
18
18
|
this.keypairManager = new KeypairManager();
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
protected async getClient(rpcUrl?: string): Promise<GenLayerClient<
|
|
21
|
+
protected async getClient(rpcUrl?: string): Promise<GenLayerClient<GenLayerChain>> {
|
|
22
22
|
if (!this._genlayerClient) {
|
|
23
|
+
const networkConfig = this.getConfig().network;
|
|
24
|
+
const network = networkConfig ? JSON.parse(networkConfig) : localnet;
|
|
23
25
|
this._genlayerClient = createClient({
|
|
24
|
-
chain:
|
|
26
|
+
chain: network,
|
|
25
27
|
endpoint: rpcUrl,
|
|
26
|
-
account: createAccount(await this.getPrivateKey() as any),
|
|
28
|
+
account: createAccount((await this.getPrivateKey()) as any),
|
|
27
29
|
});
|
|
28
30
|
}
|
|
29
31
|
return this._genlayerClient;
|
|
@@ -64,11 +66,11 @@ export class BaseAction extends ConfigFileManager {
|
|
|
64
66
|
};
|
|
65
67
|
return JSON.stringify(errorDetails, null, 2);
|
|
66
68
|
}
|
|
67
|
-
|
|
69
|
+
|
|
68
70
|
if (data instanceof Map) {
|
|
69
71
|
data = Object.fromEntries(data);
|
|
70
72
|
}
|
|
71
|
-
|
|
73
|
+
|
|
72
74
|
return typeof data === "object" ? JSON.stringify(data, null, 2) : String(data);
|
|
73
75
|
}
|
|
74
76
|
|
|
@@ -103,12 +105,12 @@ export class BaseAction extends ConfigFileManager {
|
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
protected succeedSpinner(message: string, data?: any): void {
|
|
106
|
-
if (data !== undefined) this.log(
|
|
108
|
+
if (data !== undefined) this.log("Result:", data);
|
|
107
109
|
this.spinner.succeed(chalk.green(message));
|
|
108
110
|
}
|
|
109
111
|
|
|
110
|
-
protected failSpinner(message: string, error?:any): void {
|
|
111
|
-
if (error) this.log(
|
|
112
|
+
protected failSpinner(message: string, error?: any): void {
|
|
113
|
+
if (error) this.log("Error:", error);
|
|
112
114
|
this.spinner.fail(chalk.red(message));
|
|
113
115
|
}
|
|
114
116
|
|
|
@@ -119,4 +121,4 @@ export class BaseAction extends ConfigFileManager {
|
|
|
119
121
|
protected setSpinnerText(message: string): void {
|
|
120
122
|
this.spinner.text = chalk.blue(message);
|
|
121
123
|
}
|
|
122
|
-
}
|
|
124
|
+
}
|