genlayer 0.38.8 → 0.38.10

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 (205) hide show
  1. package/.eslintignore +2 -0
  2. package/.github/workflows/cli-docs.yml +124 -0
  3. package/.github/workflows/publish.yml +55 -0
  4. package/.github/workflows/smoke.yml +27 -0
  5. package/.github/workflows/validate-code.yml +51 -0
  6. package/.prettierignore +19 -0
  7. package/.prettierrc +12 -0
  8. package/.release-it.json +66 -0
  9. package/CHANGELOG.md +545 -0
  10. package/CLAUDE.md +55 -0
  11. package/CONTRIBUTING.md +117 -0
  12. package/dist/index.js +221 -62
  13. package/docs/api-references/_meta.json +9 -0
  14. package/docs/api-references/accounts/_meta.json +3 -0
  15. package/docs/api-references/accounts/account/create.mdx +19 -0
  16. package/docs/api-references/accounts/account/export.mdx +19 -0
  17. package/docs/api-references/accounts/account/import.mdx +22 -0
  18. package/docs/api-references/accounts/account/list.mdx +15 -0
  19. package/docs/api-references/accounts/account/lock.mdx +16 -0
  20. package/docs/api-references/accounts/account/remove.mdx +20 -0
  21. package/docs/api-references/accounts/account/send.mdx +24 -0
  22. package/docs/api-references/accounts/account/show.mdx +17 -0
  23. package/docs/api-references/accounts/account/unlock.mdx +17 -0
  24. package/docs/api-references/accounts/account/use.mdx +19 -0
  25. package/docs/api-references/accounts/account.mdx +32 -0
  26. package/docs/api-references/configuration/_meta.json +4 -0
  27. package/docs/api-references/configuration/config/get.mdx +21 -0
  28. package/docs/api-references/configuration/config/reset.mdx +21 -0
  29. package/docs/api-references/configuration/config/set.mdx +21 -0
  30. package/docs/api-references/configuration/config.mdx +25 -0
  31. package/docs/api-references/configuration/network/info.mdx +15 -0
  32. package/docs/api-references/configuration/network/list.mdx +15 -0
  33. package/docs/api-references/configuration/network/set.mdx +21 -0
  34. package/docs/api-references/configuration/network.mdx +25 -0
  35. package/docs/api-references/contracts/_meta.json +7 -0
  36. package/docs/api-references/contracts/call.mdx +21 -0
  37. package/docs/api-references/contracts/code.mdx +20 -0
  38. package/docs/api-references/contracts/deploy.mdx +17 -0
  39. package/docs/api-references/contracts/schema.mdx +20 -0
  40. package/docs/api-references/contracts/write.mdx +21 -0
  41. package/docs/api-references/environment/_meta.json +7 -0
  42. package/docs/api-references/environment/init.mdx +20 -0
  43. package/docs/api-references/environment/new.mdx +21 -0
  44. package/docs/api-references/environment/stop.mdx +15 -0
  45. package/docs/api-references/environment/up.mdx +20 -0
  46. package/docs/api-references/environment/update/ollama.mdx +16 -0
  47. package/docs/api-references/environment/update.mdx +23 -0
  48. package/docs/api-references/index.mdx +35 -0
  49. package/docs/api-references/localnet/_meta.json +3 -0
  50. package/docs/api-references/localnet/localnet/validators/count.mdx +15 -0
  51. package/docs/api-references/localnet/localnet/validators/create-random.mdx +16 -0
  52. package/docs/api-references/localnet/localnet/validators/create.mdx +19 -0
  53. package/docs/api-references/localnet/localnet/validators/delete.mdx +16 -0
  54. package/docs/api-references/localnet/localnet/validators/get.mdx +16 -0
  55. package/docs/api-references/localnet/localnet/validators/update.mdx +23 -0
  56. package/docs/api-references/localnet/localnet/validators.mdx +28 -0
  57. package/docs/api-references/localnet/localnet.mdx +23 -0
  58. package/docs/api-references/staking/_meta.json +3 -0
  59. package/docs/api-references/staking/staking/active-validators.mdx +18 -0
  60. package/docs/api-references/staking/staking/banned-validators.mdx +18 -0
  61. package/docs/api-references/staking/staking/delegation-info.mdx +25 -0
  62. package/docs/api-references/staking/staking/delegator-claim.mdx +26 -0
  63. package/docs/api-references/staking/staking/delegator-exit.mdx +26 -0
  64. package/docs/api-references/staking/staking/delegator-join.mdx +26 -0
  65. package/docs/api-references/staking/staking/epoch-info.mdx +19 -0
  66. package/docs/api-references/staking/staking/prime-all.mdx +20 -0
  67. package/docs/api-references/staking/staking/quarantined-validators.mdx +18 -0
  68. package/docs/api-references/staking/staking/set-identity.mdx +33 -0
  69. package/docs/api-references/staking/staking/set-operator.mdx +26 -0
  70. package/docs/api-references/staking/staking/validator-claim.mdx +24 -0
  71. package/docs/api-references/staking/staking/validator-deposit.mdx +25 -0
  72. package/docs/api-references/staking/staking/validator-exit.mdx +25 -0
  73. package/docs/api-references/staking/staking/validator-history.mdx +29 -0
  74. package/docs/api-references/staking/staking/validator-info.mdx +25 -0
  75. package/docs/api-references/staking/staking/validator-join.mdx +22 -0
  76. package/docs/api-references/staking/staking/validator-prime.mdx +25 -0
  77. package/docs/api-references/staking/staking/validators.mdx +19 -0
  78. package/docs/api-references/staking/staking/wizard.mdx +20 -0
  79. package/docs/api-references/staking/staking.mdx +42 -0
  80. package/docs/api-references/transactions/_meta.json +6 -0
  81. package/docs/api-references/transactions/appeal-bond.mdx +20 -0
  82. package/docs/api-references/transactions/appeal.mdx +21 -0
  83. package/docs/api-references/transactions/receipt.mdx +25 -0
  84. package/docs/api-references/transactions/trace.mdx +21 -0
  85. package/docs/delegator-guide.md +203 -0
  86. package/docs/validator-guide.md +329 -0
  87. package/esbuild.config.dev.js +17 -0
  88. package/esbuild.config.js +22 -0
  89. package/esbuild.config.prod.js +17 -0
  90. package/eslint.config.js +60 -0
  91. package/package.json +2 -11
  92. package/renovate.json +22 -0
  93. package/scripts/generate-cli-docs.mjs +68 -5
  94. package/src/commands/account/create.ts +30 -0
  95. package/src/commands/account/export.ts +106 -0
  96. package/src/commands/account/import.ts +135 -0
  97. package/src/commands/account/index.ts +129 -0
  98. package/src/commands/account/list.ts +34 -0
  99. package/src/commands/account/lock.ts +39 -0
  100. package/src/commands/account/remove.ts +30 -0
  101. package/src/commands/account/send.ts +162 -0
  102. package/src/commands/account/show.ts +74 -0
  103. package/src/commands/account/unlock.ts +56 -0
  104. package/src/commands/account/use.ts +21 -0
  105. package/src/commands/config/getSetReset.ts +51 -0
  106. package/src/commands/config/index.ts +30 -0
  107. package/src/commands/contracts/call.ts +39 -0
  108. package/src/commands/contracts/code.ts +33 -0
  109. package/src/commands/contracts/deploy.ts +161 -0
  110. package/src/commands/contracts/index.ts +150 -0
  111. package/src/commands/contracts/schema.ts +31 -0
  112. package/src/commands/contracts/write.ts +49 -0
  113. package/src/commands/general/index.ts +45 -0
  114. package/src/commands/general/init.ts +180 -0
  115. package/src/commands/general/start.ts +128 -0
  116. package/src/commands/general/stop.ts +26 -0
  117. package/src/commands/localnet/index.ts +100 -0
  118. package/src/commands/localnet/validators.ts +269 -0
  119. package/src/commands/network/index.ts +29 -0
  120. package/src/commands/network/setNetwork.ts +77 -0
  121. package/src/commands/scaffold/index.ts +16 -0
  122. package/src/commands/scaffold/new.ts +34 -0
  123. package/src/commands/staking/StakingAction.ts +279 -0
  124. package/src/commands/staking/delegatorClaim.ts +41 -0
  125. package/src/commands/staking/delegatorExit.ts +56 -0
  126. package/src/commands/staking/delegatorJoin.ts +44 -0
  127. package/src/commands/staking/index.ts +357 -0
  128. package/src/commands/staking/setIdentity.ts +78 -0
  129. package/src/commands/staking/setOperator.ts +46 -0
  130. package/src/commands/staking/stakingInfo.ts +584 -0
  131. package/src/commands/staking/validatorClaim.ts +43 -0
  132. package/src/commands/staking/validatorDeposit.ts +48 -0
  133. package/src/commands/staking/validatorExit.ts +63 -0
  134. package/src/commands/staking/validatorHistory.ts +300 -0
  135. package/src/commands/staking/validatorJoin.ts +47 -0
  136. package/src/commands/staking/validatorPrime.ts +73 -0
  137. package/src/commands/staking/wizard.ts +809 -0
  138. package/src/commands/transactions/appeal.ts +83 -0
  139. package/src/commands/transactions/index.ts +60 -0
  140. package/src/commands/transactions/receipt.ts +90 -0
  141. package/src/commands/transactions/trace.ts +42 -0
  142. package/src/commands/update/index.ts +25 -0
  143. package/src/commands/update/ollama.ts +103 -0
  144. package/src/lib/actions/BaseAction.ts +301 -0
  145. package/src/lib/clients/jsonRpcClient.ts +41 -0
  146. package/src/lib/clients/system.ts +73 -0
  147. package/src/lib/config/ConfigFileManager.ts +194 -0
  148. package/src/lib/config/KeychainManager.ts +89 -0
  149. package/src/lib/config/simulator.ts +68 -0
  150. package/src/lib/config/text.ts +2 -0
  151. package/src/lib/errors/missingRequirement.ts +9 -0
  152. package/src/lib/errors/versionRequired.ts +9 -0
  153. package/src/lib/interfaces/ISimulatorService.ts +39 -0
  154. package/src/lib/services/simulator.ts +386 -0
  155. package/src/types/node-fetch.d.ts +1 -0
  156. package/tests/actions/appeal.test.ts +141 -0
  157. package/tests/actions/call.test.ts +94 -0
  158. package/tests/actions/code.test.ts +87 -0
  159. package/tests/actions/create.test.ts +65 -0
  160. package/tests/actions/deploy.test.ts +420 -0
  161. package/tests/actions/getSetReset.test.ts +88 -0
  162. package/tests/actions/init.test.ts +483 -0
  163. package/tests/actions/lock.test.ts +86 -0
  164. package/tests/actions/new.test.ts +80 -0
  165. package/tests/actions/ollama.test.ts +193 -0
  166. package/tests/actions/receipt.test.ts +261 -0
  167. package/tests/actions/schema.test.ts +94 -0
  168. package/tests/actions/setNetwork.test.ts +161 -0
  169. package/tests/actions/staking.test.ts +280 -0
  170. package/tests/actions/start.test.ts +257 -0
  171. package/tests/actions/stop.test.ts +77 -0
  172. package/tests/actions/unlock.test.ts +139 -0
  173. package/tests/actions/validators.test.ts +750 -0
  174. package/tests/actions/write.test.ts +102 -0
  175. package/tests/commands/account.test.ts +146 -0
  176. package/tests/commands/appeal.test.ts +97 -0
  177. package/tests/commands/call.test.ts +78 -0
  178. package/tests/commands/code.test.ts +69 -0
  179. package/tests/commands/config.test.ts +54 -0
  180. package/tests/commands/deploy.test.ts +83 -0
  181. package/tests/commands/init.test.ts +101 -0
  182. package/tests/commands/localnet.test.ts +131 -0
  183. package/tests/commands/network.test.ts +60 -0
  184. package/tests/commands/new.test.ts +68 -0
  185. package/tests/commands/parseArg.test.ts +156 -0
  186. package/tests/commands/receipt.test.ts +142 -0
  187. package/tests/commands/schema.test.ts +67 -0
  188. package/tests/commands/staking.test.ts +329 -0
  189. package/tests/commands/stop.test.ts +27 -0
  190. package/tests/commands/up.test.ts +105 -0
  191. package/tests/commands/update.test.ts +45 -0
  192. package/tests/commands/write.test.ts +76 -0
  193. package/tests/index.test.ts +56 -0
  194. package/tests/libs/baseAction.test.ts +535 -0
  195. package/tests/libs/configFileManager.test.ts +118 -0
  196. package/tests/libs/jsonRpcClient.test.ts +59 -0
  197. package/tests/libs/keychainManager.test.ts +156 -0
  198. package/tests/libs/platformCommands.test.ts +78 -0
  199. package/tests/libs/system.test.ts +148 -0
  200. package/tests/services/simulator.test.ts +789 -0
  201. package/tests/smoke.test.ts +134 -0
  202. package/tests/utils.ts +13 -0
  203. package/tsconfig.json +120 -0
  204. package/vitest.config.ts +13 -0
  205. package/vitest.smoke.config.ts +17 -0
@@ -0,0 +1,128 @@
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";
6
+
7
+ export interface StartActionOptions {
8
+ resetValidators: boolean;
9
+ numValidators: number;
10
+ headless: boolean;
11
+ resetDb: boolean;
12
+ ollama: boolean;
13
+ }
14
+
15
+ export class StartAction extends BaseAction {
16
+ private simulatorService: ISimulatorService;
17
+
18
+ constructor() {
19
+ super();
20
+ this.simulatorService = new SimulatorService();
21
+ }
22
+
23
+ async execute(options: StartActionOptions) {
24
+ const {resetValidators, numValidators, headless, resetDb, ollama} = options;
25
+
26
+ this.simulatorService.setComposeOptions(headless, ollama);
27
+ this.startSpinner("Checking CLI version...");
28
+ await this.simulatorService.checkCliVersion();
29
+
30
+ this.setSpinnerText("Checking Docker...");
31
+ try {
32
+ await this.simulatorService.ensureDockerRunning();
33
+ } catch (error) {
34
+ this.failSpinner(
35
+ "Docker is not running. Please start Docker Desktop and try again.",
36
+ error,
37
+ );
38
+ return;
39
+ }
40
+
41
+ const isRunning = await this.simulatorService.isLocalnetRunning();
42
+ if (isRunning) {
43
+ this.stopSpinner();
44
+ await this.confirmPrompt("GenLayer Localnet is already running. Do you want to proceed?");
45
+ this.startSpinner("Stopping Docker containers...");
46
+ await this.simulatorService.stopDockerContainers();
47
+ }
48
+
49
+ const restartValidatorsHintText = resetValidators
50
+ ? `creating new ${numValidators} random validators`
51
+ : "keeping the existing validators";
52
+ this.setSpinnerText(`Starting GenLayer Localnet (${restartValidatorsHintText})...`);
53
+
54
+ try {
55
+ this.simulatorService.setupLocalhostAccess();
56
+ await this.simulatorService.runSimulator();
57
+ } catch (error) {
58
+ this.failSpinner("Error starting the simulator", error);
59
+ return;
60
+ }
61
+
62
+ try {
63
+ this.setSpinnerText("Waiting for the simulator to be ready...");
64
+ const {initialized, errorCode, errorMessage} = await this.simulatorService.waitForSimulatorToBeReady();
65
+
66
+ if (!initialized) {
67
+ if (errorCode === "ERROR") {
68
+ this.failSpinner("Unable to initialize the GenLayer simulator.", errorMessage);
69
+ return;
70
+ }
71
+ if (errorCode === "TIMEOUT") {
72
+ this.failSpinner("The simulator is taking too long to initialize. Please try again later.");
73
+ return;
74
+ }
75
+ }
76
+ } catch (error) {
77
+ this.failSpinner("Error waiting for the simulator to be ready", error);
78
+ return;
79
+ }
80
+
81
+ if (resetDb) {
82
+ this.setSpinnerText("Resetting database...");
83
+ await this.simulatorService.cleanDatabase();
84
+ }
85
+
86
+ if (resetValidators) {
87
+ this.setSpinnerText("Initializing validators...");
88
+ try {
89
+ await this.simulatorService.deleteAllValidators();
90
+
91
+ const questions: DistinctQuestion[] = [
92
+ {
93
+ type: "checkbox",
94
+ name: "selectedLlmProviders",
95
+ message: "Select which LLM providers do you want to use:",
96
+ choices: this.simulatorService.getAiProvidersOptions(false, ollama ? [] : ["ollama"]),
97
+ validate: answer => (answer.length < 1 ? "You must choose at least one option." : true),
98
+ },
99
+ ];
100
+
101
+ const llmProvidersAnswer = await inquirer.prompt(questions);
102
+ await this.simulatorService.createRandomValidators(
103
+ numValidators,
104
+ llmProvidersAnswer.selectedLlmProviders,
105
+ );
106
+ } catch (error) {
107
+ this.failSpinner("Unable to initialize the validators", error);
108
+ return;
109
+ }
110
+ }
111
+
112
+ let successMessage = "GenLayer simulator initialized successfully! ";
113
+ successMessage += headless
114
+ ? ""
115
+ : `Go to ${this.simulatorService.getFrontendUrl()} in your browser to access it.`;
116
+ this.succeedSpinner(successMessage);
117
+
118
+ if (!headless) {
119
+ try {
120
+ this.startSpinner("Opening frontend...");
121
+ await this.simulatorService.openFrontend();
122
+ this.succeedSpinner("Frontend opened successfully");
123
+ } catch (error) {
124
+ this.failSpinner("Error opening the frontend", error);
125
+ }
126
+ }
127
+ }
128
+ }
@@ -0,0 +1,26 @@
1
+ import { BaseAction } from "../../lib/actions/BaseAction";
2
+ import { SimulatorService } from "../../lib/services/simulator";
3
+ import { ISimulatorService } from "../../lib/interfaces/ISimulatorService";
4
+
5
+ export class StopAction extends BaseAction {
6
+ private simulatorService: ISimulatorService;
7
+
8
+ constructor() {
9
+ super();
10
+ this.simulatorService = new SimulatorService();
11
+ }
12
+
13
+ public async stop(): Promise<void> {
14
+ try {
15
+ await this.confirmPrompt(
16
+ "Are you sure you want to stop all running GenLayer containers? This will halt all active processes."
17
+ );
18
+
19
+ this.startSpinner("Stopping Docker containers...");
20
+ await this.simulatorService.stopDockerContainers();
21
+ this.succeedSpinner("All running GenLayer containers have been successfully stopped.");
22
+ } catch (error) {
23
+ this.failSpinner("An error occurred while stopping the containers.", error);
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,100 @@
1
+ import { Command } from "commander";
2
+ import { ValidatorsAction } from "./validators";
3
+
4
+ export function initializeValidatorCommands(program: Command) {
5
+ const validatorsAction = new ValidatorsAction();
6
+
7
+ const localnetCommand = program
8
+ .command("localnet")
9
+ .description("Manage localnet operations");
10
+
11
+ const validatorsCommand = localnetCommand
12
+ .command("validators")
13
+ .description("Manage localnet validators operations");
14
+
15
+ validatorsCommand
16
+ .command("get")
17
+
18
+ .description("Retrieve details of a specific validator or all validators")
19
+ .option("--address <validatorAddress>", "The address of the validator to retrieve (omit to retrieve all validators)")
20
+ .action(async (options) => {
21
+ await validatorsAction.getValidator({ address: options.address });
22
+ });
23
+
24
+ validatorsCommand
25
+ .command("delete")
26
+ .description("Delete a specific validator or all validators")
27
+ .option("--address <validatorAddress>", "The address of the validator to delete (omit to delete all validators)")
28
+ .action(async (options) => {
29
+ await validatorsAction.deleteValidator({ address: options.address });
30
+ });
31
+
32
+ validatorsCommand
33
+ .command("count")
34
+ .description("Count all validators")
35
+ .action(async () => {
36
+ await validatorsAction.countValidators();
37
+ });
38
+
39
+ validatorsCommand
40
+ .command("update <validatorAddress>")
41
+ .description("Update a validator's details")
42
+ .option("--stake <stake>", "New stake for the validator")
43
+ .option("--provider <provider>", "New provider for the validator")
44
+ .option("--model <model>", "New model for the validator")
45
+ .option("--config <config>", "New JSON config for the validator")
46
+ .action(async (validatorAddress, options) => {
47
+ await validatorsAction.updateValidator({
48
+ address: validatorAddress,
49
+ stake: options.stake,
50
+ provider: options.provider,
51
+ model: options.model,
52
+ config: options.config,
53
+ });
54
+ });
55
+
56
+ validatorsCommand
57
+ .command("create-random")
58
+ .description("Create random validators")
59
+ .option("--count <count>", "Number of validators to create", "1") // Default to "1"
60
+ .option(
61
+ "--providers <providers...>",
62
+ "Space-separated list of provider names (e.g., openai ollama)",
63
+ []
64
+ )
65
+ .option(
66
+ "--models <models...>",
67
+ "Space-separated list of model names (e.g., gpt-4 gpt-4o)",
68
+ []
69
+ )
70
+ .action(async (options) => {
71
+ await validatorsAction.createRandomValidators({
72
+ count: options.count,
73
+ providers: options.providers,
74
+ models: options.models,
75
+ });
76
+ });
77
+
78
+ validatorsCommand
79
+ .command("create")
80
+ .description("Create a new validator")
81
+ .option("--stake <stake>", "Stake amount for the validator (default: 1)", "1")
82
+ .option(
83
+ "--config <config>",
84
+ `Optional JSON configuration for the validator (e.g., '{"max_tokens": 500, "temperature": 0.75}')`
85
+ )
86
+ .option("--provider <provider>", "Specify the provider for the validator")
87
+ .option("--model <model>", "Specify the model for the validator")
88
+ .action(async (options) => {
89
+ await validatorsAction.createValidator({
90
+ stake: options.stake,
91
+ config: options.config,
92
+ provider: options.provider,
93
+ model: options.model,
94
+ });
95
+ });
96
+
97
+ return program;
98
+ }
99
+
100
+
@@ -0,0 +1,269 @@
1
+ import inquirer from "inquirer";
2
+ import { rpcClient } from "../../lib/clients/jsonRpcClient";
3
+ import { BaseAction } from "../../lib/actions/BaseAction";
4
+
5
+ export interface ValidatorOptions {
6
+ address?: string;
7
+ }
8
+
9
+ export interface UpdateValidatorOptions {
10
+ address: string;
11
+ stake?: string;
12
+ provider?: string;
13
+ model?: string;
14
+ config?: string;
15
+ }
16
+
17
+ export interface CreateRandomValidatorsOptions {
18
+ count: string;
19
+ providers: string[];
20
+ models: string[];
21
+ }
22
+
23
+ export interface CreateValidatorOptions {
24
+ stake: string;
25
+ config?: string;
26
+ model?: string;
27
+ provider?: string;
28
+ }
29
+
30
+ export class ValidatorsAction extends BaseAction {
31
+ public async getValidator(options: ValidatorOptions): Promise<void> {
32
+ try {
33
+ if (options.address) {
34
+ this.startSpinner(`Fetching validator with address: ${options.address}`);
35
+
36
+ const result = await rpcClient.request({
37
+ method: "sim_getValidator",
38
+ params: [options.address],
39
+ });
40
+
41
+ this.succeedSpinner(`Successfully fetched validator with address: ${options.address}`, result.result);
42
+ } else {
43
+ this.startSpinner(`Fetching all validators...`);
44
+
45
+ const result = await rpcClient.request({
46
+ method: "sim_getAllValidators",
47
+ params: [],
48
+ });
49
+ this.succeedSpinner('Successfully fetched all validators.', result.result)
50
+ }
51
+ } catch (error) {
52
+ this.failSpinner("Error fetching validators", error);
53
+ }
54
+ }
55
+
56
+ public async deleteValidator(options: ValidatorOptions): Promise<void> {
57
+ try {
58
+ if (options.address) {
59
+ await this.confirmPrompt(`This command will delete the validator with the address: ${options.address}. Do you want to continue?`);
60
+ this.startSpinner(`Deleting validator with address: ${options.address}`);
61
+
62
+ const result = await rpcClient.request({
63
+ method: "sim_deleteValidator",
64
+ params: [options.address],
65
+ });
66
+
67
+ this.succeedSpinner(`Deleted Address: ${result.result}`);
68
+ } else {
69
+ await this.confirmPrompt(`This command will delete all validators. Do you want to continue?`);
70
+ this.startSpinner("Deleting all validators...");
71
+
72
+ await rpcClient.request({
73
+ method: "sim_deleteAllValidators",
74
+ params: [],
75
+ });
76
+
77
+ this.succeedSpinner("Successfully deleted all validators");
78
+ }
79
+ } catch (error) {
80
+ this.failSpinner("Error deleting validators", error);
81
+ }
82
+ }
83
+
84
+ public async countValidators(): Promise<void> {
85
+ try {
86
+ this.startSpinner("Counting all validators...");
87
+
88
+ const result = await rpcClient.request({
89
+ method: "sim_countValidators",
90
+ params: [],
91
+ });
92
+ this.succeedSpinner(`Total Validators: ${result.result}`);
93
+ } catch (error) {
94
+ this.failSpinner("Error counting validators", error);
95
+ }
96
+ }
97
+
98
+ public async updateValidator(options: UpdateValidatorOptions): Promise<void> {
99
+ try {
100
+ this.startSpinner(`Fetching validator with address: ${options.address}...`);
101
+ const currentValidator = await rpcClient.request({
102
+ method: "sim_getValidator",
103
+ params: [options.address],
104
+ });
105
+
106
+ this.log("Current Validator Details:", currentValidator.result);
107
+
108
+ const parsedStake = options.stake
109
+ ? parseInt(options.stake, 10)
110
+ : currentValidator.result.stake;
111
+
112
+ if (isNaN(parsedStake) || parsedStake < 0) {
113
+ return this.failSpinner("Invalid stake value. Stake must be a positive integer.");
114
+ }
115
+
116
+ const updatedValidator = {
117
+ address: options.address,
118
+ stake: options.stake || currentValidator.result.stake,
119
+ provider: options.provider || currentValidator.result.provider,
120
+ model: options.model || currentValidator.result.model,
121
+ config: options.config ? JSON.parse(options.config) : currentValidator.result.config,
122
+ };
123
+
124
+ this.log("Updated Validator Details:", updatedValidator);
125
+
126
+ this.setSpinnerText('Updating Validator...');
127
+
128
+ const result = await rpcClient.request({
129
+ method: "sim_updateValidator",
130
+ params: [
131
+ updatedValidator.address,
132
+ updatedValidator.stake,
133
+ updatedValidator.provider,
134
+ updatedValidator.model,
135
+ updatedValidator.config,
136
+ ],
137
+ });
138
+
139
+ this.succeedSpinner("Validator successfully updated", result.result);
140
+ } catch (error) {
141
+ this.failSpinner("Error updating validator", error);
142
+ }
143
+ }
144
+
145
+ public async createRandomValidators(options: CreateRandomValidatorsOptions): Promise<void> {
146
+ try {
147
+ const count = parseInt(options.count, 10);
148
+ if (isNaN(count) || count < 1) {
149
+ return this.logError("Invalid count. Please provide a positive integer.");
150
+ }
151
+
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"}`);
155
+
156
+ const result = await rpcClient.request({
157
+ method: "sim_createRandomValidators",
158
+ params: [count, 1, 10, options.providers, options.models],
159
+ });
160
+
161
+ this.succeedSpinner("Random validators successfully created", result.result);
162
+ } catch (error) {
163
+ this.failSpinner("Error creating random validators", error);
164
+ }
165
+ }
166
+
167
+ public async createValidator(options: CreateValidatorOptions): Promise<void> {
168
+ try {
169
+ const stake = parseInt(options.stake, 10);
170
+ if (isNaN(stake) || stake < 1) {
171
+ return this.logError("Invalid stake. Please provide a positive integer.");
172
+ }
173
+
174
+ if (options.model && !options.provider) {
175
+ return this.logError("You must specify a provider if using a model.");
176
+ }
177
+
178
+ this.startSpinner("Fetching available providers and models...");
179
+
180
+ const providersAndModels = await rpcClient.request({
181
+ method: "sim_getProvidersAndModels",
182
+ params: [],
183
+ });
184
+ this.stopSpinner();
185
+
186
+ if (!providersAndModels.result || providersAndModels.result.length === 0) {
187
+ return this.logError("No providers or models available.");
188
+ }
189
+
190
+ const availableProviders = [
191
+ ...new Map(
192
+ providersAndModels.result
193
+ .filter((entry: any) => entry.is_available)
194
+ .map((entry: any) => [entry.provider, entry])
195
+ ).values(),
196
+ ];
197
+
198
+ let provider = options.provider
199
+
200
+ if(!provider){
201
+ const { selectedProvider } = await inquirer.prompt([
202
+ {
203
+ type: "list",
204
+ name: "selectedProvider",
205
+ message: "Select a provider:",
206
+ choices: availableProviders.map((entry: any) => entry.provider),
207
+ },
208
+ ]);
209
+
210
+ provider = selectedProvider;
211
+ }
212
+
213
+ const availableModels = providersAndModels.result.filter(
214
+ (entry: any) => entry.provider === provider && entry.is_model_available
215
+ );
216
+
217
+ if (availableModels.length === 0) {
218
+ return this.logError("No models available for the selected provider.");
219
+ }
220
+
221
+ let model = options.model;
222
+
223
+ if(!model){
224
+ const { selectedModel } = await inquirer.prompt([
225
+ {
226
+ type: "list",
227
+ name: "selectedModel",
228
+ message: "Select a model:",
229
+ choices: availableModels.map((entry: any) => entry.model),
230
+ },
231
+ ]);
232
+
233
+ model = selectedModel;
234
+ }
235
+
236
+ const modelDetails = availableModels.find(
237
+ (entry: any) => entry.model === model
238
+ );
239
+
240
+ if (!modelDetails) {
241
+ return this.logError("Selected model details not found.");
242
+ }
243
+
244
+ const config = options.config ? JSON.parse(options.config) : modelDetails.config;
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
+
257
+ const result = await rpcClient.request({
258
+ method: "sim_createValidator",
259
+ params,
260
+ });
261
+
262
+ this.succeedSpinner("Validator successfully created:", result.result);
263
+ } catch (error) {
264
+ this.failSpinner("Error creating validator", error);
265
+ }
266
+ }
267
+ }
268
+
269
+
@@ -0,0 +1,29 @@
1
+ import {Command} from "commander";
2
+ import {NetworkActions} from "./setNetwork";
3
+
4
+ export function initializeNetworkCommands(program: Command) {
5
+ const networkActions = new NetworkActions();
6
+
7
+ const network = program.command("network").description("Network configuration");
8
+
9
+ // genlayer network set [name]
10
+ network
11
+ .command("set")
12
+ .description("Set the network to use")
13
+ .argument("[network]", "The network to set")
14
+ .action((networkName?: string) => networkActions.setNetwork(networkName));
15
+
16
+ // genlayer network info
17
+ network
18
+ .command("info")
19
+ .description("Show current network configuration and contract addresses")
20
+ .action(() => networkActions.showInfo());
21
+
22
+ // genlayer network list
23
+ network
24
+ .command("list")
25
+ .description("List available networks")
26
+ .action(() => networkActions.listNetworks());
27
+
28
+ return program;
29
+ }
@@ -0,0 +1,77 @@
1
+ import {BaseAction, BUILT_IN_NETWORKS, resolveNetwork} from "../../lib/actions/BaseAction";
2
+ import inquirer, {DistinctQuestion} from "inquirer";
3
+
4
+ const networks = Object.entries(BUILT_IN_NETWORKS).map(([alias, network]) => ({
5
+ name: network.name,
6
+ alias,
7
+ value: network,
8
+ }));
9
+
10
+ export class NetworkActions extends BaseAction {
11
+ constructor() {
12
+ super();
13
+ }
14
+
15
+ async showInfo(): Promise<void> {
16
+ const storedNetwork = this.getConfigByKey("network") || "localnet";
17
+ const network = resolveNetwork(storedNetwork);
18
+
19
+ const info: Record<string, string> = {
20
+ alias: storedNetwork,
21
+ name: network.name,
22
+ chainId: network.id?.toString() || "unknown",
23
+ rpc: network.rpcUrls?.default?.http?.[0] || "unknown",
24
+ mainContract: network.consensusMainContract?.address || "not set",
25
+ stakingContract: network.stakingContract?.address || "not set",
26
+ };
27
+
28
+ if (network.blockExplorers?.default?.url) {
29
+ info.explorer = network.blockExplorers.default.url;
30
+ }
31
+
32
+ this.succeedSpinner("Current network", info);
33
+ }
34
+
35
+ async listNetworks(): Promise<void> {
36
+ const currentNetwork = this.getConfigByKey("network") || "localnet";
37
+
38
+ console.log("");
39
+ for (const net of networks) {
40
+ const marker = net.alias === currentNetwork ? "*" : " ";
41
+ console.log(`${marker} ${net.alias.padEnd(16)} ${net.name}`);
42
+ }
43
+ console.log("");
44
+ }
45
+
46
+ async setNetwork(networkName?: string): Promise<void> {
47
+ if (networkName || networkName === "") {
48
+ if (!networks.some(n => n.name === networkName || n.alias === networkName)) {
49
+ this.failSpinner(`Network ${networkName} not found`);
50
+ return;
51
+ }
52
+ const selectedNetwork = networks.find(n => n.name === networkName || n.alias === networkName);
53
+ if (!selectedNetwork) {
54
+ this.failSpinner(`Network ${networkName} not found`);
55
+ return;
56
+ }
57
+ this.writeConfig("network", selectedNetwork.alias);
58
+ this.succeedSpinner(`Network successfully set to ${selectedNetwork.name}`);
59
+ return;
60
+ }
61
+
62
+ const networkQuestions: DistinctQuestion[] = [
63
+ {
64
+ type: "list",
65
+ name: "selectedNetwork",
66
+ message: "Select which network do you want to use:",
67
+ choices: networks.map(n => ({name: n.name, value: n.alias})),
68
+ },
69
+ ];
70
+ const networkAnswer = await inquirer.prompt(networkQuestions);
71
+ const selectedAlias = networkAnswer.selectedNetwork;
72
+ const selectedNetwork = networks.find(n => n.alias === selectedAlias)!;
73
+
74
+ this.writeConfig("network", selectedAlias);
75
+ this.succeedSpinner(`Network successfully set to ${selectedNetwork.name}`);
76
+ }
77
+ }
@@ -0,0 +1,16 @@
1
+ import { Command } from "commander";
2
+ import { NewAction } from "./new";
3
+
4
+ export function initializeScaffoldCommands(program: Command) {
5
+ program
6
+ .command("new <projectName>")
7
+ .description("Create a new GenLayer project using the default template")
8
+ .option("--path <directory>", "Specify the directory for the new project", ".")
9
+ .option("--overwrite", "Overwrite existing directory if it exists", false)
10
+ .action(async (projectName, options) => {
11
+ const newProjectAction = new NewAction();
12
+ await newProjectAction.createProject(projectName, options);
13
+ });
14
+
15
+ return program;
16
+ }
@@ -0,0 +1,34 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ import { BaseAction } from "../../lib/actions/BaseAction";
5
+
6
+ export class NewAction extends BaseAction {
7
+ private templatePath: string;
8
+
9
+ constructor() {
10
+ super();
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const basePath = path.resolve(path.dirname(__filename), "..");
13
+ this.templatePath = path.join(basePath, "templates", "default");
14
+ }
15
+
16
+ async createProject(projectName: string, options: { path: string; overwrite: boolean }) {
17
+ const targetPath = path.resolve(options.path, projectName);
18
+
19
+ if (fs.existsSync(targetPath) && !options.overwrite) {
20
+ return this.failSpinner(
21
+ `Project directory "${targetPath}" already exists. Use --overwrite to replace it.`
22
+ );
23
+ }
24
+
25
+ this.startSpinner(`Creating new GenLayer project: ${projectName}`);
26
+
27
+ try {
28
+ fs.copySync(this.templatePath, targetPath);
29
+ this.succeedSpinner(`Project "${projectName}" created successfully at ${targetPath}`);
30
+ } catch (error) {
31
+ this.failSpinner(`Error creating project "${projectName}"`, error);
32
+ }
33
+ }
34
+ }