genlayer 0.18.0-beta.0 → 0.18.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 +2 -2
- package/dist/index.js +4672 -9721
- package/docker-compose.yml +6 -1
- package/package.json +2 -2
- package/src/commands/contracts/call.ts +49 -7
- package/src/commands/contracts/deploy.ts +13 -17
- package/src/commands/contracts/index.ts +11 -36
- package/src/commands/general/index.ts +2 -0
- package/src/commands/general/init.ts +23 -17
- package/src/commands/general/start.ts +13 -16
- package/src/commands/keygen/create.ts +2 -2
- package/src/commands/update/ollama.ts +1 -1
- package/src/lib/actions/BaseAction.ts +18 -18
- package/src/lib/config/simulator.ts +5 -5
- package/src/lib/interfaces/ISimulatorService.ts +2 -2
- package/src/lib/services/simulator.ts +25 -13
- package/tests/actions/call.test.ts +86 -22
- package/tests/actions/create.test.ts +8 -8
- package/tests/actions/deploy.test.ts +60 -71
- package/tests/actions/init.test.ts +128 -173
- package/tests/actions/ollama.test.ts +2 -2
- package/tests/actions/start.test.ts +38 -48
- package/tests/commands/init.test.ts +8 -1
- package/tests/commands/up.test.ts +5 -1
- package/tests/libs/baseAction.test.ts +26 -37
- package/tests/services/simulator.test.ts +155 -98
- package/src/commands/contracts/write.ts +0 -49
- package/tests/actions/write.test.ts +0 -102
- package/tests/commands/write.test.ts +0 -76
package/docker-compose.yml
CHANGED
|
@@ -22,6 +22,8 @@ services:
|
|
|
22
22
|
options:
|
|
23
23
|
max-size: "10m"
|
|
24
24
|
max-file: "3"
|
|
25
|
+
profiles:
|
|
26
|
+
- frontend
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
jsonrpc:
|
|
@@ -83,6 +85,7 @@ services:
|
|
|
83
85
|
depends_on:
|
|
84
86
|
ollama:
|
|
85
87
|
condition: service_started
|
|
88
|
+
required: false
|
|
86
89
|
restart: always
|
|
87
90
|
security_opt:
|
|
88
91
|
- "no-new-privileges=true"
|
|
@@ -96,7 +99,7 @@ services:
|
|
|
96
99
|
image: ollama/ollama:0.6.6
|
|
97
100
|
ports:
|
|
98
101
|
- 11434:11434
|
|
99
|
-
container_name: ollama
|
|
102
|
+
container_name: genlayer-ollama
|
|
100
103
|
tty: true
|
|
101
104
|
restart: always
|
|
102
105
|
security_opt:
|
|
@@ -106,6 +109,8 @@ services:
|
|
|
106
109
|
options:
|
|
107
110
|
max-size: "10m"
|
|
108
111
|
max-file: "3"
|
|
112
|
+
profiles:
|
|
113
|
+
- ollama
|
|
109
114
|
|
|
110
115
|
postgres:
|
|
111
116
|
image: postgres:17-alpine
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genlayer",
|
|
3
|
-
"version": "0.18.0
|
|
3
|
+
"version": "0.18.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.9.
|
|
67
|
+
"genlayer-js": "^0.9.0",
|
|
68
68
|
"inquirer": "^12.0.0",
|
|
69
69
|
"node-fetch": "^3.0.0",
|
|
70
70
|
"open": "^10.1.0",
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { simulator } from "genlayer-js/chains";
|
|
2
|
+
import type { GenLayerClient } from "genlayer-js/types";
|
|
3
|
+
import { BaseAction } from "../../lib/actions/BaseAction";
|
|
2
4
|
|
|
3
5
|
export interface CallOptions {
|
|
4
6
|
args: any[];
|
|
5
7
|
rpc?: string;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
export class CallAction extends BaseAction
|
|
10
|
+
export class CallAction extends BaseAction{
|
|
9
11
|
constructor() {
|
|
10
12
|
super();
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
async call({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
contractAddress,
|
|
17
|
+
method,
|
|
18
|
+
args,
|
|
19
|
+
rpc,
|
|
20
|
+
}: {
|
|
19
21
|
contractAddress: string;
|
|
20
22
|
method: string;
|
|
21
23
|
args: any[];
|
|
@@ -25,7 +27,26 @@ export class CallAction extends BaseAction {
|
|
|
25
27
|
await client.initializeConsensusSmartContract();
|
|
26
28
|
this.startSpinner(`Calling method ${method} on contract at ${contractAddress}...`);
|
|
27
29
|
|
|
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> {
|
|
28
48
|
try {
|
|
49
|
+
const client = await this.getClient();
|
|
29
50
|
const result = await client.readContract({
|
|
30
51
|
address: contractAddress as any,
|
|
31
52
|
functionName: method,
|
|
@@ -36,4 +57,25 @@ export class CallAction extends BaseAction {
|
|
|
36
57
|
this.failSpinner("Error during read operation", error);
|
|
37
58
|
}
|
|
38
59
|
}
|
|
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
|
+
}
|
|
39
81
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { simulator } from "genlayer-js/chains";
|
|
4
|
+
import type { GenLayerClient } from "genlayer-js/types";
|
|
5
|
+
import { BaseAction } from "../../lib/actions/BaseAction";
|
|
6
|
+
import { pathToFileURL } from "url";
|
|
7
|
+
import { TransactionStatus } from "genlayer-js/types";
|
|
8
|
+
import { buildSync } from "esbuild";
|
|
7
9
|
|
|
8
10
|
export interface DeployOptions {
|
|
9
11
|
contract?: string;
|
|
@@ -42,7 +44,7 @@ export class DeployAction extends BaseAction {
|
|
|
42
44
|
target: "es2020",
|
|
43
45
|
sourcemap: false,
|
|
44
46
|
});
|
|
45
|
-
|
|
47
|
+
await this.executeJsScript(filePath, outFile, rpcUrl);
|
|
46
48
|
} catch (error) {
|
|
47
49
|
this.failSpinner(`Error executing: ${filePath}`, error);
|
|
48
50
|
} finally {
|
|
@@ -50,17 +52,13 @@ export class DeployAction extends BaseAction {
|
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
private async executeJsScript(
|
|
54
|
-
filePath: string,
|
|
55
|
-
transpiledFilePath?: string,
|
|
56
|
-
rpcUrl?: string,
|
|
57
|
-
): Promise<void> {
|
|
55
|
+
private async executeJsScript(filePath: string, transpiledFilePath?: string, rpcUrl?: string): Promise<void> {
|
|
58
56
|
this.startSpinner(`Executing file: ${filePath}`);
|
|
59
57
|
try {
|
|
60
58
|
const module = await import(pathToFileURL(transpiledFilePath || filePath).href);
|
|
61
59
|
if (!module.default || typeof module.default !== "function") {
|
|
62
60
|
this.failSpinner(`No "default" function found in: ${filePath}`);
|
|
63
|
-
return
|
|
61
|
+
return
|
|
64
62
|
}
|
|
65
63
|
const client = await this.getClient(rpcUrl);
|
|
66
64
|
await module.default(client);
|
|
@@ -76,8 +74,7 @@ export class DeployAction extends BaseAction {
|
|
|
76
74
|
this.failSpinner("No deploy folder found.");
|
|
77
75
|
return;
|
|
78
76
|
}
|
|
79
|
-
const files = fs
|
|
80
|
-
.readdirSync(this.deployDir)
|
|
77
|
+
const files = fs.readdirSync(this.deployDir)
|
|
81
78
|
.filter(file => file.endsWith(".ts") || file.endsWith(".js"))
|
|
82
79
|
.sort((a, b) => {
|
|
83
80
|
const numA = parseInt(a.split("_")[0]);
|
|
@@ -130,17 +127,16 @@ export class DeployAction extends BaseAction {
|
|
|
130
127
|
}
|
|
131
128
|
|
|
132
129
|
const leaderOnly = false;
|
|
133
|
-
const deployParams: any = {code: contractCode, args: options.args, leaderOnly};
|
|
130
|
+
const deployParams: any = { code: contractCode, args: options.args, leaderOnly };
|
|
134
131
|
|
|
135
132
|
this.setSpinnerText("Starting contract deployment...");
|
|
136
133
|
this.log("Deployment Parameters:", deployParams);
|
|
137
134
|
|
|
138
135
|
const hash = (await client.deployContract(deployParams)) as any;
|
|
139
|
-
this.log("Deployment Transaction Hash:", hash);
|
|
140
136
|
const result = await client.waitForTransactionReceipt({
|
|
141
137
|
hash,
|
|
142
|
-
retries:
|
|
143
|
-
interval:
|
|
138
|
+
retries: 15,
|
|
139
|
+
interval: 2000,
|
|
144
140
|
status: TransactionStatus.ACCEPTED,
|
|
145
141
|
});
|
|
146
142
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {Command} from "commander";
|
|
2
|
-
import {DeployAction, DeployOptions, DeployScriptsOptions} from "./deploy";
|
|
3
|
-
import {CallAction, CallOptions} from "./call";
|
|
4
|
-
import {WriteAction, WriteOptions} from "./write";
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { DeployAction, DeployOptions, DeployScriptsOptions } from "./deploy";
|
|
3
|
+
import { CallAction, CallOptions } from "./call";
|
|
5
4
|
|
|
6
5
|
function parseArg(value: string, previous: any[] = []): any[] {
|
|
7
6
|
if (value === "true") return [...previous, true];
|
|
@@ -11,55 +10,31 @@ function parseArg(value: string, previous: any[] = []): any[] {
|
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
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(
|
|
20
|
-
"--args <args...>",
|
|
21
|
-
"Positional arguments for the contract (space-separated, use quotes for multi-word arguments)",
|
|
22
|
-
parseArg,
|
|
23
|
-
[],
|
|
24
|
-
)
|
|
19
|
+
.option("--args <args...>", "Positional arguments for the contract (space-separated, use quotes for multi-word arguments)", parseArg, [])
|
|
25
20
|
.action(async (options: DeployOptions) => {
|
|
26
21
|
const deployer = new DeployAction();
|
|
27
|
-
if
|
|
22
|
+
if(options.contract){
|
|
28
23
|
await deployer.deploy(options);
|
|
29
|
-
}
|
|
30
|
-
const deployScriptsOptions: DeployScriptsOptions = {rpc: options.rpc};
|
|
24
|
+
}else {
|
|
25
|
+
const deployScriptsOptions: DeployScriptsOptions = { rpc: options.rpc };
|
|
31
26
|
await deployer.deployScripts(deployScriptsOptions);
|
|
32
27
|
}
|
|
33
28
|
});
|
|
34
29
|
|
|
35
30
|
program
|
|
36
31
|
.command("call <contractAddress> <method>")
|
|
37
|
-
.description("Call a contract method
|
|
32
|
+
.description("Call a contract method")
|
|
38
33
|
.option("--rpc <rpcUrl>", "RPC URL for the network")
|
|
39
|
-
.option(
|
|
40
|
-
"--args <args...>",
|
|
41
|
-
"Positional arguments for the method (space-separated, use quotes for multi-word arguments)",
|
|
42
|
-
parseArg,
|
|
43
|
-
[],
|
|
44
|
-
)
|
|
34
|
+
.option("--args <args...>", "Positional arguments for the method (space-separated, use quotes for multi-word arguments)", parseArg, [])
|
|
45
35
|
.action(async (contractAddress: string, method: string, options: CallOptions) => {
|
|
46
36
|
const caller = new CallAction();
|
|
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});
|
|
37
|
+
await caller.call({ contractAddress, method, ...options });
|
|
63
38
|
});
|
|
64
39
|
|
|
65
40
|
return program;
|
|
@@ -14,6 +14,7 @@ export function initializeGeneralCommands(program: Command) {
|
|
|
14
14
|
.option("--headless", "Headless mode", false)
|
|
15
15
|
.option("--reset-db", "Reset Database", false)
|
|
16
16
|
.option("--localnet-version <localnetVersion>", "Select a specific localnet version", localnetCompatibleVersion)
|
|
17
|
+
.option("--ollama", "Enable Ollama container", false)
|
|
17
18
|
.action(async (options: InitActionOptions) => {
|
|
18
19
|
const initAction = new InitAction();
|
|
19
20
|
await initAction.execute(options)
|
|
@@ -26,6 +27,7 @@ export function initializeGeneralCommands(program: Command) {
|
|
|
26
27
|
.option("--numValidators <numValidators>", "Number of validators", "5")
|
|
27
28
|
.option("--headless", "Headless mode", false)
|
|
28
29
|
.option("--reset-db", "Reset Database", false)
|
|
30
|
+
.option("--ollama", "Enable Ollama container", false)
|
|
29
31
|
.action(async (options: StartActionOptions) => {
|
|
30
32
|
const startAction = new StartAction();
|
|
31
33
|
await startAction.execute(options);
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import inquirer from "inquirer";
|
|
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";
|
|
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;
|
|
11
11
|
headless: boolean;
|
|
12
12
|
resetDb: boolean;
|
|
13
13
|
localnetVersion: string;
|
|
14
|
+
ollama: boolean;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
function getRequirementsErrorMessage({docker}: Record<string, boolean>): string {
|
|
17
|
+
function getRequirementsErrorMessage({ docker }: Record<string, boolean>): string {
|
|
17
18
|
if (!docker) {
|
|
18
19
|
return "Docker is not installed. Please install Docker and try again.\n";
|
|
19
20
|
}
|
|
20
21
|
return "";
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
function getVersionErrorMessage({docker, node}: Record<string, string>): string {
|
|
24
|
+
function getVersionErrorMessage({ docker, node }: Record<string, string>): string {
|
|
24
25
|
let message = "";
|
|
25
26
|
|
|
26
27
|
if (docker) {
|
|
@@ -41,7 +42,7 @@ export class InitAction extends BaseAction {
|
|
|
41
42
|
|
|
42
43
|
public async execute(options: InitActionOptions): Promise<void> {
|
|
43
44
|
try {
|
|
44
|
-
this.simulatorService.setComposeOptions(options.headless);
|
|
45
|
+
this.simulatorService.setComposeOptions(options.headless, options.ollama);
|
|
45
46
|
let localnetVersion = options.localnetVersion;
|
|
46
47
|
if (localnetVersion !== "latest") {
|
|
47
48
|
localnetVersion = this.simulatorService.normalizeLocalnetVersion(localnetVersion);
|
|
@@ -72,7 +73,7 @@ export class InitAction extends BaseAction {
|
|
|
72
73
|
const confirmMessage = isRunning
|
|
73
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?`
|
|
74
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?`;
|
|
75
|
-
|
|
76
|
+
|
|
76
77
|
await this.confirmPrompt(confirmMessage);
|
|
77
78
|
|
|
78
79
|
this.logInfo(`Initializing GenLayer CLI with ${options.numValidators} validators`);
|
|
@@ -88,8 +89,9 @@ export class InitAction extends BaseAction {
|
|
|
88
89
|
type: "checkbox",
|
|
89
90
|
name: "selectedLlmProviders",
|
|
90
91
|
message: "Select which LLM providers do you want to use:",
|
|
91
|
-
choices: this.simulatorService.getAiProvidersOptions(true),
|
|
92
|
-
validate: answer =>
|
|
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
95
|
},
|
|
94
96
|
];
|
|
95
97
|
const llmProvidersAnswer = await inquirer.prompt(llmQuestions);
|
|
@@ -98,7 +100,7 @@ export class InitAction extends BaseAction {
|
|
|
98
100
|
let defaultOllamaModel = this.getConfig().defaultOllamaModel;
|
|
99
101
|
const aiProvidersEnvVars: Record<string, string> = {};
|
|
100
102
|
const configurableAiProviders = selectedLlmProviders.filter(
|
|
101
|
-
(provider: AiProviders) => AI_PROVIDERS_CONFIG[provider].envVar
|
|
103
|
+
(provider: AiProviders) => AI_PROVIDERS_CONFIG[provider].envVar
|
|
102
104
|
);
|
|
103
105
|
for (const provider of configurableAiProviders) {
|
|
104
106
|
const providerConfig = AI_PROVIDERS_CONFIG[provider];
|
|
@@ -117,13 +119,14 @@ export class InitAction extends BaseAction {
|
|
|
117
119
|
|
|
118
120
|
this.startSpinner("Configuring GenLayer Localnet environment...");
|
|
119
121
|
this.simulatorService.addConfigToEnvFile(aiProvidersEnvVars);
|
|
120
|
-
this.simulatorService.addConfigToEnvFile({LOCALNETVERSION: localnetVersion});
|
|
122
|
+
this.simulatorService.addConfigToEnvFile({ LOCALNETVERSION: localnetVersion });
|
|
121
123
|
|
|
122
124
|
this.setSpinnerText("Running GenLayer Localnet...");
|
|
123
125
|
await this.simulatorService.runSimulator();
|
|
124
126
|
|
|
125
127
|
this.setSpinnerText("Waiting for localnet to be ready...");
|
|
126
|
-
const {initialized, errorCode, errorMessage} =
|
|
128
|
+
const { initialized, errorCode, errorMessage } =
|
|
129
|
+
await this.simulatorService.waitForSimulatorToBeReady();
|
|
127
130
|
if (!initialized) {
|
|
128
131
|
if (errorCode === "ERROR") {
|
|
129
132
|
this.failSpinner(`Unable to initialize the GenLayer Localnet: ${errorMessage}`);
|
|
@@ -131,7 +134,7 @@ export class InitAction extends BaseAction {
|
|
|
131
134
|
}
|
|
132
135
|
if (errorCode === "TIMEOUT") {
|
|
133
136
|
this.failSpinner(
|
|
134
|
-
"The localnet is taking too long to initialize. Please try again after the localnet is ready."
|
|
137
|
+
"The localnet is taking too long to initialize. Please try again after the localnet is ready."
|
|
135
138
|
);
|
|
136
139
|
return;
|
|
137
140
|
}
|
|
@@ -150,7 +153,10 @@ export class InitAction extends BaseAction {
|
|
|
150
153
|
|
|
151
154
|
this.startSpinner("Initializing validators...");
|
|
152
155
|
await this.simulatorService.deleteAllValidators();
|
|
153
|
-
await this.simulatorService.createRandomValidators(
|
|
156
|
+
await this.simulatorService.createRandomValidators(
|
|
157
|
+
Number(options.numValidators),
|
|
158
|
+
selectedLlmProviders
|
|
159
|
+
);
|
|
154
160
|
|
|
155
161
|
if (options.resetDb) {
|
|
156
162
|
this.setSpinnerText("Cleaning database...");
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import inquirer from "inquirer";
|
|
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";
|
|
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;
|
|
9
9
|
numValidators: number;
|
|
10
10
|
headless: boolean;
|
|
11
11
|
resetDb: boolean;
|
|
12
|
+
ollama: boolean;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export class StartAction extends BaseAction {
|
|
@@ -20,9 +21,9 @@ export class StartAction extends BaseAction {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
async execute(options: StartActionOptions) {
|
|
23
|
-
const {resetValidators, numValidators, headless, resetDb} = options;
|
|
24
|
+
const { resetValidators, numValidators, headless, resetDb, ollama } = options;
|
|
24
25
|
|
|
25
|
-
this.simulatorService.setComposeOptions(headless);
|
|
26
|
+
this.simulatorService.setComposeOptions(headless, ollama);
|
|
26
27
|
this.startSpinner("Checking CLI version...");
|
|
27
28
|
await this.simulatorService.checkCliVersion();
|
|
28
29
|
|
|
@@ -48,7 +49,7 @@ export class StartAction extends BaseAction {
|
|
|
48
49
|
|
|
49
50
|
try {
|
|
50
51
|
this.setSpinnerText("Waiting for the simulator to be ready...");
|
|
51
|
-
const {initialized, errorCode, errorMessage} = await this.simulatorService.waitForSimulatorToBeReady();
|
|
52
|
+
const { initialized, errorCode, errorMessage } = await this.simulatorService.waitForSimulatorToBeReady();
|
|
52
53
|
|
|
53
54
|
if (!initialized) {
|
|
54
55
|
if (errorCode === "ERROR") {
|
|
@@ -60,6 +61,7 @@ export class StartAction extends BaseAction {
|
|
|
60
61
|
return;
|
|
61
62
|
}
|
|
62
63
|
}
|
|
64
|
+
|
|
63
65
|
} catch (error) {
|
|
64
66
|
this.failSpinner("Error waiting for the simulator to be ready", error);
|
|
65
67
|
return;
|
|
@@ -80,16 +82,13 @@ export class StartAction extends BaseAction {
|
|
|
80
82
|
type: "checkbox",
|
|
81
83
|
name: "selectedLlmProviders",
|
|
82
84
|
message: "Select which LLM providers do you want to use:",
|
|
83
|
-
choices: this.simulatorService.getAiProvidersOptions(false),
|
|
84
|
-
validate: answer => (answer.length < 1 ? "You must choose at least one option." : true),
|
|
85
|
+
choices: this.simulatorService.getAiProvidersOptions(false, ollama ? [] : ["ollama"]),
|
|
86
|
+
validate: (answer) => (answer.length < 1 ? "You must choose at least one option." : true),
|
|
85
87
|
},
|
|
86
88
|
];
|
|
87
89
|
|
|
88
90
|
const llmProvidersAnswer = await inquirer.prompt(questions);
|
|
89
|
-
await this.simulatorService.createRandomValidators(
|
|
90
|
-
numValidators,
|
|
91
|
-
llmProvidersAnswer.selectedLlmProviders,
|
|
92
|
-
);
|
|
91
|
+
await this.simulatorService.createRandomValidators(numValidators, llmProvidersAnswer.selectedLlmProviders);
|
|
93
92
|
} catch (error) {
|
|
94
93
|
this.failSpinner("Unable to initialize the validators", error);
|
|
95
94
|
return;
|
|
@@ -97,9 +96,7 @@ export class StartAction extends BaseAction {
|
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
let successMessage = "GenLayer simulator initialized successfully! ";
|
|
100
|
-
successMessage += headless
|
|
101
|
-
? ""
|
|
102
|
-
: `Go to ${this.simulatorService.getFrontendUrl()} in your browser to access it.`;
|
|
99
|
+
successMessage += headless ? "" : `Go to ${this.simulatorService.getFrontendUrl()} in your browser to access it.`;
|
|
103
100
|
this.succeedSpinner(successMessage);
|
|
104
101
|
|
|
105
102
|
if (!headless) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
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
|
+
}
|
|
@@ -67,7 +67,7 @@ export class OllamaAction extends BaseAction {
|
|
|
67
67
|
this.startSpinner(`Executing '${command}' command on model "${modelName}"...`);
|
|
68
68
|
|
|
69
69
|
let success = false;
|
|
70
|
-
const ollamaContainer = this.docker.getContainer("ollama");
|
|
70
|
+
const ollamaContainer = this.docker.getContainer("genlayer-ollama");
|
|
71
71
|
const exec = await ollamaContainer.exec({
|
|
72
72
|
Cmd: ["ollama", command, modelName],
|
|
73
73
|
AttachStdout: true,
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import {ConfigFileManager} from "../../lib/config/ConfigFileManager";
|
|
2
|
-
import ora, {Ora} from "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 {KeypairManager} from "../accounts/KeypairManager";
|
|
6
|
-
import {createClient, createAccount} from "genlayer-js";
|
|
7
|
-
import {
|
|
8
|
-
import type {GenLayerClient} from "genlayer-js/types";
|
|
5
|
+
import { KeypairManager } from "../accounts/KeypairManager";
|
|
6
|
+
import { createClient, createAccount } from "genlayer-js";
|
|
7
|
+
import { localnet } from "genlayer-js/chains";
|
|
8
|
+
import type { GenLayerClient } 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<typeof
|
|
13
|
+
private _genlayerClient: GenLayerClient<typeof localnet> | null = null;
|
|
14
14
|
|
|
15
15
|
constructor() {
|
|
16
|
-
super()
|
|
17
|
-
this.spinner = ora({text: "", spinner: "dots"});
|
|
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<typeof
|
|
21
|
+
protected async getClient(rpcUrl?: string): Promise<GenLayerClient<typeof localnet>> {
|
|
22
22
|
if (!this._genlayerClient) {
|
|
23
23
|
this._genlayerClient = createClient({
|
|
24
|
-
chain:
|
|
24
|
+
chain: localnet,
|
|
25
25
|
endpoint: rpcUrl,
|
|
26
|
-
account: createAccount(
|
|
26
|
+
account: createAccount(await this.getPrivateKey() as any),
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
return this._genlayerClient;
|
|
@@ -64,11 +64,11 @@ export class BaseAction extends ConfigFileManager {
|
|
|
64
64
|
};
|
|
65
65
|
return JSON.stringify(errorDetails, null, 2);
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
if (data instanceof Map) {
|
|
69
69
|
data = Object.fromEntries(data);
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
return typeof data === "object" ? JSON.stringify(data, null, 2) : String(data);
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -103,12 +103,12 @@ export class BaseAction extends ConfigFileManager {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
protected succeedSpinner(message: string, data?: any): void {
|
|
106
|
-
if (data !== undefined) this.log(
|
|
106
|
+
if (data !== undefined) this.log('Result:', data);
|
|
107
107
|
this.spinner.succeed(chalk.green(message));
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
protected failSpinner(message: string, error?:
|
|
111
|
-
if (error) this.log(
|
|
110
|
+
protected failSpinner(message: string, error?:any): void {
|
|
111
|
+
if (error) this.log('Error:', error);
|
|
112
112
|
this.spinner.fail(chalk.red(message));
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -119,4 +119,4 @@ export class BaseAction extends ConfigFileManager {
|
|
|
119
119
|
protected setSpinnerText(message: string): void {
|
|
120
120
|
this.spinner.text = chalk.blue(message);
|
|
121
121
|
}
|
|
122
|
-
}
|
|
122
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export const localnetCompatibleVersion = "v0.
|
|
1
|
+
export const localnetCompatibleVersion = "v0.55.0";
|
|
2
2
|
export const DEFAULT_JSON_RPC_URL = "http://localhost:4000/api";
|
|
3
3
|
export const CONTAINERS_NAME_PREFIX = "/genlayer-";
|
|
4
4
|
export const IMAGES_NAME_PREFIX = "yeagerai";
|
|
5
|
-
export const DEFAULT_RUN_SIMULATOR_COMMAND = (location: string,
|
|
6
|
-
darwin: `osascript -e 'tell application "Terminal" to do script "cd ${location} && docker compose build && docker compose -p genlayer
|
|
7
|
-
win32: `start cmd.exe /c "cd /d ${location} && docker compose build && docker compose -p genlayer
|
|
8
|
-
linux: `nohup bash -c 'cd ${location} && docker compose build && docker compose -p genlayer
|
|
5
|
+
export const DEFAULT_RUN_SIMULATOR_COMMAND = (location: string, profiles: string) => ({
|
|
6
|
+
darwin: `osascript -e 'tell application "Terminal" to do script "cd ${location} && docker compose build && docker compose -p genlayer ${profiles} up"'`,
|
|
7
|
+
win32: `start cmd.exe /c "cd /d ${location} && docker compose build && docker compose -p genlayer ${profiles} up && pause"`,
|
|
8
|
+
linux: `nohup bash -c 'cd ${location} && docker compose build && docker compose -p genlayer ${profiles} up -d '`,
|
|
9
9
|
});
|
|
10
10
|
export const DEFAULT_RUN_DOCKER_COMMAND = {
|
|
11
11
|
darwin: "open -a Docker",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {AiProviders} from "../config/simulator";
|
|
2
2
|
|
|
3
3
|
export interface ISimulatorService {
|
|
4
|
-
setComposeOptions(headless: boolean): void;
|
|
4
|
+
setComposeOptions(headless: boolean, disableOllama?: boolean): void;
|
|
5
5
|
getComposeOptions(): string;
|
|
6
6
|
checkInstallRequirements(): Promise<Record<string, boolean>>;
|
|
7
7
|
checkVersionRequirements(): Promise<Record<string, string>>;
|
|
@@ -9,7 +9,7 @@ export interface ISimulatorService {
|
|
|
9
9
|
waitForSimulatorToBeReady(retries?: number): Promise<WaitForSimulatorToBeReadyResultType>;
|
|
10
10
|
createRandomValidators(numValidators: number, llmProviders: AiProviders[]): Promise<any>;
|
|
11
11
|
deleteAllValidators(): Promise<any>;
|
|
12
|
-
getAiProvidersOptions(withHint: boolean): Array<{name: string; value: string}>;
|
|
12
|
+
getAiProvidersOptions(withHint: boolean, excludeProviders?: AiProviders[]): Array<{name: string; value: string}>;
|
|
13
13
|
getFrontendUrl(): string;
|
|
14
14
|
openFrontend(): Promise<boolean>;
|
|
15
15
|
stopDockerContainers(): Promise<void>;
|