genlayer 0.34.0 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/dist/index.js +13 -3
  2. package/package.json +11 -2
  3. package/.eslintignore +0 -2
  4. package/.github/workflows/cli-docs.yml +0 -121
  5. package/.github/workflows/publish-beta.yml +0 -41
  6. package/.github/workflows/publish.yml +0 -43
  7. package/.github/workflows/validate-code.yml +0 -47
  8. package/.prettierignore +0 -19
  9. package/.prettierrc +0 -12
  10. package/.release-it.json +0 -64
  11. package/CHANGELOG.md +0 -425
  12. package/CLAUDE.md +0 -55
  13. package/CONTRIBUTING.md +0 -117
  14. package/docker-compose.yml +0 -154
  15. package/docs/delegator-guide.md +0 -203
  16. package/docs/validator-guide.md +0 -329
  17. package/esbuild.config.dev.js +0 -17
  18. package/esbuild.config.js +0 -22
  19. package/esbuild.config.prod.js +0 -17
  20. package/eslint.config.js +0 -60
  21. package/renovate.json +0 -22
  22. package/src/commands/account/create.ts +0 -30
  23. package/src/commands/account/export.ts +0 -106
  24. package/src/commands/account/import.ts +0 -135
  25. package/src/commands/account/index.ts +0 -129
  26. package/src/commands/account/list.ts +0 -34
  27. package/src/commands/account/lock.ts +0 -39
  28. package/src/commands/account/remove.ts +0 -30
  29. package/src/commands/account/send.ts +0 -162
  30. package/src/commands/account/show.ts +0 -74
  31. package/src/commands/account/unlock.ts +0 -56
  32. package/src/commands/account/use.ts +0 -21
  33. package/src/commands/config/getSetReset.ts +0 -51
  34. package/src/commands/config/index.ts +0 -30
  35. package/src/commands/contracts/call.ts +0 -39
  36. package/src/commands/contracts/code.ts +0 -33
  37. package/src/commands/contracts/deploy.ts +0 -157
  38. package/src/commands/contracts/index.ts +0 -86
  39. package/src/commands/contracts/schema.ts +0 -31
  40. package/src/commands/contracts/write.ts +0 -49
  41. package/src/commands/general/index.ts +0 -45
  42. package/src/commands/general/init.ts +0 -179
  43. package/src/commands/general/start.ts +0 -116
  44. package/src/commands/general/stop.ts +0 -26
  45. package/src/commands/localnet/index.ts +0 -100
  46. package/src/commands/localnet/validators.ts +0 -269
  47. package/src/commands/network/index.ts +0 -29
  48. package/src/commands/network/setNetwork.ts +0 -77
  49. package/src/commands/scaffold/index.ts +0 -16
  50. package/src/commands/scaffold/new.ts +0 -34
  51. package/src/commands/staking/StakingAction.ts +0 -279
  52. package/src/commands/staking/delegatorClaim.ts +0 -41
  53. package/src/commands/staking/delegatorExit.ts +0 -56
  54. package/src/commands/staking/delegatorJoin.ts +0 -44
  55. package/src/commands/staking/index.ts +0 -357
  56. package/src/commands/staking/setIdentity.ts +0 -78
  57. package/src/commands/staking/setOperator.ts +0 -46
  58. package/src/commands/staking/stakingInfo.ts +0 -584
  59. package/src/commands/staking/validatorClaim.ts +0 -43
  60. package/src/commands/staking/validatorDeposit.ts +0 -48
  61. package/src/commands/staking/validatorExit.ts +0 -63
  62. package/src/commands/staking/validatorHistory.ts +0 -298
  63. package/src/commands/staking/validatorJoin.ts +0 -47
  64. package/src/commands/staking/validatorPrime.ts +0 -73
  65. package/src/commands/staking/wizard.ts +0 -809
  66. package/src/commands/transactions/appeal.ts +0 -39
  67. package/src/commands/transactions/index.ts +0 -39
  68. package/src/commands/transactions/receipt.ts +0 -90
  69. package/src/commands/update/index.ts +0 -25
  70. package/src/commands/update/ollama.ts +0 -103
  71. package/src/lib/actions/BaseAction.ts +0 -299
  72. package/src/lib/clients/jsonRpcClient.ts +0 -41
  73. package/src/lib/clients/system.ts +0 -73
  74. package/src/lib/config/ConfigFileManager.ts +0 -194
  75. package/src/lib/config/KeychainManager.ts +0 -89
  76. package/src/lib/config/simulator.ts +0 -68
  77. package/src/lib/config/text.ts +0 -2
  78. package/src/lib/errors/missingRequirement.ts +0 -9
  79. package/src/lib/errors/versionRequired.ts +0 -9
  80. package/src/lib/interfaces/ISimulatorService.ts +0 -37
  81. package/src/lib/services/simulator.ts +0 -351
  82. package/src/types/node-fetch.d.ts +0 -1
  83. package/tests/actions/appeal.test.ts +0 -99
  84. package/tests/actions/call.test.ts +0 -94
  85. package/tests/actions/code.test.ts +0 -87
  86. package/tests/actions/create.test.ts +0 -65
  87. package/tests/actions/deploy.test.ts +0 -420
  88. package/tests/actions/getSetReset.test.ts +0 -88
  89. package/tests/actions/init.test.ts +0 -467
  90. package/tests/actions/lock.test.ts +0 -86
  91. package/tests/actions/new.test.ts +0 -80
  92. package/tests/actions/ollama.test.ts +0 -193
  93. package/tests/actions/receipt.test.ts +0 -261
  94. package/tests/actions/schema.test.ts +0 -94
  95. package/tests/actions/setNetwork.test.ts +0 -160
  96. package/tests/actions/staking.test.ts +0 -279
  97. package/tests/actions/start.test.ts +0 -235
  98. package/tests/actions/stop.test.ts +0 -77
  99. package/tests/actions/unlock.test.ts +0 -139
  100. package/tests/actions/validators.test.ts +0 -750
  101. package/tests/actions/write.test.ts +0 -102
  102. package/tests/commands/account.test.ts +0 -146
  103. package/tests/commands/appeal.test.ts +0 -58
  104. package/tests/commands/call.test.ts +0 -78
  105. package/tests/commands/code.test.ts +0 -69
  106. package/tests/commands/config.test.ts +0 -54
  107. package/tests/commands/deploy.test.ts +0 -83
  108. package/tests/commands/init.test.ts +0 -101
  109. package/tests/commands/localnet.test.ts +0 -131
  110. package/tests/commands/network.test.ts +0 -60
  111. package/tests/commands/new.test.ts +0 -68
  112. package/tests/commands/receipt.test.ts +0 -142
  113. package/tests/commands/schema.test.ts +0 -67
  114. package/tests/commands/staking.test.ts +0 -329
  115. package/tests/commands/stop.test.ts +0 -27
  116. package/tests/commands/up.test.ts +0 -105
  117. package/tests/commands/update.test.ts +0 -45
  118. package/tests/commands/write.test.ts +0 -76
  119. package/tests/index.test.ts +0 -56
  120. package/tests/libs/baseAction.test.ts +0 -516
  121. package/tests/libs/configFileManager.test.ts +0 -117
  122. package/tests/libs/jsonRpcClient.test.ts +0 -59
  123. package/tests/libs/keychainManager.test.ts +0 -156
  124. package/tests/libs/system.test.ts +0 -148
  125. package/tests/services/simulator.test.ts +0 -705
  126. package/tests/utils.ts +0 -13
  127. package/tsconfig.json +0 -120
  128. package/vitest.config.ts +0 -12
@@ -1,467 +0,0 @@
1
- import {describe, test, vi, beforeEach, afterEach, expect} from "vitest";
2
- import inquirer from "inquirer";
3
- import {InitAction, InitActionOptions} from "../../src/commands/general/init";
4
- import {SimulatorService} from "../../src/lib/services/simulator";
5
- import {OllamaAction} from "../../src/commands/update/ollama";
6
- import {localnetCompatibleVersion} from "../../src/lib/config/simulator";
7
-
8
- describe("InitAction", () => {
9
- let initAction: InitAction;
10
- let inquirerPromptSpy: ReturnType<any>;
11
- let checkCliVersionSpy: ReturnType<typeof vi.spyOn>;
12
- let checkInstallRequirementsSpy: ReturnType<typeof vi.spyOn>;
13
- let checkVersionRequirementsSpy: ReturnType<typeof vi.spyOn>;
14
- let resetDockerContainersSpy: ReturnType<typeof vi.spyOn>;
15
- let resetDockerImagesSpy: ReturnType<typeof vi.spyOn>;
16
- let resetDockerVolumesSpy: ReturnType<typeof vi.spyOn>;
17
- let addConfigToEnvFileSpy: ReturnType<typeof vi.spyOn>;
18
- let runSimulatorSpy: ReturnType<typeof vi.spyOn>;
19
- let waitForSimulatorSpy: ReturnType<typeof vi.spyOn>;
20
- let deleteAllValidatorsSpy: ReturnType<typeof vi.spyOn>;
21
- let createRandomValidatorsSpy: ReturnType<typeof vi.spyOn>;
22
- let cleanDatabaseSpy: ReturnType<typeof vi.spyOn>;
23
- let openFrontendSpy: ReturnType<typeof vi.spyOn>;
24
- let getFrontendUrlSpy: ReturnType<typeof vi.spyOn>;
25
- let normalizeLocalnetVersionSpy: ReturnType<typeof vi.spyOn>;
26
-
27
- const defaultConfig = {defaultOllamaModel: "llama3"};
28
-
29
- const defaultOptions: InitActionOptions = {
30
- numValidators: 5,
31
- headless: false,
32
- resetDb: false,
33
- localnetVersion: localnetCompatibleVersion,
34
- ollama: false
35
- };
36
-
37
- beforeEach(() => {
38
- vi.clearAllMocks();
39
- initAction = new InitAction();
40
- inquirerPromptSpy = vi.spyOn(inquirer, "prompt");
41
- vi.spyOn(initAction as any, "startSpinner").mockImplementation(() => {});
42
- vi.spyOn(initAction as any, "setSpinnerText").mockImplementation(() => {});
43
- vi.spyOn(initAction as any, "succeedSpinner").mockImplementation(() => {});
44
- vi.spyOn(initAction as any, "failSpinner").mockImplementation(() => {});
45
- vi.spyOn(initAction as any, "stopSpinner").mockImplementation(() => {});
46
- vi.spyOn(initAction as any, "logError").mockImplementation(() => {});
47
- vi.spyOn(initAction, "getConfig").mockReturnValue(defaultConfig);
48
- checkCliVersionSpy = vi.spyOn(SimulatorService.prototype, "checkCliVersion").mockResolvedValue(undefined);
49
- checkInstallRequirementsSpy = vi
50
- .spyOn(SimulatorService.prototype, "checkInstallRequirements")
51
- .mockResolvedValue({git: true, docker: true});
52
- checkVersionRequirementsSpy = vi
53
- .spyOn(SimulatorService.prototype, "checkVersionRequirements")
54
- .mockResolvedValue({node: "", docker: ""});
55
- resetDockerContainersSpy = vi
56
- .spyOn(SimulatorService.prototype, "resetDockerContainers")
57
- .mockResolvedValue(undefined);
58
- resetDockerImagesSpy = vi
59
- .spyOn(SimulatorService.prototype, "resetDockerImages")
60
- .mockResolvedValue(undefined);
61
- resetDockerVolumesSpy = vi
62
- .spyOn(SimulatorService.prototype, "resetDockerVolumes")
63
- .mockResolvedValue(undefined);
64
- addConfigToEnvFileSpy = vi.spyOn(SimulatorService.prototype, "addConfigToEnvFile").mockResolvedValue();
65
- runSimulatorSpy = vi
66
- .spyOn(SimulatorService.prototype, "runSimulator")
67
- .mockResolvedValue(undefined as any);
68
- waitForSimulatorSpy = vi
69
- .spyOn(SimulatorService.prototype, "waitForSimulatorToBeReady")
70
- .mockResolvedValue({initialized: true}) as any;
71
- deleteAllValidatorsSpy = vi
72
- .spyOn(SimulatorService.prototype, "deleteAllValidators")
73
- .mockResolvedValue(undefined);
74
- createRandomValidatorsSpy = vi
75
- .spyOn(SimulatorService.prototype, "createRandomValidators")
76
- .mockResolvedValue(undefined) as any;
77
- cleanDatabaseSpy = vi.spyOn(SimulatorService.prototype, "cleanDatabase").mockResolvedValue(true);
78
- openFrontendSpy = vi.spyOn(SimulatorService.prototype, "openFrontend").mockResolvedValue(true);
79
- getFrontendUrlSpy = vi
80
- .spyOn(SimulatorService.prototype, "getFrontendUrl")
81
- .mockReturnValue("http://localhost:8080");
82
- normalizeLocalnetVersionSpy = vi
83
- .spyOn(SimulatorService.prototype, "normalizeLocalnetVersion")
84
- .mockImplementation((v: string) => v) as any;
85
- vi.spyOn(SimulatorService.prototype, "isLocalnetRunning").mockResolvedValue(false);
86
- });
87
-
88
- afterEach(() => {
89
- vi.restoreAllMocks();
90
- });
91
-
92
- describe("Successful Execution", () => {
93
- test("should show combined confirmation message when localnet is running", async () => {
94
- vi.spyOn(SimulatorService.prototype, "isLocalnetRunning").mockResolvedValue(true);
95
-
96
- const confirmPromptSpy = vi.spyOn(initAction as any, "confirmPrompt").mockResolvedValue(undefined);
97
-
98
- inquirerPromptSpy
99
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
100
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
101
-
102
- await initAction.execute(defaultOptions);
103
-
104
- expect(confirmPromptSpy).toHaveBeenCalledWith(
105
- "GenLayer Localnet is already running and this command is going to reset GenLayer docker images, containers and volumes, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?",
106
- );
107
- });
108
-
109
- test("should show standard confirmation message when localnet is not running", async () => {
110
- vi.spyOn(SimulatorService.prototype, "isLocalnetRunning").mockResolvedValue(false);
111
-
112
- const confirmPromptSpy = vi.spyOn(initAction as any, "confirmPrompt").mockResolvedValue(undefined);
113
-
114
- inquirerPromptSpy
115
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
116
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
117
-
118
- await initAction.execute(defaultOptions);
119
-
120
- expect(confirmPromptSpy).toHaveBeenCalledWith(
121
- "This command is going to reset GenLayer docker images, containers and volumes, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?",
122
- );
123
- });
124
-
125
- test("executes the full flow in non-headless mode", async () => {
126
- inquirerPromptSpy
127
- .mockResolvedValueOnce({confirmAction: true})
128
- .mockResolvedValueOnce({selectedLlmProviders: ["openai", "heuristai"]})
129
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"})
130
- .mockResolvedValueOnce({heuristai: "API_KEY_HEURIST"});
131
- await initAction.execute(defaultOptions);
132
- expect(checkCliVersionSpy).toHaveBeenCalled();
133
- expect(checkInstallRequirementsSpy).toHaveBeenCalled();
134
- expect(checkVersionRequirementsSpy).toHaveBeenCalled();
135
- expect(resetDockerContainersSpy).toHaveBeenCalled();
136
- expect(resetDockerImagesSpy).toHaveBeenCalled();
137
- expect(resetDockerVolumesSpy).toHaveBeenCalled();
138
- expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({
139
- OPENAIKEY: "API_KEY_OPENAI",
140
- HEURISTAIAPIKEY: "API_KEY_HEURIST",
141
- });
142
- expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({LOCALNETVERSION: localnetCompatibleVersion});
143
- expect(runSimulatorSpy).toHaveBeenCalled();
144
- expect(waitForSimulatorSpy).toHaveBeenCalled();
145
- expect(deleteAllValidatorsSpy).toHaveBeenCalled();
146
- expect(createRandomValidatorsSpy).toHaveBeenCalledWith(5, ["openai", "heuristai"]);
147
- expect(getFrontendUrlSpy).toHaveBeenCalled();
148
- expect(openFrontendSpy).toHaveBeenCalled();
149
- expect((initAction as any).succeedSpinner).toHaveBeenCalledWith(
150
- "GenLayer Localnet initialized successfully! Go to http://localhost:8080 in your browser to access it.",
151
- );
152
- });
153
-
154
- test("executes correctly in headless mode with DB reset and 'ollama' selected", async () => {
155
- inquirerPromptSpy
156
- .mockResolvedValueOnce({confirmAction: true})
157
- .mockResolvedValueOnce({selectedLlmProviders: ["openai", "ollama"]})
158
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
159
- const ollamaUpdateSpy = vi.spyOn(OllamaAction.prototype, "updateModel").mockResolvedValue(undefined);
160
- const headlessOptions: InitActionOptions = {
161
- numValidators: 5,
162
- headless: true,
163
- resetDb: true,
164
- localnetVersion: localnetCompatibleVersion,
165
- ollama: true
166
- };
167
- await initAction.execute(headlessOptions);
168
- expect(cleanDatabaseSpy).toHaveBeenCalled();
169
- expect(openFrontendSpy).not.toHaveBeenCalled();
170
- expect((initAction as any).succeedSpinner).toHaveBeenCalledWith(
171
- "GenLayer Localnet initialized successfully! ",
172
- );
173
- expect(ollamaUpdateSpy).toHaveBeenCalledWith("llama3");
174
- });
175
-
176
- test("normalizes localnetVersion if not 'latest'", async () => {
177
- const customVersion = "v99";
178
- normalizeLocalnetVersionSpy.mockReturnValue(customVersion);
179
- inquirerPromptSpy
180
- .mockResolvedValueOnce({confirmAction: true})
181
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
182
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
183
- await initAction.execute({...defaultOptions, localnetVersion: customVersion});
184
- expect(normalizeLocalnetVersionSpy).toHaveBeenCalledWith(customVersion);
185
- expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({LOCALNETVERSION: customVersion});
186
- });
187
-
188
- test("should set defaultOllamaModel to 'llama3' if not provided in config", async () => {
189
- vi.spyOn(initAction, "getConfig").mockReturnValue({});
190
- const writeConfigSpy = vi.spyOn(initAction, "writeConfig").mockImplementation(() => {});
191
- const ollamaUpdateSpy = vi.spyOn(OllamaAction.prototype, "updateModel").mockResolvedValue(undefined);
192
- inquirerPromptSpy
193
- .mockResolvedValueOnce({confirmAction: true})
194
- .mockResolvedValueOnce({selectedLlmProviders: ["ollama"]})
195
- .mockResolvedValueOnce({ollama: "API_KEY_OLLAMA"});
196
- await initAction.execute(defaultOptions);
197
- expect(writeConfigSpy).toHaveBeenCalledWith("defaultOllamaModel", "llama3");
198
- expect(ollamaUpdateSpy).toHaveBeenCalledWith("llama3");
199
- });
200
-
201
- test("validates API key input for configurable provider", async () => {
202
- inquirerPromptSpy.mockResolvedValueOnce({confirmAction: true});
203
- inquirerPromptSpy.mockResolvedValueOnce({selectedLlmProviders: ["openai"]});
204
- let capturedQuestion: any;
205
- inquirerPromptSpy.mockImplementationOnce((questions: any) => {
206
- capturedQuestion = questions[0];
207
- return Promise.resolve({openai: "dummy-key"});
208
- });
209
- await initAction.execute(defaultOptions);
210
- expect(capturedQuestion).toBeDefined();
211
- const expectedError = `Please enter a valid API Key for OpenAI.`;
212
- expect(capturedQuestion.validate("")).toBe(expectedError);
213
- expect(capturedQuestion.validate("non-empty-key")).toBe(true);
214
- });
215
-
216
- test("validates LLM provider selection prompt", async () => {
217
- let capturedQuestion: any;
218
- inquirerPromptSpy
219
- .mockResolvedValueOnce({confirmAction: true})
220
- .mockImplementationOnce((questions: any) => {
221
- capturedQuestion = questions[0];
222
- return Promise.resolve({selectedLlmProviders: ["openai"]});
223
- })
224
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
225
- await initAction.execute(defaultOptions);
226
- expect(capturedQuestion.validate([])).toBe("You must choose at least one option.");
227
- expect(capturedQuestion.validate(["openai"])).toBe(true);
228
- });
229
-
230
- test("should exclude ollama from choices when ollama option is false", async () => {
231
- const getAiProvidersOptionsSpy = vi.spyOn(SimulatorService.prototype, "getAiProvidersOptions");
232
- inquirerPromptSpy
233
- .mockResolvedValueOnce({ confirmAction: true })
234
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
235
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
236
-
237
- await initAction.execute({ ...defaultOptions, ollama: false });
238
-
239
- expect(getAiProvidersOptionsSpy).toHaveBeenCalledWith(true, ["ollama"]);
240
- });
241
-
242
- test("should include ollama in choices when ollama option is true", async () => {
243
- const getAiProvidersOptionsSpy = vi.spyOn(SimulatorService.prototype, "getAiProvidersOptions");
244
- inquirerPromptSpy
245
- .mockResolvedValueOnce({ confirmAction: true })
246
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
247
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
248
-
249
- await initAction.execute({ ...defaultOptions, ollama: true });
250
-
251
- expect(getAiProvidersOptionsSpy).toHaveBeenCalledWith(true, []);
252
- });
253
- });
254
-
255
- describe("Error Handling", () => {
256
- test("fails if Docker is not installed", async () => {
257
- checkInstallRequirementsSpy.mockResolvedValue({git: true, docker: false});
258
- await initAction.execute(defaultOptions);
259
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
260
- "Docker is not installed. Please install Docker and try again.\n",
261
- );
262
- });
263
-
264
- test("fails if localnet version is older than compatible version", async () => {
265
- const olderVersion = "v0.0.1";
266
- normalizeLocalnetVersionSpy.mockReturnValue(olderVersion);
267
- await initAction.execute({...defaultOptions, localnetVersion: olderVersion});
268
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
269
- `Localnet version ${olderVersion} is not supported. Minimum required version is ${localnetCompatibleVersion}. Please use a newer version.`
270
- );
271
- });
272
-
273
- test("should proceed when localnet version is equal to compatible version", async () => {
274
- normalizeLocalnetVersionSpy.mockReturnValue(localnetCompatibleVersion);
275
- inquirerPromptSpy
276
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
277
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
278
- await initAction.execute({...defaultOptions, localnetVersion: localnetCompatibleVersion});
279
- expect((initAction as any).failSpinner).not.toHaveBeenCalledWith(
280
- expect.stringContaining("Localnet version")
281
- );
282
- });
283
-
284
- test("should proceed when localnet version is newer than compatible version", async () => {
285
- const newerVersion = "v99.99.99";
286
- normalizeLocalnetVersionSpy.mockReturnValue(newerVersion);
287
- inquirerPromptSpy
288
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
289
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
290
- await initAction.execute({...defaultOptions, localnetVersion: newerVersion});
291
- expect((initAction as any).failSpinner).not.toHaveBeenCalledWith(
292
- expect.stringContaining("Localnet version")
293
- );
294
- });
295
-
296
- test("should skip version validation when localnet version is 'latest'", async () => {
297
- inquirerPromptSpy
298
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
299
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
300
- await initAction.execute({...defaultOptions, localnetVersion: "latest"});
301
- expect(normalizeLocalnetVersionSpy).not.toHaveBeenCalled();
302
- expect((initAction as any).failSpinner).not.toHaveBeenCalledWith(
303
- expect.stringContaining("Localnet version")
304
- );
305
- });
306
-
307
- test("fails if checkInstallRequirements throws an error", async () => {
308
- const error = new Error("Install error");
309
- checkInstallRequirementsSpy.mockRejectedValue(error);
310
- await initAction.execute(defaultOptions);
311
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
312
- "An error occurred during initialization.",
313
- error,
314
- );
315
- });
316
-
317
- test("fails if version requirements are not met (both docker and node)", async () => {
318
- const version = "99.9.9";
319
- checkVersionRequirementsSpy.mockResolvedValue({docker: version, node: version});
320
- await initAction.execute(defaultOptions);
321
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
322
- `Docker version ${version} or higher is required. Please update Docker and try again.\nNode version ${version} or higher is required. Please update Node and try again.\n`,
323
- );
324
- });
325
-
326
- test("fails if version requirement for docker is not met", async () => {
327
- const version = "99.9.9";
328
- checkVersionRequirementsSpy.mockResolvedValue({docker: version});
329
- await initAction.execute(defaultOptions);
330
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
331
- `Docker version ${version} or higher is required. Please update Docker and try again.\n`,
332
- );
333
- });
334
-
335
- test("fails if version requirement for node is not met", async () => {
336
- const version = "99.9.9";
337
- checkVersionRequirementsSpy.mockResolvedValue({node: version});
338
- await initAction.execute(defaultOptions);
339
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
340
- `Node version ${version} or higher is required. Please update Node and try again.\n`,
341
- );
342
- });
343
-
344
- test("aborts if user does not confirm reset action", async () => {
345
- inquirerPromptSpy.mockResolvedValueOnce({confirmAction: false});
346
- await initAction.execute(defaultOptions);
347
- expect((initAction as any).logError).toHaveBeenCalledWith(`Operation aborted!`);
348
- });
349
-
350
- test("fails if resetDockerContainers throws an error", async () => {
351
- inquirerPromptSpy.mockResolvedValueOnce({confirmAction: true});
352
- resetDockerContainersSpy.mockRejectedValue(new Error("Container reset error"));
353
- await initAction.execute(defaultOptions);
354
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
355
- "An error occurred during initialization.",
356
- new Error("Container reset error"),
357
- );
358
- });
359
-
360
- test("fails if runSimulator throws an error", async () => {
361
- inquirerPromptSpy
362
- .mockResolvedValueOnce({confirmAction: true})
363
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
364
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
365
- runSimulatorSpy.mockRejectedValue(new Error("Run simulator error"));
366
- await initAction.execute(defaultOptions);
367
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
368
- "An error occurred during initialization.",
369
- new Error("Run simulator error"),
370
- );
371
- });
372
-
373
- test("fails if waitForSimulatorToBeReady returns ERROR code", async () => {
374
- inquirerPromptSpy
375
- .mockResolvedValueOnce({confirmAction: true})
376
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
377
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
378
- waitForSimulatorSpy.mockResolvedValue({
379
- initialized: false,
380
- errorCode: "ERROR",
381
- errorMessage: "Initialization failed",
382
- });
383
- await initAction.execute(defaultOptions);
384
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
385
- "Unable to initialize the GenLayer Localnet: Initialization failed",
386
- );
387
- });
388
-
389
- test("fails if waitForSimulatorToBeReady returns TIMEOUT code", async () => {
390
- inquirerPromptSpy
391
- .mockResolvedValueOnce({confirmAction: true})
392
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
393
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
394
- waitForSimulatorSpy.mockResolvedValue({
395
- initialized: false,
396
- errorCode: "TIMEOUT",
397
- errorMessage: "Timeout",
398
- });
399
- await initAction.execute(defaultOptions);
400
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
401
- "The localnet is taking too long to initialize. Please try again after the localnet is ready.",
402
- );
403
- });
404
-
405
- test("fails if deleteAllValidators throws an error", async () => {
406
- inquirerPromptSpy
407
- .mockResolvedValueOnce({confirmAction: true})
408
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
409
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
410
- deleteAllValidatorsSpy.mockRejectedValue(new Error("Validator deletion error"));
411
- await initAction.execute(defaultOptions);
412
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
413
- "An error occurred during initialization.",
414
- expect.any(Error),
415
- );
416
- });
417
-
418
- test("fails if createRandomValidators throws an error", async () => {
419
- inquirerPromptSpy
420
- .mockResolvedValueOnce({confirmAction: true})
421
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
422
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
423
- createRandomValidatorsSpy.mockRejectedValue(new Error("Validator creation error"));
424
- await initAction.execute(defaultOptions);
425
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
426
- "An error occurred during initialization.",
427
- Error("Validator creation error"),
428
- );
429
- });
430
-
431
- test("fails if cleanDatabase throws an error when resetDb is true", async () => {
432
- inquirerPromptSpy
433
- .mockResolvedValueOnce({confirmAction: true})
434
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
435
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
436
- cleanDatabaseSpy.mockRejectedValue(new Error("Database error"));
437
- const optionsWithResetDb: InitActionOptions = {...defaultOptions, resetDb: true};
438
- await initAction.execute(optionsWithResetDb);
439
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
440
- "An error occurred during initialization.",
441
- new Error("Database error"),
442
- );
443
- });
444
-
445
- test("fails if openFrontend throws an error", async () => {
446
- inquirerPromptSpy
447
- .mockResolvedValueOnce({confirmAction: true})
448
- .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
449
- .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
450
- openFrontendSpy.mockRejectedValue(new Error("Frontend error"));
451
- await initAction.execute(defaultOptions);
452
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
453
- "An error occurred during initialization.",
454
- new Error("Frontend error"),
455
- );
456
- });
457
-
458
- test("catches and logs unexpected errors", async () => {
459
- inquirerPromptSpy.mockRejectedValueOnce(new Error("Unexpected prompt error"));
460
- await initAction.execute(defaultOptions);
461
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(
462
- "An error occurred during initialization.",
463
- new Error("Unexpected prompt error"),
464
- );
465
- });
466
- });
467
- });
@@ -1,86 +0,0 @@
1
- import {describe, test, vi, beforeEach, afterEach, expect} from "vitest";
2
- import {LockAccountAction} from "../../src/commands/account/lock";
3
- import {readFileSync, existsSync} from "fs";
4
- import os from "os";
5
-
6
- vi.mock("fs");
7
- vi.mock("os");
8
-
9
- describe("LockAccountAction", () => {
10
- let lockAction: LockAccountAction;
11
-
12
- beforeEach(() => {
13
- vi.clearAllMocks();
14
- // Setup mocks before creating the action (needed for constructor)
15
- vi.mocked(os.homedir).mockReturnValue("/mocked/home");
16
- vi.mocked(existsSync).mockReturnValue(true);
17
- vi.mocked(readFileSync).mockReturnValue(JSON.stringify({activeAccount: "default"}));
18
-
19
- lockAction = new LockAccountAction();
20
-
21
- // Mock the BaseAction methods
22
- vi.spyOn(lockAction as any, "startSpinner").mockImplementation(() => {});
23
- vi.spyOn(lockAction as any, "setSpinnerText").mockImplementation(() => {});
24
- vi.spyOn(lockAction as any, "succeedSpinner").mockImplementation(() => {});
25
- vi.spyOn(lockAction as any, "failSpinner").mockImplementation(() => {});
26
- vi.spyOn(lockAction as any, "resolveAccountName").mockReturnValue("default");
27
-
28
- // Mock keychainManager
29
- vi.spyOn(lockAction["keychainManager"], "isKeychainAvailable").mockResolvedValue(true);
30
- vi.spyOn(lockAction["keychainManager"], "getPrivateKey").mockResolvedValue("test-private-key");
31
- vi.spyOn(lockAction["keychainManager"], "removePrivateKey").mockResolvedValue(true);
32
- });
33
-
34
- afterEach(() => {
35
- vi.restoreAllMocks();
36
- });
37
-
38
- test("successfully locks wallet when keychain is available and key exists", async () => {
39
- await lockAction.execute();
40
-
41
- expect(lockAction["startSpinner"]).toHaveBeenCalledWith("Checking keychain availability...");
42
- expect(lockAction["keychainManager"].isKeychainAvailable).toHaveBeenCalled();
43
- expect(lockAction["setSpinnerText"]).toHaveBeenCalledWith("Checking for cached private key for 'default'...");
44
- expect(lockAction["keychainManager"].getPrivateKey).toHaveBeenCalledWith("default");
45
- expect(lockAction["setSpinnerText"]).toHaveBeenCalledWith("Removing private key for 'default' from OS keychain...");
46
- expect(lockAction["keychainManager"].removePrivateKey).toHaveBeenCalledWith("default");
47
- expect(lockAction["succeedSpinner"]).toHaveBeenCalledWith("Account 'default' locked! Private key removed from OS keychain.");
48
- });
49
-
50
- test("fails when keychain is not available", async () => {
51
- vi.spyOn(lockAction["keychainManager"], "isKeychainAvailable").mockResolvedValue(false);
52
-
53
- await lockAction.execute();
54
-
55
- expect(lockAction["failSpinner"]).toHaveBeenCalledWith("OS keychain is not available. This command requires a supported keychain (e.g. macOS Keychain, Windows Credential Manager, or GNOME Keyring).");
56
- expect(lockAction["keychainManager"].getPrivateKey).not.toHaveBeenCalled();
57
- expect(lockAction["keychainManager"].removePrivateKey).not.toHaveBeenCalled();
58
- });
59
-
60
- test("succeeds when wallet is already locked (no cached key)", async () => {
61
- vi.spyOn(lockAction["keychainManager"], "getPrivateKey").mockResolvedValue(null);
62
-
63
- await lockAction.execute();
64
-
65
- expect(lockAction["succeedSpinner"]).toHaveBeenCalledWith("Account 'default' is already locked.");
66
- expect(lockAction["keychainManager"].removePrivateKey).not.toHaveBeenCalled();
67
- });
68
-
69
- test("handles error during key removal", async () => {
70
- const mockError = new Error("Keychain error");
71
- vi.spyOn(lockAction["keychainManager"], "removePrivateKey").mockRejectedValue(mockError);
72
-
73
- await lockAction.execute();
74
-
75
- expect(lockAction["failSpinner"]).toHaveBeenCalledWith("Failed to lock account.", mockError);
76
- });
77
-
78
- test("uses account option when provided", async () => {
79
- vi.spyOn(lockAction as any, "resolveAccountName").mockReturnValue("validator");
80
-
81
- await lockAction.execute({account: "validator"});
82
-
83
- expect(lockAction["accountOverride"]).toBe("validator");
84
- expect(lockAction["setSpinnerText"]).toHaveBeenCalledWith("Checking for cached private key for 'validator'...");
85
- });
86
- });
@@ -1,80 +0,0 @@
1
- import { describe, test, vi, beforeEach, afterEach, expect } from "vitest";
2
- import fs from "fs-extra";
3
- import path from "path";
4
- import { NewAction } from "../../src/commands/scaffold/new";
5
-
6
- vi.mock("fs-extra");
7
-
8
- describe("NewAction", () => {
9
- let newAction: NewAction;
10
- let mockExistsSync: any;
11
- let mockCopySync: any;
12
-
13
- beforeEach(() => {
14
- vi.clearAllMocks();
15
- newAction = new NewAction();
16
-
17
- mockExistsSync = vi.mocked(fs.existsSync);
18
- mockCopySync = vi.mocked(fs.copySync);
19
-
20
- vi.spyOn(newAction as any, "startSpinner").mockImplementation(() => {});
21
- vi.spyOn(newAction as any, "succeedSpinner").mockImplementation(() => {});
22
- vi.spyOn(newAction as any, "failSpinner").mockImplementation(() => {});
23
- });
24
-
25
- afterEach(() => {
26
- vi.restoreAllMocks();
27
- });
28
-
29
- test("should successfully create a new project", async () => {
30
- mockExistsSync.mockReturnValue(false);
31
- mockCopySync.mockImplementation(() => {});
32
-
33
- await newAction.createProject("myProject", { path: ".", overwrite: false });
34
-
35
- expect(newAction["startSpinner"]).toHaveBeenCalledWith("Creating new GenLayer project: myProject");
36
- expect(mockCopySync).toHaveBeenCalledWith(expect.any(String), path.resolve(".", "myProject"));
37
- expect(newAction["succeedSpinner"]).toHaveBeenCalledWith(
38
- `Project "myProject" created successfully at ${path.resolve(".", "myProject")}`
39
- );
40
- });
41
-
42
- test("should fail if project directory exists and overwrite is not set", async () => {
43
- mockExistsSync.mockReturnValue(true);
44
-
45
- await newAction.createProject("existingProject", { path: ".", overwrite: false });
46
-
47
- expect(newAction["failSpinner"]).toHaveBeenCalledWith(
48
- `Project directory "${path.resolve(".", "existingProject")}" already exists. Use --overwrite to replace it.`
49
- );
50
- expect(mockCopySync).not.toHaveBeenCalled();
51
- });
52
-
53
- test("should overwrite existing project if overwrite is set", async () => {
54
- mockExistsSync.mockReturnValue(true);
55
- mockCopySync.mockImplementation(() => {});
56
-
57
- await newAction.createProject("overwriteProject", { path: ".", overwrite: true });
58
-
59
- expect(newAction["startSpinner"]).toHaveBeenCalledWith("Creating new GenLayer project: overwriteProject");
60
- expect(mockCopySync).toHaveBeenCalledWith(expect.any(String), path.resolve(".", "overwriteProject"));
61
- expect(newAction["succeedSpinner"]).toHaveBeenCalledWith(
62
- `Project "overwriteProject" created successfully at ${path.resolve(".", "overwriteProject")}`
63
- );
64
- });
65
-
66
- test("should fail if an error occurs while copying files", async () => {
67
- mockExistsSync.mockReturnValue(false);
68
- const error = new Error("Mocked file system error");
69
- mockCopySync.mockImplementation(() => {
70
- throw error;
71
- });
72
-
73
- await newAction.createProject("errorProject", { path: ".", overwrite: false });
74
-
75
- expect(newAction["failSpinner"]).toHaveBeenCalledWith(
76
- "Error creating project \"errorProject\"",
77
- error
78
- );
79
- });
80
- });