genlayer 0.12.1 → 0.12.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/.github/workflows/publish-beta.yml +2 -2
- package/.github/workflows/publish.yml +2 -2
- package/.github/workflows/validate-code.yml +1 -1
- package/CHANGELOG.md +6 -0
- package/dist/index.js +24736 -108331
- package/docker-compose.yml +1 -1
- package/esbuild.config.dev.js +18 -0
- package/esbuild.config.js +10 -5
- package/esbuild.config.prod.js +16 -0
- package/eslint.config.js +59 -0
- package/package.json +12 -9
- package/scripts/postinstall.js +10 -6
- package/src/commands/config/getSetReset.ts +25 -18
- package/src/commands/contracts/deploy.ts +105 -25
- package/src/commands/contracts/index.ts +5 -1
- package/src/commands/general/index.ts +10 -4
- package/src/commands/general/init.ts +136 -189
- package/src/commands/general/start.ts +76 -77
- package/src/commands/general/stop.ts +6 -5
- package/src/commands/keygen/create.ts +9 -11
- package/src/commands/update/index.ts +3 -8
- package/src/commands/update/ollama.ts +56 -56
- package/src/commands/validators/validators.ts +48 -55
- package/src/lib/actions/BaseAction.ts +75 -4
- package/src/lib/config/simulator.ts +1 -1
- package/src/lib/services/simulator.ts +3 -2
- package/tests/actions/create.test.ts +18 -30
- package/tests/actions/deploy.test.ts +200 -30
- package/tests/actions/getSetReset.test.ts +29 -42
- package/tests/actions/init.test.ts +240 -475
- package/tests/actions/ollama.test.ts +40 -55
- package/tests/actions/start.test.ts +107 -108
- package/tests/actions/stop.test.ts +23 -4
- package/tests/actions/validators.test.ts +273 -142
- package/tests/commands/call.test.ts +4 -1
- package/tests/commands/deploy.test.ts +11 -0
- package/tests/commands/init.test.ts +11 -12
- package/tests/commands/up.test.ts +31 -23
- package/tests/commands/update.test.ts +2 -5
- package/tests/libs/baseAction.test.ts +175 -0
- package/tests/services/simulator.test.ts +15 -0
- package/.eslintrc.js +0 -58
- package/esbuild.config.dev +0 -16
- package/esbuild.config.prod +0 -16
|
@@ -1,72 +1,71 @@
|
|
|
1
1
|
import Docker from "dockerode";
|
|
2
2
|
import { rpcClient } from "../../lib/clients/jsonRpcClient";
|
|
3
|
+
import { BaseAction } from "../../lib/actions/BaseAction";
|
|
3
4
|
|
|
4
|
-
export class OllamaAction {
|
|
5
|
+
export class OllamaAction extends BaseAction {
|
|
5
6
|
private docker: Docker;
|
|
6
7
|
|
|
7
8
|
constructor() {
|
|
9
|
+
super();
|
|
8
10
|
this.docker = new Docker();
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
async updateModel(modelName: string) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
params: [],
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const existingOllamaProvider = providersAndModels.result.find(
|
|
18
|
-
(entry: any) => entry.plugin === "ollama"
|
|
19
|
-
);
|
|
14
|
+
try {
|
|
15
|
+
this.startSpinner(`Updating model "${modelName}"...`);
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
if(!modelName){
|
|
18
|
+
modelName = this.getConfig().defaultOllamaModel;
|
|
19
|
+
}
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
`Model "${modelName}" updated successfully`
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
const existingModel = providersAndModels.result.some(
|
|
32
|
-
(entry: any) =>
|
|
33
|
-
entry.plugin === "ollama" && entry.model === modelName
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
if (!existingModel) {
|
|
37
|
-
console.log(`Model "${modelName}" not found in Provider Presets. Adding...`);
|
|
38
|
-
|
|
39
|
-
const newModelConfig = {
|
|
40
|
-
config: existingOllamaProvider.config,
|
|
41
|
-
model: modelName,
|
|
42
|
-
plugin: "ollama",
|
|
43
|
-
plugin_config: existingOllamaProvider.plugin_config,
|
|
44
|
-
provider: "ollama",
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
await rpcClient.request({
|
|
48
|
-
method: "sim_addProvider",
|
|
49
|
-
params: [newModelConfig],
|
|
21
|
+
const providersAndModels = await rpcClient.request({
|
|
22
|
+
method: "sim_getProvidersAndModels",
|
|
23
|
+
params: [],
|
|
50
24
|
});
|
|
51
25
|
|
|
52
|
-
|
|
26
|
+
const existingOllamaProvider = providersAndModels.result.find(
|
|
27
|
+
(entry: any) => entry.plugin === "ollama"
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
if (!existingOllamaProvider) {
|
|
31
|
+
return this.failSpinner("No existing 'ollama' provider found. Unable to add/update a model.");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await this.executeModelCommand("pull", modelName, `Model "${modelName}" updated successfully`);
|
|
35
|
+
|
|
36
|
+
const existingModel = providersAndModels.result.some(
|
|
37
|
+
(entry: any) => entry.plugin === "ollama" && entry.model === modelName
|
|
38
|
+
);
|
|
39
|
+
if (!existingModel) {
|
|
40
|
+
this.startSpinner(`Adding model "${modelName}" to Provider Presets...`);
|
|
41
|
+
|
|
42
|
+
const newModelConfig = {
|
|
43
|
+
config: existingOllamaProvider.config,
|
|
44
|
+
model: modelName,
|
|
45
|
+
plugin: "ollama",
|
|
46
|
+
plugin_config: existingOllamaProvider.plugin_config,
|
|
47
|
+
provider: "ollama",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
await rpcClient.request({
|
|
51
|
+
method: "sim_addProvider",
|
|
52
|
+
params: [newModelConfig],
|
|
53
|
+
});
|
|
54
|
+
this.succeedSpinner(`Model "${modelName}" added to Provider Presets successfully.`);
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
this.failSpinner(`Error updating model "${modelName}"`, error);
|
|
53
58
|
}
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
async removeModel(modelName: string) {
|
|
57
|
-
await this.executeModelCommand(
|
|
58
|
-
"rm",
|
|
59
|
-
modelName,
|
|
60
|
-
`Model "${modelName}" removed successfully`
|
|
61
|
-
);
|
|
62
|
+
await this.executeModelCommand("rm", modelName, `Model "${modelName}" removed successfully`);
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
private async executeModelCommand(
|
|
65
|
-
command: string,
|
|
66
|
-
modelName: string,
|
|
67
|
-
successMessage: string
|
|
68
|
-
) {
|
|
65
|
+
private async executeModelCommand(command: string, modelName: string, successMessage: string) {
|
|
69
66
|
try {
|
|
67
|
+
this.startSpinner(`Executing '${command}' command on model "${modelName}"...`);
|
|
68
|
+
|
|
70
69
|
let success = false;
|
|
71
70
|
const ollamaContainer = this.docker.getContainer("ollama");
|
|
72
71
|
const exec = await ollamaContainer.exec({
|
|
@@ -74,12 +73,13 @@ export class OllamaAction {
|
|
|
74
73
|
AttachStdout: true,
|
|
75
74
|
AttachStderr: true,
|
|
76
75
|
});
|
|
77
|
-
const stream = await exec.start({Detach: false, Tty: false});
|
|
76
|
+
const stream = await exec.start({ Detach: false, Tty: false });
|
|
78
77
|
|
|
79
78
|
stream.on("data", (chunk: any) => {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
const output = chunk.toString();
|
|
80
|
+
this.setSpinnerText(output.trim());
|
|
81
|
+
|
|
82
|
+
if (output.includes("success") || output.includes("deleted")) {
|
|
83
83
|
success = true;
|
|
84
84
|
}
|
|
85
85
|
});
|
|
@@ -87,17 +87,17 @@ export class OllamaAction {
|
|
|
87
87
|
await new Promise<void>((resolve, reject) => {
|
|
88
88
|
stream.on("end", () => {
|
|
89
89
|
if (success) {
|
|
90
|
+
this.succeedSpinner(successMessage);
|
|
90
91
|
resolve();
|
|
91
92
|
} else {
|
|
93
|
+
this.failSpinner(`Failed to execute '${command}' on model "${modelName}".`);
|
|
92
94
|
reject('internal error');
|
|
93
95
|
}
|
|
94
96
|
});
|
|
95
97
|
stream.on("error", reject);
|
|
96
98
|
});
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}catch (error) {
|
|
100
|
-
console.error(`Error executing command "${command}" on model "${modelName}":`, error);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
this.failSpinner(`Error executing command "${command}" on model "${modelName}"`, error);
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
}
|
|
@@ -31,26 +31,25 @@ export class ValidatorsAction extends BaseAction {
|
|
|
31
31
|
public async getValidator(options: ValidatorOptions): Promise<void> {
|
|
32
32
|
try {
|
|
33
33
|
if (options.address) {
|
|
34
|
-
|
|
34
|
+
this.startSpinner(`Fetching validator with address: ${options.address}`);
|
|
35
35
|
|
|
36
36
|
const result = await rpcClient.request({
|
|
37
37
|
method: "sim_getValidator",
|
|
38
38
|
params: [options.address],
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
this.succeedSpinner(`Successfully fetched validator with address: ${options.address}`, result.result);
|
|
42
42
|
} else {
|
|
43
|
-
|
|
43
|
+
this.startSpinner(`Fetching all validators...`);
|
|
44
44
|
|
|
45
45
|
const result = await rpcClient.request({
|
|
46
46
|
method: "sim_getAllValidators",
|
|
47
47
|
params: [],
|
|
48
48
|
});
|
|
49
|
-
|
|
50
|
-
console.log("All Validators:", result.result);
|
|
49
|
+
this.succeedSpinner('Successfully fetched all validators.', result.result)
|
|
51
50
|
}
|
|
52
51
|
} catch (error) {
|
|
53
|
-
|
|
52
|
+
this.failSpinner("Error fetching validators", error);
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
|
|
@@ -58,65 +57,60 @@ export class ValidatorsAction extends BaseAction {
|
|
|
58
57
|
try {
|
|
59
58
|
if (options.address) {
|
|
60
59
|
await this.confirmPrompt(`This command will delete the validator with the address: ${options.address}. Do you want to continue?`);
|
|
61
|
-
|
|
60
|
+
this.startSpinner(`Deleting validator with address: ${options.address}`);
|
|
62
61
|
|
|
63
62
|
const result = await rpcClient.request({
|
|
64
63
|
method: "sim_deleteValidator",
|
|
65
64
|
params: [options.address],
|
|
66
65
|
});
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
this.succeedSpinner(`Deleted Address: ${result.result}`);
|
|
69
68
|
} else {
|
|
70
69
|
await this.confirmPrompt(`This command will delete all validators. Do you want to continue?`);
|
|
71
|
-
|
|
70
|
+
this.startSpinner("Deleting all validators...");
|
|
72
71
|
|
|
73
72
|
await rpcClient.request({
|
|
74
73
|
method: "sim_deleteAllValidators",
|
|
75
74
|
params: [],
|
|
76
75
|
});
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
this.succeedSpinner("Successfully deleted all validators");
|
|
79
78
|
}
|
|
80
79
|
} catch (error) {
|
|
81
|
-
|
|
80
|
+
this.failSpinner("Error deleting validators", error);
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
public async countValidators(): Promise<void> {
|
|
86
85
|
try {
|
|
87
|
-
|
|
86
|
+
this.startSpinner("Counting all validators...");
|
|
88
87
|
|
|
89
88
|
const result = await rpcClient.request({
|
|
90
89
|
method: "sim_countValidators",
|
|
91
90
|
params: [],
|
|
92
91
|
});
|
|
93
|
-
|
|
94
|
-
console.log("Total Validators:", result.result);
|
|
92
|
+
this.succeedSpinner(`Total Validators: ${result.result}`);
|
|
95
93
|
} catch (error) {
|
|
96
|
-
|
|
94
|
+
this.failSpinner("Error counting validators", error);
|
|
97
95
|
}
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
public async updateValidator(options: UpdateValidatorOptions): Promise<void> {
|
|
101
99
|
try {
|
|
102
|
-
|
|
100
|
+
this.startSpinner(`Fetching validator with address: ${options.address}...`);
|
|
103
101
|
const currentValidator = await rpcClient.request({
|
|
104
102
|
method: "sim_getValidator",
|
|
105
103
|
params: [options.address],
|
|
106
104
|
});
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
throw new Error(`Validator with address ${options.address} not found.`);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
console.log("Current Validator Details:", currentValidator.result);
|
|
106
|
+
this.log("Current Validator Details:", currentValidator.result);
|
|
113
107
|
|
|
114
108
|
const parsedStake = options.stake
|
|
115
109
|
? parseInt(options.stake, 10)
|
|
116
110
|
: currentValidator.result.stake;
|
|
117
111
|
|
|
118
112
|
if (isNaN(parsedStake) || parsedStake < 0) {
|
|
119
|
-
return
|
|
113
|
+
return this.failSpinner("Invalid stake value. Stake must be a positive integer.");
|
|
120
114
|
}
|
|
121
115
|
|
|
122
116
|
const updatedValidator = {
|
|
@@ -127,7 +121,9 @@ export class ValidatorsAction extends BaseAction {
|
|
|
127
121
|
config: options.config ? JSON.parse(options.config) : currentValidator.result.config,
|
|
128
122
|
};
|
|
129
123
|
|
|
130
|
-
|
|
124
|
+
this.log("Updated Validator Details:", updatedValidator);
|
|
125
|
+
|
|
126
|
+
this.setSpinnerText('Updating Validator...');
|
|
131
127
|
|
|
132
128
|
const result = await rpcClient.request({
|
|
133
129
|
method: "sim_updateValidator",
|
|
@@ -140,9 +136,9 @@ export class ValidatorsAction extends BaseAction {
|
|
|
140
136
|
],
|
|
141
137
|
});
|
|
142
138
|
|
|
143
|
-
|
|
139
|
+
this.succeedSpinner("Validator successfully updated", result.result);
|
|
144
140
|
} catch (error) {
|
|
145
|
-
|
|
141
|
+
this.failSpinner("Error updating validator", error);
|
|
146
142
|
}
|
|
147
143
|
}
|
|
148
144
|
|
|
@@ -150,21 +146,21 @@ export class ValidatorsAction extends BaseAction {
|
|
|
150
146
|
try {
|
|
151
147
|
const count = parseInt(options.count, 10);
|
|
152
148
|
if (isNaN(count) || count < 1) {
|
|
153
|
-
return
|
|
149
|
+
return this.logError("Invalid count. Please provide a positive integer.");
|
|
154
150
|
}
|
|
155
151
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
152
|
+
this.startSpinner(`Creating ${count} random validator(s)...`);
|
|
153
|
+
this.log(`Providers: ${options.providers.length > 0 ? options.providers.join(", ") : "All"}`);
|
|
154
|
+
this.log(`Models: ${options.models.length > 0 ? options.models.join(", ") : "All"}`);
|
|
159
155
|
|
|
160
156
|
const result = await rpcClient.request({
|
|
161
157
|
method: "sim_createRandomValidators",
|
|
162
158
|
params: [count, 1, 10, options.providers, options.models],
|
|
163
159
|
});
|
|
164
160
|
|
|
165
|
-
|
|
161
|
+
this.succeedSpinner("Random validators successfully created", result.result);
|
|
166
162
|
} catch (error) {
|
|
167
|
-
|
|
163
|
+
this.failSpinner("Error creating random validators", error);
|
|
168
164
|
}
|
|
169
165
|
}
|
|
170
166
|
|
|
@@ -172,22 +168,23 @@ export class ValidatorsAction extends BaseAction {
|
|
|
172
168
|
try {
|
|
173
169
|
const stake = parseInt(options.stake, 10);
|
|
174
170
|
if (isNaN(stake) || stake < 1) {
|
|
175
|
-
return
|
|
171
|
+
return this.logError("Invalid stake. Please provide a positive integer.");
|
|
176
172
|
}
|
|
177
173
|
|
|
178
174
|
if (options.model && !options.provider) {
|
|
179
|
-
return
|
|
175
|
+
return this.logError("You must specify a provider if using a model.");
|
|
180
176
|
}
|
|
181
177
|
|
|
182
|
-
|
|
178
|
+
this.startSpinner("Fetching available providers and models...");
|
|
183
179
|
|
|
184
180
|
const providersAndModels = await rpcClient.request({
|
|
185
181
|
method: "sim_getProvidersAndModels",
|
|
186
182
|
params: [],
|
|
187
183
|
});
|
|
184
|
+
this.stopSpinner();
|
|
188
185
|
|
|
189
186
|
if (!providersAndModels.result || providersAndModels.result.length === 0) {
|
|
190
|
-
return
|
|
187
|
+
return this.logError("No providers or models available.");
|
|
191
188
|
}
|
|
192
189
|
|
|
193
190
|
const availableProviders = [
|
|
@@ -218,7 +215,7 @@ export class ValidatorsAction extends BaseAction {
|
|
|
218
215
|
);
|
|
219
216
|
|
|
220
217
|
if (availableModels.length === 0) {
|
|
221
|
-
return
|
|
218
|
+
return this.logError("No models available for the selected provider.");
|
|
222
219
|
}
|
|
223
220
|
|
|
224
221
|
let model = options.model;
|
|
@@ -241,34 +238,30 @@ export class ValidatorsAction extends BaseAction {
|
|
|
241
238
|
);
|
|
242
239
|
|
|
243
240
|
if (!modelDetails) {
|
|
244
|
-
return
|
|
241
|
+
return this.logError("Selected model details not found.");
|
|
245
242
|
}
|
|
246
243
|
|
|
247
244
|
const config = options.config ? JSON.parse(options.config) : modelDetails.config;
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
245
|
+
const params = [
|
|
246
|
+
stake,
|
|
247
|
+
modelDetails.provider,
|
|
248
|
+
modelDetails.model,
|
|
249
|
+
config,
|
|
250
|
+
modelDetails.plugin,
|
|
251
|
+
modelDetails.plugin_config,
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
this.log("Validator details:", params);
|
|
255
|
+
this.startSpinner('Creating validator...');
|
|
256
256
|
|
|
257
257
|
const result = await rpcClient.request({
|
|
258
258
|
method: "sim_createValidator",
|
|
259
|
-
params
|
|
260
|
-
stake,
|
|
261
|
-
modelDetails.provider,
|
|
262
|
-
modelDetails.model,
|
|
263
|
-
config,
|
|
264
|
-
modelDetails.plugin,
|
|
265
|
-
modelDetails.plugin_config,
|
|
266
|
-
],
|
|
259
|
+
params,
|
|
267
260
|
});
|
|
268
261
|
|
|
269
|
-
|
|
262
|
+
this.succeedSpinner("Validator successfully created:", result.result);
|
|
270
263
|
} catch (error) {
|
|
271
|
-
|
|
264
|
+
this.failSpinner("Error creating validator", error);
|
|
272
265
|
}
|
|
273
266
|
}
|
|
274
267
|
}
|
|
@@ -1,19 +1,90 @@
|
|
|
1
|
+
import { ConfigFileManager } from "../../lib/config/ConfigFileManager";
|
|
2
|
+
import ora, { Ora } from "ora";
|
|
3
|
+
import chalk from "chalk";
|
|
1
4
|
import inquirer from "inquirer";
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
|
|
7
|
+
export class BaseAction extends ConfigFileManager {
|
|
8
|
+
private spinner: Ora;
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
super()
|
|
12
|
+
this.spinner = ora({ text: "", spinner: "dots" });
|
|
13
|
+
}
|
|
14
|
+
|
|
4
15
|
protected async confirmPrompt(message: string): Promise<void> {
|
|
5
16
|
const answer = await inquirer.prompt([
|
|
6
17
|
{
|
|
7
18
|
type: "confirm",
|
|
8
19
|
name: "confirmAction",
|
|
9
|
-
message: message,
|
|
20
|
+
message: chalk.yellow(message),
|
|
10
21
|
default: true,
|
|
11
22
|
},
|
|
12
23
|
]);
|
|
13
24
|
|
|
14
25
|
if (!answer.confirmAction) {
|
|
15
|
-
|
|
26
|
+
this.logError("Operation aborted!");
|
|
16
27
|
process.exit(0);
|
|
17
28
|
}
|
|
18
29
|
}
|
|
19
|
-
|
|
30
|
+
|
|
31
|
+
private formatOutput(data: any): string {
|
|
32
|
+
if (data instanceof Error) {
|
|
33
|
+
const errorDetails = {
|
|
34
|
+
name: data.name,
|
|
35
|
+
message: data.message,
|
|
36
|
+
...(Object.keys(data).length ? data : {}),
|
|
37
|
+
};
|
|
38
|
+
return JSON.stringify(errorDetails, null, 2);
|
|
39
|
+
}
|
|
40
|
+
return typeof data === "object" ? JSON.stringify(data, null, 2) : String(data);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
protected log(message: string, data?: any): void {
|
|
44
|
+
console.log(chalk.white(`\n${message}`));
|
|
45
|
+
if (data) console.log(this.formatOutput(data));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected logSuccess(message: string, data?: any): void {
|
|
49
|
+
console.log(chalk.green(`\n✔ ${message}`));
|
|
50
|
+
if (data) console.log(chalk.green(this.formatOutput(data)));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
protected logInfo(message: string, data?: any): void {
|
|
54
|
+
console.log(chalk.blue(`\nℹ ${message}`));
|
|
55
|
+
if (data) console.log(chalk.blue(this.formatOutput(data)));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected logWarning(message: string, data?: any): void {
|
|
59
|
+
console.log(chalk.yellow(`\n⚠ ${message}`));
|
|
60
|
+
if (data) console.log(chalk.yellow(this.formatOutput(data)));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
protected logError(message: string, error?: any): void {
|
|
64
|
+
console.error(chalk.red(`\n✖ ${message}`));
|
|
65
|
+
if (error) console.error(chalk.red(this.formatOutput(error)));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
protected startSpinner(message: string) {
|
|
69
|
+
this.spinner.text = chalk.blue(`${message}`);
|
|
70
|
+
this.spinner.start();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected succeedSpinner(message: string, data?: any): void {
|
|
74
|
+
if (data) this.log('Result:', data);
|
|
75
|
+
this.spinner.succeed(chalk.green(message));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
protected failSpinner(message: string, error?:any): void {
|
|
79
|
+
if (error) this.log('Error:', error);
|
|
80
|
+
this.spinner.fail(chalk.red(message));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
protected stopSpinner(): void {
|
|
84
|
+
this.spinner.stop();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
protected setSpinnerText(message: string): void {
|
|
88
|
+
this.spinner.text = chalk.blue(message);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -32,7 +32,7 @@ export type AiProvidersConfigType = {
|
|
|
32
32
|
export const AI_PROVIDERS_CONFIG: AiProvidersConfigType = {
|
|
33
33
|
ollama: {
|
|
34
34
|
name: "Ollama",
|
|
35
|
-
hint: "(
|
|
35
|
+
hint: "(By default, this will download and run a local instance of Llama 3)",
|
|
36
36
|
cliOptionValue: "ollama",
|
|
37
37
|
},
|
|
38
38
|
openai: {
|
|
@@ -4,6 +4,7 @@ import * as dotenv from "dotenv";
|
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
import * as semver from "semver";
|
|
6
6
|
import updateCheck from "update-check";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
7
8
|
import pkg from '../../../package.json'
|
|
8
9
|
|
|
9
10
|
import {rpcClient} from "../clients/jsonRpcClient";
|
|
@@ -43,7 +44,8 @@ export class SimulatorService implements ISimulatorService {
|
|
|
43
44
|
public location: string;
|
|
44
45
|
|
|
45
46
|
constructor() {
|
|
46
|
-
|
|
47
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
48
|
+
this.location = path.resolve(path.dirname(__filename), '..');
|
|
47
49
|
this.composeOptions = "";
|
|
48
50
|
this.docker = new Docker();
|
|
49
51
|
}
|
|
@@ -184,7 +186,6 @@ export class SimulatorService implements ISimulatorService {
|
|
|
184
186
|
public async waitForSimulatorToBeReady(
|
|
185
187
|
retries: number = STARTING_TIMEOUT_ATTEMPTS,
|
|
186
188
|
): Promise<WaitForSimulatorToBeReadyResultType> {
|
|
187
|
-
console.log("Waiting for the simulator to start up...");
|
|
188
189
|
try {
|
|
189
190
|
const response = await rpcClient.request({method: "ping", params: []});
|
|
190
191
|
|
|
@@ -13,13 +13,6 @@ vi.mock("ethers", () => ({
|
|
|
13
13
|
},
|
|
14
14
|
}));
|
|
15
15
|
|
|
16
|
-
vi.mock("../../src/lib/config/ConfigFileManager", () => ({
|
|
17
|
-
ConfigFileManager: vi.fn().mockImplementation(() => ({
|
|
18
|
-
getFilePath: vi.fn((fileName) => `/mocked/path/${fileName}`),
|
|
19
|
-
writeConfig: vi.fn(),
|
|
20
|
-
})),
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
16
|
describe("KeypairCreator", () => {
|
|
24
17
|
let keypairCreator: KeypairCreator;
|
|
25
18
|
|
|
@@ -31,6 +24,11 @@ describe("KeypairCreator", () => {
|
|
|
31
24
|
|
|
32
25
|
beforeEach(() => {
|
|
33
26
|
vi.clearAllMocks();
|
|
27
|
+
vi.spyOn(keypairCreator as any, "startSpinner").mockImplementation(() => {});
|
|
28
|
+
vi.spyOn(keypairCreator as any, "succeedSpinner").mockImplementation(() => {});
|
|
29
|
+
vi.spyOn(keypairCreator as any, "failSpinner").mockImplementation(() => {});
|
|
30
|
+
vi.spyOn(keypairCreator as any, "writeConfig").mockImplementation(() => {});
|
|
31
|
+
vi.spyOn(keypairCreator as any, "getFilePath").mockImplementation((fileName) => `/mocked/path/${fileName}`);
|
|
34
32
|
vi.mocked(ethers.Wallet.createRandom).mockReturnValue(mockWallet);
|
|
35
33
|
});
|
|
36
34
|
|
|
@@ -39,15 +37,15 @@ describe("KeypairCreator", () => {
|
|
|
39
37
|
});
|
|
40
38
|
|
|
41
39
|
test("successfully creates and saves a keypair", () => {
|
|
42
|
-
const consoleLogSpy = vi.spyOn(console, "log");
|
|
43
40
|
vi.mocked(existsSync).mockReturnValue(false);
|
|
44
41
|
const options = { output: "keypair.json", overwrite: false };
|
|
45
42
|
|
|
46
43
|
keypairCreator.createKeypairAction(options);
|
|
47
44
|
|
|
45
|
+
expect(keypairCreator["startSpinner"]).toHaveBeenCalledWith("Creating keypair...");
|
|
48
46
|
expect(ethers.Wallet.createRandom).toHaveBeenCalledTimes(1);
|
|
47
|
+
expect(keypairCreator["getFilePath"]).toHaveBeenCalledWith("keypair.json");
|
|
49
48
|
|
|
50
|
-
expect(keypairCreator["filePathManager"].getFilePath).toHaveBeenCalledWith("keypair.json");
|
|
51
49
|
|
|
52
50
|
expect(writeFileSync).toHaveBeenCalledWith(
|
|
53
51
|
"/mocked/path/keypair.json",
|
|
@@ -61,20 +59,17 @@ describe("KeypairCreator", () => {
|
|
|
61
59
|
)
|
|
62
60
|
);
|
|
63
61
|
|
|
64
|
-
expect(keypairCreator["
|
|
62
|
+
expect(keypairCreator["writeConfig"]).toHaveBeenCalledWith(
|
|
65
63
|
"keyPairPath",
|
|
66
64
|
"/mocked/path/keypair.json"
|
|
67
65
|
);
|
|
68
66
|
|
|
69
|
-
expect(
|
|
67
|
+
expect(keypairCreator["succeedSpinner"]).toHaveBeenCalledWith(
|
|
70
68
|
"Keypair successfully created and saved to: /mocked/path/keypair.json"
|
|
71
69
|
);
|
|
72
70
|
});
|
|
73
71
|
|
|
74
72
|
test("skips creation if file exists and overwrite is false", () => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const consoleWarnSpy = vi.spyOn(console, "warn");
|
|
78
73
|
vi.mocked(existsSync).mockReturnValue(true);
|
|
79
74
|
const options = { output: "keypair.json", overwrite: false };
|
|
80
75
|
|
|
@@ -82,21 +77,20 @@ describe("KeypairCreator", () => {
|
|
|
82
77
|
|
|
83
78
|
expect(ethers.Wallet.createRandom).not.toHaveBeenCalled();
|
|
84
79
|
expect(writeFileSync).not.toHaveBeenCalled();
|
|
85
|
-
expect(
|
|
80
|
+
expect(keypairCreator["failSpinner"]).toHaveBeenCalledWith(
|
|
86
81
|
"The file at /mocked/path/keypair.json already exists. Use the '--overwrite' option to replace it."
|
|
87
82
|
);
|
|
88
83
|
});
|
|
89
84
|
|
|
90
85
|
test("overwrites the file if overwrite is true", () => {
|
|
91
|
-
const consoleLogSpy = vi.spyOn(console, "log");
|
|
92
86
|
vi.mocked(existsSync).mockReturnValue(true);
|
|
93
87
|
const options = { output: "keypair.json", overwrite: true };
|
|
94
88
|
|
|
95
89
|
keypairCreator.createKeypairAction(options);
|
|
96
90
|
|
|
91
|
+
expect(keypairCreator["startSpinner"]).toHaveBeenCalledWith("Creating keypair...");
|
|
97
92
|
expect(ethers.Wallet.createRandom).toHaveBeenCalledTimes(1);
|
|
98
|
-
|
|
99
|
-
expect(keypairCreator["filePathManager"].getFilePath).toHaveBeenCalledWith("keypair.json");
|
|
93
|
+
expect(keypairCreator["getFilePath"]).toHaveBeenCalledWith("keypair.json");
|
|
100
94
|
|
|
101
95
|
expect(writeFileSync).toHaveBeenCalledWith(
|
|
102
96
|
"/mocked/path/keypair.json",
|
|
@@ -110,31 +104,25 @@ describe("KeypairCreator", () => {
|
|
|
110
104
|
)
|
|
111
105
|
);
|
|
112
106
|
|
|
113
|
-
expect(keypairCreator["
|
|
107
|
+
expect(keypairCreator["writeConfig"]).toHaveBeenCalledWith(
|
|
114
108
|
"keyPairPath",
|
|
115
109
|
"/mocked/path/keypair.json"
|
|
116
110
|
);
|
|
117
111
|
|
|
118
|
-
expect(
|
|
112
|
+
expect(keypairCreator["succeedSpinner"]).toHaveBeenCalledWith(
|
|
119
113
|
"Keypair successfully created and saved to: /mocked/path/keypair.json"
|
|
120
114
|
);
|
|
121
115
|
});
|
|
122
116
|
|
|
123
117
|
test("handles errors during keypair creation", () => {
|
|
124
|
-
const
|
|
125
|
-
const processExitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
126
|
-
throw new Error("process.exit");
|
|
127
|
-
});
|
|
118
|
+
const mockError = new Error("Mocked write error");
|
|
128
119
|
|
|
129
120
|
vi.mocked(writeFileSync).mockImplementation(() => {
|
|
130
|
-
throw
|
|
121
|
+
throw mockError;
|
|
131
122
|
});
|
|
132
123
|
|
|
133
|
-
|
|
134
|
-
keypairCreator.createKeypairAction({ output: "keypair.json", overwrite: true });
|
|
135
|
-
}).toThrowError("process.exit");
|
|
124
|
+
keypairCreator.createKeypairAction({ output: "keypair.json", overwrite: true });
|
|
136
125
|
|
|
137
|
-
expect(
|
|
138
|
-
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
126
|
+
expect(keypairCreator["failSpinner"]).toHaveBeenCalledWith("Failed to generate keypair:", mockError);
|
|
139
127
|
});
|
|
140
128
|
});
|