Skip to content

feat: rename studio validators commands - #249

Merged
cristiam86 merged 10 commits into
mainfrom
dxp-600-rename-studio-validators-commands
Sep 3, 2025
Merged

cristiam86 merged 10 commits into
mainfrom
dxp-600-rename-studio-validators-commands

Conversation

@epsjunior

@epsjunior epsjunior commented Aug 27, 2025 •

Copy link
Copy Markdown
Contributor

Rename Validators Commands to Localnet Namespace

Summary

Moves existing Studio validators CLI commands under a new localnet namespace to avoid confusion with upcoming testnet validators. Commands are now accessed via genlayer localnet validators ....

Changes

🚀 Command Namespace Update

  • New hierarchy: genlayer localnet validators <subcommand>
  • Subcommands: get, delete, count, update, create, create-random

🔧 Implementation Details

  • Introduced src/commands/localnet with validators command group and actions
  • Removed legacy src/commands/validators folder
  • Updated CLI bootstrap to initialize localnet commands
  • Updated tests to reflect the new command path

📁 File Structure

src/
├── commands/
│   ├── localnet/
│   │   ├── index.ts        # Registers `localnet validators` commands
│   │   └── validators.ts   # ValidatorsAction (moved from validators/)
│   └── index.ts            # Updated to initialize localnet commands

tests/
├── actions/
│   └── validators.test.ts  # Updated imports to localnet/validators
└── commands/
    └── localnet.test.ts    # New tests for `localnet validators` command group

🏗️ Command Architecture

  • Group: localnet
  • Subgroup: validators
  • Commands:
    • get --address <address>
    • delete [--address <address>]
    • count
    • update <address> [--stake <n>] [--provider <name>] [--model <name>] [--config <json>]
    • create [--stake <n>] [--provider <name>] [--model <name>] [--config <json>]
    • create-random --count <n> [--providers <...>] [--models <...>]

🧪 Testing

  • Updated command tests: tests/commands/localnet.test.ts
  • Updated action tests: tests/actions/validators.test.ts (import path)
  • CLI index tests updated to mock localnet initializer
  • All tests pass locally with coverage

🔧 Usage

# List all validators
genlayer localnet validators get

# Get validator by address
genlayer localnet validators get --address 0xabc

# Create a validator
genlayer localnet validators create --stake 5 --provider openai --model gpt-4

# Update a validator
genlayer localnet validators update 0xabc --stake 10 --config '{"max_tokens":1000}'

✨ Code Quality

  • Consistent action pattern (BaseAction)
  • Clear command registration and options
  • TypeScript throughout with maintained types
  • Error handling preserved (spinners, fail/succeed)

🔗 Dependencies

  • Reuses existing simulator RPC client and BaseAction infrastructure
  • No new external dependencies

🛡️ Backward Compatibility

  • Breaking change: old root-level validators commands replaced by localnet validators
  • All functionality preserved under new namespace

Testing: ✅ All tests pass
Type Safety: ✅ TypeScript maintained
UX: ✅ Clear namespace separation for localnet vs testnet

Summary by CodeRabbit

  • New Features

    • Adds a top-level CLI command: localnet for managing local network operations.
  • Refactor

    • Validators commands are now nested under localnet (use: localnet validators ...).
    • Improved --config option description for validator commands.
  • Tests

    • Test suites updated to target the new localnet CLI namespace.
  • Documentation

    • README updated to use genlayer localnet validators command examples.

@coderabbitai

coderabbitai Bot commented Aug 27, 2025 •

Copy link
Copy Markdown

Walkthrough

Introduces a new top-level CLI namespace "localnet" and nests the existing "validators" subcommand under it. Adjusts imports to reference the new module path, updates tests and README to use the "localnet" command hierarchy, and applies a minor formatting tweak in validators.ts. No functional changes to ValidatorsAction or command signatures.

Changes

Cohort / File(s) Summary of changes
CLI command restructuring
src/commands/localnet/index.ts
Adds top-level localnet command and moves validators under it. Updates --config option description formatting. Control flow shifts from program.validators to program.localnet.validators.
Validators action formatting
src/commands/localnet/validators.ts
Minor formatting: adds two blank lines after the ValidatorsAction class closing brace; no functional changes.
Root CLI wiring
src/index.ts
Redirects import of initializeValidatorCommands to ./commands/localnet (was ./commands/validators); initialization call unchanged.
Tests: actions
tests/actions/validators.test.ts
Updates import path to ../../src/commands/localnet/validators; test logic and expectations unchanged.
Tests: command namespace
tests/commands/localnet.test.ts
Updates tests to invoke localnet validators ..., imports from src/commands/localnet/..., and updates describe text; no behavioral changes.
Tests: index wiring
tests/index.test.ts
Mocks/stubs initializeValidatorCommands from src/commands/localnet instead of src/commands/validators; test structure unchanged.
Documentation
README.md
Updates documentation and examples to use genlayer localnet validators ... and renames header/description to "Localnet Validator Management"; semantics unchanged.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as CLI User
  participant P as Program (CLI)
  participant L as Localnet Command
  participant V as ValidatorsAction

  U->>P: run "genlayer localnet validators [args]"
  P->>L: dispatch to localnet namespace
  L->>V: invoke validators subcommand handler
  V-->>U: return output / status
  note right of L: New nesting: validators now under localnet
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

In burrows of code, I twitch my nose,
"localnet" springs where the command tree grows.
Validators hop to their brand-new nest,
Paths adjusted, tidy and dressed.
I stamp my paw — ready for the test. 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 75b0b9a and f5c3841.

📒 Files selected for processing (1)
  • README.md (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • README.md
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dxp-600-rename-studio-validators-commands

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (8)
src/commands/localnet/validators.ts (2)

108-121: Normalize stake type in updateValidator (align with createValidator).

createValidator sends a numeric stake; updateValidator validates numerically but forwards a string when provided. Standardize to number to avoid RPC/type drift.

-  const parsedStake = options.stake
-    ? parseInt(options.stake, 10)
-    : currentValidator.result.stake;
+  const parsedStake = options.stake != null
+    ? parseInt(options.stake, 10)
+    : currentValidator.result.stake;

   if (isNaN(parsedStake) || parsedStake < 0) {
     return this.failSpinner("Invalid stake value. Stake must be a positive integer.");
   }

   const updatedValidator = {
     address: options.address,
-    stake: options.stake || currentValidator.result.stake,
+    stake: parsedStake,
     provider: options.provider || currentValidator.result.provider,
     model: options.model || currentValidator.result.model,
     config: options.config ? JSON.parse(options.config) : currentValidator.result.config,
   };

If the simulator expects strings here, keep current behavior and update createValidator to also send a string for consistency instead. Please confirm the expected RPC types.

Also applies to: 128-137


156-159: Avoid magic numbers in createRandomValidators.

Expose min/max stake as flags or constants to make behavior explicit and configurable.

+const DEFAULT_MIN_STAKE = 1;
+const DEFAULT_MAX_STAKE = 10;
 ...
-  params: [count, 1, 10, options.providers, options.models],
+  params: [count, DEFAULT_MIN_STAKE, DEFAULT_MAX_STAKE, options.providers, options.models],
src/index.ts (1)

9-9: Good rewire to localnet initializer; consider a temporary deprecation alias.

To smooth the breaking change, add a root-level "validators" alias that prints a deprecation notice guiding users to localnet validators ....

Example (in your command wiring, not necessarily this file):

program
  .command("validators")
  .allowUnknownOption()
  .action(() => {
    console.error("The 'validators' commands moved under 'localnet'. Use: genlayer localnet validators <subcommand>");
    process.exitCode = 1;
  });
tests/commands/localnet.test.ts (1)

3-129: Wiring tests updated to cover the new 'localnet validators' path — LGTM.

End-to-end command argument plumbing remains validated via Commander parsing and method spy assertions. If you add the deprecation alias, consider a small test asserting the notice for root-level validators.

src/commands/localnet/index.ts (4)

7-14: Add a deprecation shim for root-level validators to reduce breakage

Provide a transitional alias that surfaces a clear migration message if users invoke the old entrypoint.

   const validatorsCommand = localnetCommand
     .command("validators")
     .description("Manage localnet validators operations");
+
+  // Back-compat shim for renamed validators commands (remove in next major)
+  program
+    .command("validators")
+    .description("This command moved under 'localnet'.")
+    .allowUnknownOption(true)
+    .action(() => {
+      program.error("Use: genlayer localnet validators <subcommand>");
+    });

24-31: Guard destructive delete: require explicit --all when no --address

Prevents accidental mass-deletion while preserving current behavior when --all is supplied.

   validatorsCommand
     .command("delete")
     .description("Delete a specific validator or all validators")
     .option("--address <validatorAddress>", "The address of the validator to delete (omit to delete all validators)")
-    .action(async (options) => {
-      await validatorsAction.deleteValidator({ address: options.address });
-    });
+    .option("--all", "Delete ALL validators")
+    .action(async (options, cmd) => {
+      if (!options.address && !options.all) {
+        cmd.error("Refusing to delete all validators without --all. Provide --address or --all.");
+      }
+      await validatorsAction.deleteValidator({ address: options.address });
+    });

82-85: Validate --config as JSON at parse time; improve shell-agnostic example

Early validation gives better UX; the example uses escaped double quotes to work across shells.

-    .option(
-      "--config <config>",
-      `Optional JSON configuration for the validator (e.g., '{"max_tokens": 500, "temperature": 0.75}')`
-    )
+    .addOption(
+      new Option("--config <config>", "Optional JSON configuration for the validator (e.g., {\"max_tokens\": 500, \"temperature\": 0.75})")
+        .argParser((s) => {
+          try { JSON.parse(s); return s; } catch { throw new InvalidArgumentError("Invalid JSON for --config"); }
+        })
+    )

Apply import update outside this hunk if not already done:

import { Command, Option, InvalidArgumentError } from "commander";

59-76: Validate and parse --count as a positive integer at the CLI boundary

Shifting the count parsing into Commander’s argParser will turn options.count into a number instead of a string, which is a worthwhile improvement—but it also means downstream code and tests must be updated to expect a numeric count.

• In src/commands/localnet/index.ts

  • Replace the .option("--count <count>", …) call with the new Option() + .argParser() + .default(1) form.
  • Update imports to include Option and InvalidArgumentError.

• In src/commands/localnet/validators.ts

  • Change the CreateRandomValidatorsOptions.count type from string to number.
  • Remove the in-method parseInt(options.count, 10) and its NaN/<1 guards (Commander will have already enforced validity).

• In tests/actions/validators.test.ts

  • Update all invocations of createRandomValidators({ count: "…" }) to pass a number literal, e.g. { count: 5 }.
  • Adjust the “invalid count” test to assert that Commander rejects non-numeric values (e.g. invoking the CLI with --count invalid throws an InvalidArgumentError).

Example diff for the CLI change in src/commands/localnet/index.ts:

-import { Command } from "commander";
+import { Command, Option, InvalidArgumentError } from "commander";

 command
-  .option("--count <count>", "Number of validators to create", "1")
+  .addOption(
+    new Option("--count <count>", "Number of validators to create")
+      .argParser((v: string) => {
+        const n = parseInt(v, 10);
+        if (!Number.isFinite(n) || n < 1) {
+          throw new InvalidArgumentError("--count must be a positive integer");
+        }
+        return n;
+      })
+      .default(1)
+  )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b2f0e99 and 75b0b9a.

📒 Files selected for processing (6)
  • src/commands/localnet/index.ts (3 hunks)
  • src/commands/localnet/validators.ts (1 hunks)
  • src/index.ts (1 hunks)
  • tests/actions/validators.test.ts (1 hunks)
  • tests/commands/localnet.test.ts (7 hunks)
  • tests/index.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/commands/localnet.test.ts (1)
src/commands/localnet/validators.ts (1)
  • ValidatorsAction (30-267)
🔇 Additional comments (5)
src/commands/localnet/validators.ts (1)

268-269: No-op formatting change.

Safe whitespace-only change.

tests/actions/validators.test.ts (1)

2-2: Import path update looks correct.

Tests now target the relocated ValidatorsAction under localnet.

tests/index.test.ts (1)

28-30: Mocks updated to new module — OK.

Keeps the CLI init test green after the namespace move.

src/commands/localnet/index.ts (2)

11-14: LGTM: nesting validators under localnet

The namespacing is clear and aligns with the upcoming testnet split. No functional concerns here.


39-55: No additional stake validation needed in CLI

The validatorsAction.updateValidator method already parses and validates the incoming stake string, rejecting non-numeric or non-positive values and surface errors via failSpinner (covered by the “should log an error for invalid stake value” test in tests/actions/validators.test.ts) . Since the CLI simply forwards options.stake as a string to that layer, no extra parsing or validation is required in index.ts.

@cristiam86
cristiam86 merged commit fb875e5 into main Sep 3, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants