Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@MuncleUscles
Copy link
Member

@MuncleUscles MuncleUscles commented Dec 2, 2025

Adds staking commands, account management, and documentation for validator and delegator operations.

This commit introduces the staking functionality to the GenLayer CLI, enabling users to participate in the testnet-asimov staking program. It includes commands for validators to join, deposit, exit, and claim rewards, as well as commands for delegators to join, exit, and claim rewards.

Also includes account management commands for creating, unlocking, and locking accounts, and updates the README with usage examples and links to the new validator and delegator guides.

Summary by CodeRabbit

  • New Features

    • Account management CLI: create, import, show, send, unlock, lock (replaces prior keypair workflow)
    • Full staking suite: validator & delegator commands (join, deposit, exit, claim, prime, set-identity/operator, info)
  • Enhancements

    • Improved network selection (alias-based) and more robust network resolution
    • Transaction UX improvements and clearer account/status messages
  • Documentation

    • New validator and delegator guides and README updates with examples and staking workflows

✏️ Tip: You can customize this high-level summary in your review settings.

Adds staking commands, account management, and documentation for validator and delegator operations.

This commit introduces the staking functionality to the GenLayer CLI, enabling users to participate in the testnet-asimov staking program.  It includes commands for validators to join, deposit, exit, and claim rewards, as well as commands for delegators to join, exit, and claim rewards.

Also includes account management commands for creating, unlocking, and locking accounts, and updates the README with usage examples and links to the new validator and delegator guides.
@coderabbitai
Copy link

coderabbitai bot commented Dec 2, 2025

Walkthrough

Replaces keygen commands with account-focused CLI, adds comprehensive staking commands (validator/delegator actions and info queries), introduces alias-based network resolution, updates tests and docs (accounts, staking, guides), and adjusts core BaseAction keystore/network handling and package dependency versions.

Changes

Cohort / File(s) Summary
Documentation
CLAUDE.md, README.md, docs/delegator-guide.md, docs/validator-guide.md
Added CLAUDE guide; renamed keypair → account sections; added staking operations and guides; expanded examples and run-from-source instructions; no code changes.
Account Commands
src/commands/account/*
src/commands/account/create.ts, src/commands/account/import.ts, src/commands/account/show.ts, src/commands/account/send.ts, src/commands/account/unlock.ts, src/commands/account/lock.ts, src/commands/account/index.ts
Added account command set: CreateAccountAction, ImportAccountAction, ShowAccountAction, SendAction; renamed unlock/lock classes to account-centric names; wired initializeAccountCommands.
Keygen Removal
src/commands/keygen/*
src/commands/keygen/create.ts, src/commands/keygen/index.ts
Removed legacy keygen module and exports (KeypairCreator, CreateKeypairOptions, initializeKeygenCommands).
Staking Commands
src/commands/staking/*
src/commands/staking/StakingAction.ts, src/commands/staking/index.ts, src/commands/staking/validatorJoin.ts, ...validator*.ts, src/commands/staking/delegatorJoin.ts, ...delegator*.ts, src/commands/staking/setIdentity.ts, src/commands/staking/setOperator.ts, src/commands/staking/stakingInfo.ts
Added staking framework and actions: StakingAction base, ValidatorJoin/Deposit/Exit/Claim/Prime, DelegatorJoin/Exit/Claim, SetIdentity, SetOperator, StakingInfo actions, and initializeStakingCommands.
Core Infrastructure
src/lib/actions/BaseAction.ts, src/commands/network/setNetwork.ts, src/index.ts
Introduced BUILT_IN_NETWORKS and resolveNetwork; changed network persistence to alias strings; refactored failSpinner exit behavior; replaced keygen wiring with account and staking initialization in CLI bootstrap.
Tests
tests/actions/*, tests/commands/*, tests/libs/*, tests/index.test.ts
Updated/added tests to reflect account commands and staking actions; removed keygen command tests; adjusted network tests to expect alias strings; added staking action tests; updated BaseAction tests for non-exiting failSpinner.
Package
package.json
Bumped genlayer-js dependency from ^0.16.0 → ^0.18.5.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • src/commands/account/send.ts — transaction construction, signing, nonce/gas handling, receipt polling.
  • src/commands/staking/stakingInfo.ts — data aggregation, epoch/unbonding timeline and reward projection math.
  • src/lib/actions/BaseAction.ts — resolveNetwork compatibility with prior stored JSON formats and failSpinner behavior.
  • Command wiring in src/commands/staking/index.ts — option mappings and correct action invocation.

Possibly related PRs

Suggested reviewers

  • cristiam86
  • danielrc888

Poem

"I hopped through code like fields of grain,
Swapped keygen burrows for accounts that reign,
Validators dance and delegators cheer,
Aliases hum and the chains draw near,
A rabbit nods — docs, tests, and staking clear!" 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: Implements staking functionality' accurately captures the primary objective of this changeset, which adds comprehensive staking commands for validators and delegators to the GenLayer CLI.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch edgars/asimov-phase-4

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51340fd and 8a26ae1.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-12T22:52:10.974Z
Learnt from: epsjunior
Repo: genlayerlabs/genlayer-cli PR: 248
File: package.json:67-67
Timestamp: 2025-08-12T22:52:10.974Z
Learning: genlayer-js v0.14.0 is a valid and published version on npm as of December 2024. The package has regular releases and v0.14.0 is the current latest version.

Applied to files:

  • package.json
📚 Learning: 2025-07-10T23:50:34.628Z
Learnt from: epsjunior
Repo: genlayerlabs/genlayer-cli PR: 239
File: package.json:60-66
Timestamp: 2025-07-10T23:50:34.628Z
Learning: In the genlayer-cli project, dotenv is used with manual parsing via dotenv.parse() rather than automatic loading via dotenv.config(), so warnings about implicit .env.local auto-loading changes in dotenv v17 are not applicable to this project.

Applied to files:

  • package.json
📚 Learning: 2025-09-03T13:20:22.582Z
Learnt from: epsjunior
Repo: genlayerlabs/genlayer-cli PR: 253
File: tests/actions/code.test.ts:78-84
Timestamp: 2025-09-03T13:20:22.582Z
Learning: In genlayer-cli, the CLI framework handles unhandled promise rejections globally, so errors outside try/catch blocks are still displayed to users appropriately.

Applied to files:

  • package.json
🔇 Additional comments (1)
package.json (1)

68-68: Correct genlayer-js version to v0.18.2; v0.18.5 does not exist on npm.

The specified version ^0.18.5 is not published on npm. The latest available version is v0.18.2. Update the dependency to use a valid version to prevent installation failures.

⛔ Skipped due to learnings
Learnt from: epsjunior
Repo: genlayerlabs/genlayer-cli PR: 248
File: package.json:67-67
Timestamp: 2025-08-12T22:52:10.974Z
Learning: genlayer-js v0.14.0 is a valid and published version on npm as of December 2024. The package has regular releases and v0.14.0 is the current latest version.
Learnt from: epsjunior
Repo: genlayerlabs/genlayer-cli PR: 239
File: package.json:60-66
Timestamp: 2025-07-10T23:50:34.628Z
Learning: In the genlayer-cli project, dotenv is used with manual parsing via dotenv.parse() rather than automatic loading via dotenv.config(), so warnings about implicit .env.local auto-loading changes in dotenv v17 are not applicable to this project.
Learnt from: epsjunior
Repo: genlayerlabs/genlayer-cli PR: 253
File: tests/actions/code.test.ts:78-84
Timestamp: 2025-09-03T13:20:22.582Z
Learning: In genlayer-cli, the CLI framework handles unhandled promise rejections globally, so errors outside try/catch blocks are still displayed to users appropriately.

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Updates network configuration to use aliases for built-in networks.

This change introduces a more robust and maintainable approach to handling network configurations within the application. It replaces the direct storage of network configurations as JSON strings with a system that uses aliases to reference built-in networks. This allows for easier management of network settings and ensures that the application always uses the most up-to-date configurations for known networks.

The key changes include:

- Introduction of `BUILT_IN_NETWORKS`: A centralized record that always resolves fresh from `genlayer-js`.
- `resolveNetwork` function: Handles resolution of stored network configs, supporting both new (alias) and old (JSON) formats for backwards compatibility.
- Updates to `setNetwork` command: Now stores network aliases instead of full JSON configurations.
- Usage of `resolveNetwork` in account and staking actions: Ensures consistent and up-to-date network configurations across the application.
This commit introduces a new "import" command to the account management suite.

The new command allows users to import an existing account into the application by providing a private key.  It prompts for the private key (if not provided as an option), validates it, encrypts it with a user-provided password, and saves the encrypted keystore to a file. The command includes options to specify the output path and overwrite existing files. It also handles password validation (minimum length) and confirmation, and removes the private key from the keychain after import.
@MuncleUscles MuncleUscles marked this pull request as ready for review December 3, 2025 22:28
@cursor
Copy link

cursor bot commented Dec 3, 2025

You have run out of free Bugbot PR reviews for this billing cycle. This will reset on January 26.

To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (10)
docs/delegator-guide.md (1)

54-63: Consider adding language specifiers to code blocks.

The fenced code block lacks a language identifier. Consider adding text or json to improve rendering:

-```
+```json
 {
   count: 6,
   validators: [

This also applies to code blocks at lines 101 and 138.

docs/validator-guide.md (1)

50-55: Clarify the self-transfer example.

The example shows transferring tokens to your own address, which is confusing. Consider either removing this example or clarifying that users should transfer from a different funded account.

Apply this diff:

-Transfer GEN tokens to your address. You can:
-- Use the faucet (if available)
-- Transfer from another account:
-  ```bash
-  genlayer account send <your-address> 50000gen
-  ```
+Transfer GEN tokens to your address:
+- Use the faucet (if available)
+- Transfer from another funded account using the send command
src/commands/network/setNetwork.ts (1)

7-23: Consider consolidating network definitions.

The networks array appears to duplicate the network definitions that exist in BUILT_IN_NETWORKS (mentioned in the AI summary for BaseAction.ts). Consider importing and reusing the centralized network configuration to maintain a single source of truth.

Based on the AI summary, the network resolution was centralized in BaseAction.ts. Consider refactoring to:

import { BUILT_IN_NETWORKS } from "../../lib/actions/BaseAction";

const networks = Object.entries(BUILT_IN_NETWORKS).map(([alias, network]) => ({
  name: network.name,
  alias,
  value: network,
}));
src/commands/account/show.ts (1)

38-41: Consider RPC endpoint configuration.

The createClient call doesn't accept an RPC endpoint override. While this is likely intentional for a read-only show command, consider whether users might want to query account info from a specific RPC endpoint via a --rpc option.

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

1-323: Staking action tests are strong; consider a few edge-case additions

The test suite covers all main staking actions and validates client invocations and spinner messaging well. As future polish, you might:

  • Add tests for invalid shares inputs in validator/delegator exits and ensure the “Invalid shares value…” spinner path is hit.
  • Add coverage for StakingInfoAction.getStakeInfo, listQuarantinedValidators, and listBannedValidators.
  • If you ever start asserting exact formatted amounts, consider making the parseStakingAmount mock BigInt-safe (instead of parseFloat * 1e18) to avoid rounding surprises.

These are nice-to-haves rather than blockers.

tests/commands/staking.test.ts (1)

22-211: Good test coverage for core staking commands.

The tests correctly verify CLI wiring by checking that action constructors and execute methods are called with the expected options.

However, there are additional staking commands in src/commands/staking/index.ts that lack test coverage:

  • validator-prime
  • set-operator
  • set-identity
  • stake-info

Consider adding tests for these commands for completeness.

src/commands/staking/setIdentity.ts (1)

51-54: Inconsistent output: some optional fields are omitted.

The output selectively includes website, twitter, and github but omits logoUri, description, email, and telegram when provided. Consider including all provided optional fields for consistency:

       // Add optional fields that were set
+      if (options.logoUri) output.logoUri = options.logoUri;
       if (options.website) output.website = options.website;
+      if (options.description) output.description = options.description;
+      if (options.email) output.email = options.email;
       if (options.twitter) output.twitter = options.twitter;
+      if (options.telegram) output.telegram = options.telegram;
       if (options.github) output.github = options.github;
+      if (options.extraCid) output.extraCid = options.extraCid;
src/commands/account/import.ts (1)

12-17: Consider extracting MIN_PASSWORD_LENGTH to avoid duplication.

This constant is defined identically in BaseAction (line 52). Since BaseAction.MIN_PASSWORD_LENGTH is private, consider making it protected in BaseAction so subclasses can reuse it, or extract it to a shared constants file.

In src/lib/actions/BaseAction.ts:

-  private static readonly MIN_PASSWORD_LENGTH = 8;
+  protected static readonly MIN_PASSWORD_LENGTH = 8;

Then in this file:

 export class ImportAccountAction extends BaseAction {
-  private static readonly MIN_PASSWORD_LENGTH = 8;

   constructor() {
     super();
   }

And update line 41 to use BaseAction.MIN_PASSWORD_LENGTH.

src/commands/staking/stakingInfo.ts (2)

48-84: Consider extracting epoch-related constants.

The magic numbers 2n (activation delay) and 7n (unbonding period) appear multiple times in this file. Extract them as named constants for better maintainability.

// At class or module level
private static readonly ACTIVATION_DELAY_EPOCHS = 2n;
private static readonly UNBONDING_PERIOD_EPOCHS = 7n;

Then use these constants instead of the literal values on lines 52, 70, 144, and 162.


140-176: Duplicate deposit/withdrawal formatting logic.

The deposit and withdrawal formatting logic (lines 140-176) is nearly identical to that in getValidatorInfo (lines 48-84). Consider extracting this to shared helper methods.

private formatPendingDeposits(deposits: any[], currentEpoch: bigint): any {
  if (deposits.length === 0) return "None";
  return deposits.map(d => {
    const activationEpoch = d.epoch + StakingInfoAction.ACTIVATION_DELAY_EPOCHS;
    const epochsUntilActive = activationEpoch - currentEpoch;
    return {
      epoch: d.epoch.toString(),
      stake: d.stake,
      shares: d.shares.toString(),
      activatesAtEpoch: activationEpoch.toString(),
      status: epochsUntilActive <= 0n
        ? "Active"
        : `Pending (${epochsUntilActive} epoch${epochsUntilActive > 1n ? "s" : ""} remaining)`,
    };
  });
}

Apply a similar pattern for formatPendingWithdrawals.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26ea482 and 51340fd.

📒 Files selected for processing (39)
  • CLAUDE.md (1 hunks)
  • README.md (3 hunks)
  • docs/delegator-guide.md (1 hunks)
  • docs/validator-guide.md (1 hunks)
  • src/commands/account/create.ts (1 hunks)
  • src/commands/account/import.ts (1 hunks)
  • src/commands/account/index.ts (1 hunks)
  • src/commands/account/lock.ts (2 hunks)
  • src/commands/account/send.ts (1 hunks)
  • src/commands/account/show.ts (1 hunks)
  • src/commands/account/unlock.ts (2 hunks)
  • src/commands/keygen/create.ts (0 hunks)
  • src/commands/keygen/index.ts (0 hunks)
  • src/commands/network/setNetwork.ts (2 hunks)
  • src/commands/staking/StakingAction.ts (1 hunks)
  • src/commands/staking/delegatorClaim.ts (1 hunks)
  • src/commands/staking/delegatorExit.ts (1 hunks)
  • src/commands/staking/delegatorJoin.ts (1 hunks)
  • src/commands/staking/index.ts (1 hunks)
  • src/commands/staking/setIdentity.ts (1 hunks)
  • src/commands/staking/setOperator.ts (1 hunks)
  • src/commands/staking/stakingInfo.ts (1 hunks)
  • src/commands/staking/validatorClaim.ts (1 hunks)
  • src/commands/staking/validatorDeposit.ts (1 hunks)
  • src/commands/staking/validatorExit.ts (1 hunks)
  • src/commands/staking/validatorJoin.ts (1 hunks)
  • src/commands/staking/validatorPrime.ts (1 hunks)
  • src/index.ts (1 hunks)
  • src/lib/actions/BaseAction.ts (4 hunks)
  • tests/actions/create.test.ts (2 hunks)
  • tests/actions/lock.test.ts (4 hunks)
  • tests/actions/setNetwork.test.ts (8 hunks)
  • tests/actions/staking.test.ts (1 hunks)
  • tests/actions/unlock.test.ts (9 hunks)
  • tests/commands/account.test.ts (1 hunks)
  • tests/commands/keygen.test.ts (0 hunks)
  • tests/commands/staking.test.ts (1 hunks)
  • tests/index.test.ts (2 hunks)
  • tests/libs/baseAction.test.ts (1 hunks)
💤 Files with no reviewable changes (3)
  • src/commands/keygen/index.ts
  • src/commands/keygen/create.ts
  • tests/commands/keygen.test.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-03T13:20:22.582Z
Learnt from: epsjunior
Repo: genlayerlabs/genlayer-cli PR: 253
File: tests/actions/code.test.ts:78-84
Timestamp: 2025-09-03T13:20:22.582Z
Learning: In genlayer-cli, the CLI framework handles unhandled promise rejections globally, so errors outside try/catch blocks are still displayed to users appropriately.

Applied to files:

  • README.md
📚 Learning: 2025-07-10T00:34:14.320Z
Learnt from: epsjunior
Repo: genlayerlabs/genlayer-cli PR: 237
File: src/lib/services/simulator.ts:0-0
Timestamp: 2025-07-10T00:34:14.320Z
Learning: The genlayer-cli codebase uses failSpinner() patterns for error handling rather than throwing exceptions in service methods like compareVersions().

Applied to files:

  • src/lib/actions/BaseAction.ts
  • tests/libs/baseAction.test.ts
🧬 Code graph analysis (23)
src/commands/staking/validatorDeposit.ts (1)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
src/commands/account/create.ts (1)
src/lib/actions/BaseAction.ts (1)
  • BaseAction (49-269)
src/commands/staking/validatorJoin.ts (2)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
templates/default/tools/types.py (1)
  • Address (11-83)
tests/commands/account.test.ts (4)
src/commands/account/index.ts (1)
  • initializeAccountCommands (9-67)
src/commands/account/create.ts (1)
  • CreateAccountAction (8-23)
src/commands/account/unlock.ts (1)
  • UnlockAccountAction (5-41)
src/commands/account/lock.ts (1)
  • LockAccountAction (3-30)
src/index.ts (2)
src/commands/account/index.ts (1)
  • initializeAccountCommands (9-67)
src/commands/staking/index.ts (1)
  • initializeStakingCommands (14-224)
src/commands/staking/delegatorClaim.ts (1)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
src/commands/staking/delegatorJoin.ts (1)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
tests/actions/staking.test.ts (8)
src/commands/staking/validatorJoin.ts (1)
  • ValidatorJoinAction (9-47)
src/commands/staking/validatorDeposit.ts (1)
  • ValidatorDepositAction (7-35)
src/commands/staking/validatorExit.ts (1)
  • ValidatorExitAction (7-44)
src/commands/staking/validatorClaim.ts (1)
  • ValidatorClaimAction (8-38)
src/commands/staking/delegatorJoin.ts (1)
  • DelegatorJoinAction (9-42)
src/commands/staking/delegatorExit.ts (1)
  • DelegatorExitAction (9-50)
src/commands/staking/delegatorClaim.ts (1)
  • DelegatorClaimAction (9-41)
src/commands/staking/stakingInfo.ts (1)
  • StakingInfoAction (8-292)
src/commands/account/unlock.ts (1)
src/lib/actions/BaseAction.ts (1)
  • BaseAction (49-269)
src/commands/account/send.ts (2)
src/lib/actions/BaseAction.ts (3)
  • BaseAction (49-269)
  • BUILT_IN_NETWORKS (12-16)
  • resolveNetwork (22-44)
src/lib/interfaces/KeystoreData.ts (1)
  • KeystoreData (1-5)
src/commands/staking/validatorClaim.ts (1)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
tests/actions/create.test.ts (1)
src/commands/account/create.ts (1)
  • CreateAccountAction (8-23)
src/commands/staking/validatorPrime.ts (1)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
src/commands/staking/setIdentity.ts (1)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
src/commands/account/lock.ts (1)
src/lib/actions/BaseAction.ts (1)
  • BaseAction (49-269)
src/commands/staking/setOperator.ts (1)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
src/commands/account/import.ts (2)
src/lib/actions/BaseAction.ts (1)
  • BaseAction (49-269)
src/lib/interfaces/KeystoreData.ts (1)
  • KeystoreData (1-5)
src/commands/account/index.ts (6)
src/commands/account/show.ts (1)
  • ShowAccountAction (8-60)
src/commands/account/create.ts (2)
  • CreateAccountOptions (3-6)
  • CreateAccountAction (8-23)
src/commands/account/import.ts (1)
  • ImportAccountOptions (6-10)
src/commands/account/send.ts (1)
  • SendAction (16-150)
src/commands/account/unlock.ts (1)
  • UnlockAccountAction (5-41)
src/commands/account/lock.ts (1)
  • LockAccountAction (3-30)
tests/commands/staking.test.ts (9)
src/commands/staking/index.ts (1)
  • initializeStakingCommands (14-224)
src/commands/staking/validatorJoin.ts (1)
  • ValidatorJoinAction (9-47)
src/commands/staking/validatorDeposit.ts (1)
  • ValidatorDepositAction (7-35)
src/commands/staking/validatorExit.ts (1)
  • ValidatorExitAction (7-44)
src/commands/staking/validatorClaim.ts (1)
  • ValidatorClaimAction (8-38)
src/commands/staking/delegatorJoin.ts (1)
  • DelegatorJoinAction (9-42)
src/commands/staking/delegatorExit.ts (1)
  • DelegatorExitAction (9-50)
src/commands/staking/delegatorClaim.ts (1)
  • DelegatorClaimAction (9-41)
src/commands/staking/stakingInfo.ts (1)
  • StakingInfoAction (8-292)
src/commands/staking/index.ts (11)
src/commands/staking/validatorJoin.ts (2)
  • ValidatorJoinOptions (4-7)
  • ValidatorJoinAction (9-47)
src/commands/staking/validatorDeposit.ts (2)
  • ValidatorDepositOptions (3-5)
  • ValidatorDepositAction (7-35)
src/commands/staking/validatorExit.ts (2)
  • ValidatorExitOptions (3-5)
  • ValidatorExitAction (7-44)
src/commands/staking/validatorClaim.ts (2)
  • ValidatorClaimOptions (4-6)
  • ValidatorClaimAction (8-38)
src/commands/staking/validatorPrime.ts (2)
  • ValidatorPrimeOptions (4-6)
  • ValidatorPrimeAction (8-35)
src/commands/staking/setOperator.ts (2)
  • SetOperatorOptions (4-7)
  • SetOperatorAction (9-40)
src/commands/staking/setIdentity.ts (2)
  • SetIdentityOptions (4-15)
  • SetIdentityAction (17-61)
src/commands/staking/delegatorJoin.ts (2)
  • DelegatorJoinOptions (4-7)
  • DelegatorJoinAction (9-42)
src/commands/staking/delegatorExit.ts (2)
  • DelegatorExitOptions (4-7)
  • DelegatorExitAction (9-50)
src/commands/staking/delegatorClaim.ts (2)
  • DelegatorClaimOptions (4-7)
  • DelegatorClaimAction (9-41)
src/commands/staking/stakingInfo.ts (2)
  • StakingInfoOptions (4-6)
  • StakingInfoAction (8-292)
tests/actions/lock.test.ts (1)
src/commands/account/lock.ts (1)
  • LockAccountAction (3-30)
src/commands/staking/delegatorExit.ts (1)
src/commands/staking/StakingAction.ts (2)
  • StakingConfig (8-12)
  • StakingAction (14-125)
tests/actions/unlock.test.ts (1)
src/commands/account/unlock.ts (1)
  • UnlockAccountAction (5-41)
🪛 GitHub Actions: CI Workflow
src/commands/staking/StakingAction.ts

[error] 2-2: Build failed: No matching export in 'genlayer-js/dist/index.js' for import 'formatStakingAmount'.


[error] 2-2: Build failed: No matching export in 'genlayer-js/dist/index.js' for import 'parseStakingAmount'.

🪛 markdownlint-cli2 (0.18.1)
docs/delegator-guide.md

54-54: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


101-101: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


138-138: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (44)
src/commands/account/lock.ts (1)

1-30: LGTM! Clean terminology update.

The rename from LockAction to LockAccountAction and the updated user-facing messages ("account" instead of "wallet") align well with the broader refactor to account-centric terminology across the CLI.

src/commands/account/unlock.ts (1)

1-41: LGTM! Consistent terminology update.

The rename from UnlockAction to UnlockAccountAction and the updated messaging align well with the account-centric refactor. The core unlock flow remains functionally unchanged.

src/index.ts (1)

6-27: LGTM! CLI initialization updated correctly.

The replacement of initializeKeygenCommands with initializeAccountCommands and the addition of initializeStakingCommands properly reflect the new command structure. The initialization order is logical and consistent.

CLAUDE.md (1)

1-55: LGTM! Helpful documentation for AI assistants.

This documentation provides clear guidance on the project structure, build/test commands, and architectural patterns. The content accurately reflects the current codebase structure including the new account and staking command domains.

tests/libs/baseAction.test.ts (1)

110-124: LGTM! Tests correctly cover new failSpinner behavior.

The updates properly test both the non-exit path (with shouldExit=false) and the default exit behavior. This aligns with the broader refactor to support non-fatal error handling in BaseAction.

Based on learnings, the codebase uses failSpinner patterns for error handling rather than throwing exceptions.

docs/delegator-guide.md (1)

1-203: Excellent comprehensive guide for delegators!

The guide provides clear step-by-step instructions with concrete examples and expected outputs. The content covers all essential aspects of delegation including validator selection criteria, stake management, and troubleshooting.

tests/index.test.ts (1)

16-50: LGTM! Test mocks updated correctly.

The mocks properly reflect the CLI refactor from keygen to account commands and the addition of staking commands.

src/commands/account/index.ts (1)

9-67: LGTM! Clean command wiring with good UX.

The command structure is well-organized with:

  • A sensible default action (showing account info)
  • Consistent pattern across all subcommands
  • Clear option descriptions and defaults
  • Ergonomic command signatures (e.g., send <to> <amount>)
src/commands/staking/delegatorJoin.ts (1)

1-42: LGTM!

The implementation follows established patterns from other staking actions (ValidatorJoinAction, DelegatorClaimAction) with appropriate error handling, spinner feedback, and structured output.

src/commands/staking/index.ts (1)

1-224: LGTM!

The staking command wiring is comprehensive and consistent. All subcommands properly define their options, match their corresponding action interfaces, and follow the established CLI patterns.

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

2-64: LGTM!

Test updates correctly align with the renamed LockAccountAction and updated messaging. All test expectations match the implementation.

src/commands/network/setNetwork.ts (1)

30-59: LGTM!

The alias-based network storage implementation is correct and consistent throughout the method. The non-null assertion on line 56 is safe since the network is validated before use.

src/commands/staking/setOperator.ts (1)

1-40: LGTM!

The implementation follows the established staking action patterns with proper error handling and structured output. Consistent with other staking actions like ValidatorJoinAction and SetIdentityAction.

src/commands/account/show.ts (1)

17-59: LGTM!

The implementation correctly handles account info retrieval with proper validation, error handling, and formatted output. Network resolution is properly integrated.

src/commands/staking/delegatorExit.ts (1)

1-50: LGTM!

The implementation correctly mirrors ValidatorExitAction patterns with proper shares validation (positive BigInt check), error handling, and informative output including the unbonding period note.

docs/validator-guide.md (1)

113-113: No action needed — the --output option is properly implemented.

The genlayer account create command includes the --output option, defined in src/commands/account/index.ts at line 22 with the default value "./keypair.json". The documentation example is accurate.

src/commands/account/create.ts (1)

1-23: CreateAccountAction wiring and flow look consistent and correct

Account creation delegates cleanly to BaseAction.createKeypair, and spinner/success/failure handling matches the existing action patterns. I don’t see any functional issues here.

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

2-121: UnlockAccountAction tests accurately track the new account-unlock behavior

The tests now line up with UnlockAccountAction (constructor, path, spinner text, error messages) and exercise the key success and failure paths, so the coverage here looks solid.

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

29-145: NetworkActions tests correctly reflect alias-based network storage

The expectations against writeConfig("network", "<alias>") and the updated interactive prompt choices/return values all match the new alias-centric network handling, while keeping the existing failure cases intact. Looks good.

tests/commands/account.test.ts (1)

1-121: Account command wiring tests align with initializeAccountCommands behavior

These tests correctly assert the options passed into CreateAccountAction.execute for all flag combinations, and verify that unlock/lock actions are instantiated and invoked. The coverage of the CLI wiring looks good.

src/commands/staking/delegatorClaim.ts (1)

1-41: DelegatorClaimAction execute flow is consistent and matches tests

The action correctly resolves the delegator address (explicit or signer), calls client.delegatorClaim with typed addresses, and surfaces clear spinner messages on success/failure. It lines up with the expectations in tests/actions/staking.test.ts.

src/commands/staking/validatorDeposit.ts (1)

1-35: ValidatorDepositAction logic is straightforward and correct (pending StakingAction helper fix)

The deposit action correctly parses the amount via parseAmount, calls validatorDeposit, and reports a detailed success payload; error handling follows the shared pattern. Once the parseAmount/formatAmount helpers in StakingAction are fixed, this should work as intended.

src/commands/staking/validatorJoin.ts (1)

1-47: LGTM! Clean implementation following established patterns.

The action correctly extends StakingAction, handles the optional operator parameter, and follows the spinner-based UX pattern used by other staking actions. Error handling and output formatting are consistent with the codebase conventions.

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

1-45: LGTM! Tests properly updated to align with the renamed action class.

The test expectations correctly match the implementation in src/commands/account/create.ts. Both success and error paths are covered.

src/commands/staking/validatorClaim.ts (1)

1-38: LGTM! Clean implementation with sensible defaults.

The action correctly falls back to the signer's address when no validator is specified, which is the expected behavior for self-claiming. The implementation follows the established staking action pattern.

src/commands/staking/validatorPrime.ts (1)

1-35: LGTM! Follows the established staking action pattern.

The implementation is clean and consistent with other staking actions. The required validator parameter is appropriate for this operation.

src/commands/staking/setIdentity.ts (1)

1-61: Overall structure looks good.

The action correctly extends StakingAction and follows the established spinner-based UX pattern.

src/commands/staking/validatorExit.ts (2)

15-23: Good input validation for shares.

The nested try-catch correctly handles both invalid numeric input (e.g., non-numeric strings) and non-positive values. The early return after failSpinner prevents further execution.


1-44: LGTM! Clean implementation with proper validation.

The action correctly validates the shares input before attempting the exit operation and includes a helpful note about the unbonding period in the output.

src/commands/account/send.ts (3)

110-118: Consider making the polling timeout configurable or using exponential backoff.

The fixed 2-second polling interval for up to 60 iterations (120 seconds total) works but could be improved:

  • Network congestion may require longer waits
  • Initial polls could use shorter intervals

This is acceptable for now but could be enhanced later.


47-149: Overall implementation is solid.

The execute method correctly handles:

  • Account validation and keystore decryption
  • Network resolution with fallback
  • Transaction preparation, signing, and submission
  • Receipt polling with graceful handling of pending transactions
  • Error handling throughout the flow

79-80: The Hash type cast is correct and does not require changes.

The Hash type from genlayer-js/types is equivalent to 0x${string} (a hex string prefixed with "0x"), which is exactly what createAccount expects. However, note that src/commands/staking/StakingAction.ts line 47 uses the more explicit 0x${string} pattern for the same function call. Consider aligning this with that pattern for consistency across the codebase.

README.md (2)

296-393: Well-documented staking operations section.

The staking documentation is comprehensive with clear command descriptions, options, and practical examples including sample output. This will help users understand the staking workflows effectively.


412-416: Both guide documents exist in the repository (docs/validator-guide.md and docs/delegator-guide.md), so the links in the Guides section are valid.

src/commands/account/import.ts (3)

1-10: Clean imports and interface definition.

The interface correctly defines the import options with optional privateKey for interactive input.


19-65: LGTM - Solid import workflow implementation.

The execute method properly:

  • Handles both CLI argument and interactive input for private keys
  • Validates before file I/O operations
  • Uses secure password prompts with confirmation
  • Clears the keychain after import to ensure clean state

67-80: Good security practice using masked input for private key.

Using promptPassword for private key input ensures the sensitive data is masked in the terminal.

src/lib/actions/BaseAction.ts (4)

97-108: Clean integration of network resolution.

The getClient method now uses the centralized resolveNetwork function, simplifying network handling across the codebase.


123-129: Good use of non-exiting failure for recoverable scenarios.

Using failSpinner(..., undefined, false) allows the user to be informed of the invalid format while still offering the option to create a new keypair.


253-260: Backwards-compatible enhancement to failSpinner.

The optional shouldExit parameter (defaulting to true) maintains existing behavior while enabling non-fatal failure scenarios. Based on learnings, this aligns with the codebase's error handling patterns.


11-44: Network resolution implementation is sound with proper backwards compatibility.

The resolveNetwork function cleanly handles both the new alias format (direct key lookup) and old JSON format (with name matching) for backwards compatibility. The assumption that built-in network names (localnet, studionet, testnetAsimov) are unique across chains is reasonable given they're imported from the external genlayer-js library and used consistently throughout the codebase. The implementation correctly prioritizes direct alias lookup first for performance before falling back to JSON parsing, and provides appropriate error handling for truly invalid input.

src/commands/staking/stakingInfo.ts (3)

1-11: Clean interface and class setup.

The StakingInfoOptions interface appropriately extends StakingConfig for the query methods that need a validator address.


184-226: Well-implemented epoch info retrieval.

The formatDuration helper and time calculations are clean. The method provides comprehensive epoch information with human-readable formatting.


228-291: Consistent implementation across validator list methods.

All three list methods (listActiveValidators, listQuarantinedValidators, listBannedValidators) follow a clean, consistent pattern with proper error handling.

Comment on lines +212 to +216
genlayer account Show account info (address, balance, network, status)
genlayer account create [options] Create a new account
genlayer account send <to> <amount> Send GEN to an address
genlayer account unlock Unlock account (cache key in OS keychain)
genlayer account lock Lock account (remove key from OS keychain)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing space in usage syntax on Line 214.

The usage line for the send command is missing a space, making it harder to read and inconsistent with the format of other commands.

-   genlayer account send <to> <amount> Send GEN to an address
+   genlayer account send <to> <amount>  Send GEN to an address
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
genlayer account Show account info (address, balance, network, status)
genlayer account create [options] Create a new account
genlayer account send <to> <amount> Send GEN to an address
genlayer account unlock Unlock account (cache key in OS keychain)
genlayer account lock Lock account (remove key from OS keychain)
genlayer account Show account info (address, balance, network, status)
genlayer account create [options] Create a new account
genlayer account send <to> <amount> Send GEN to an address
genlayer account unlock Unlock account (cache key in OS keychain)
genlayer account lock Lock account (remove key from OS keychain)
🤖 Prompt for AI Agents
In README.md around lines 212 to 216, the usage line "genlayer account send <to>
<amount> Send GEN to an address" is missing the separating space(s) between the
command usage and its description; update that line to include the same
spacing/column alignment as the other lines (e.g., add at least one extra space
between "<amount>" and "Send GEN to an address") so the usage and description
are visually separated and consistent with the other entries.

Comment on lines +32 to +45
private parseAmount(amount: string): bigint {
// Support "10gen" or "10" (assumes gen) or wei values
const lowerAmount = amount.toLowerCase();
if (lowerAmount.endsWith("gen")) {
const value = lowerAmount.slice(0, -3);
return parseEther(value);
}
// If it's a large number (likely wei), use as-is
if (BigInt(amount) > 1_000_000_000_000n) {
return BigInt(amount);
}
// Otherwise assume it's in GEN
return parseEther(amount);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Amount parsing heuristic may cause unexpected behavior.

The logic using 1_000_000_000_000n (1 trillion) as the threshold to distinguish wei from GEN is fragile:

  • "999999999999" (just under 1 trillion) → treated as GEN → becomes ~1e30 wei
  • "1000000000000" (1 trillion) → treated as wei → stays as 1 trillion wei (~0.000001 GEN)

This creates a discontinuity where amounts just below the threshold behave very differently. Consider:

  1. Requiring explicit units (e.g., "10gen" or "10wei")
  2. Using a higher/clearer threshold
  3. Adding documentation warning about this behavior
  private parseAmount(amount: string): bigint {
-   // Support "10gen" or "10" (assumes gen) or wei values
+   // Support "10gen", "10wei", or "10" (assumes gen for small values, wei for large)
    const lowerAmount = amount.toLowerCase();
    if (lowerAmount.endsWith("gen")) {
      const value = lowerAmount.slice(0, -3);
      return parseEther(value);
    }
+   if (lowerAmount.endsWith("wei")) {
+     const value = lowerAmount.slice(0, -3);
+     return BigInt(value);
+   }
    // If it's a large number (likely wei), use as-is
    if (BigInt(amount) > 1_000_000_000_000n) {
      return BigInt(amount);
    }
    // Otherwise assume it's in GEN
    return parseEther(amount);
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private parseAmount(amount: string): bigint {
// Support "10gen" or "10" (assumes gen) or wei values
const lowerAmount = amount.toLowerCase();
if (lowerAmount.endsWith("gen")) {
const value = lowerAmount.slice(0, -3);
return parseEther(value);
}
// If it's a large number (likely wei), use as-is
if (BigInt(amount) > 1_000_000_000_000n) {
return BigInt(amount);
}
// Otherwise assume it's in GEN
return parseEther(amount);
}
private parseAmount(amount: string): bigint {
// Support "10gen", "10wei", or "10" (assumes gen for small values, wei for large)
const lowerAmount = amount.toLowerCase();
if (lowerAmount.endsWith("gen")) {
const value = lowerAmount.slice(0, -3);
return parseEther(value);
}
if (lowerAmount.endsWith("wei")) {
const value = lowerAmount.slice(0, -3);
return BigInt(value);
}
// If it's a large number (likely wei), use as-is
if (BigInt(amount) > 1_000_000_000_000n) {
return BigInt(amount);
}
// Otherwise assume it's in GEN
return parseEther(amount);
}

Upgrades the genlayer-js dependency from version 0.16.0 to 0.18.5.

This update likely includes new features, bug fixes, and performance improvements within the genlayer-js library.
@cristiam86 cristiam86 merged commit 36e4180 into main Dec 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.

3 participants