-
Notifications
You must be signed in to change notification settings - Fork 3
feat: Implements staking functionality #266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
WalkthroughReplaces 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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas requiring extra attention:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (3)📚 Learning: 2025-08-12T22:52:10.974ZApplied to files:
📚 Learning: 2025-07-10T23:50:34.628ZApplied to files:
📚 Learning: 2025-09-03T13:20:22.582ZApplied to files:
🔇 Additional comments (1)
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. Comment |
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.
|
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. |
There was a problem hiding this 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
textorjsonto 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 commandsrc/commands/network/setNetwork.ts (1)
7-23: Consider consolidating network definitions.The
networksarray appears to duplicate the network definitions that exist inBUILT_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
createClientcall 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--rpcoption.tests/actions/staking.test.ts (1)
1-323: Staking action tests are strong; consider a few edge-case additionsThe test suite covers all main staking actions and validates client invocations and spinner messaging well. As future polish, you might:
- Add tests for invalid
sharesinputs in validator/delegator exits and ensure the “Invalid shares value…” spinner path is hit.- Add coverage for
StakingInfoAction.getStakeInfo,listQuarantinedValidators, andlistBannedValidators.- If you ever start asserting exact formatted amounts, consider making the
parseStakingAmountmock BigInt-safe (instead ofparseFloat * 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.tsthat lack test coverage:
validator-primeset-operatorset-identitystake-infoConsider 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,githubbut omitslogoUri,description,telegramwhen 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 extractingMIN_PASSWORD_LENGTHto avoid duplication.This constant is defined identically in
BaseAction(line 52). SinceBaseAction.MIN_PASSWORD_LENGTHis private, consider making itprotectedinBaseActionso 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) and7n(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
📒 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.tstests/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
LockActiontoLockAccountActionand 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
UnlockActiontoUnlockAccountActionand 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
initializeKeygenCommandswithinitializeAccountCommandsand the addition ofinitializeStakingCommandsproperly 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--outputoption is properly implemented.The
genlayer account createcommand includes the--outputoption, defined insrc/commands/account/index.tsat 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 correctAccount 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 behaviorThe 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 storageThe 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 behaviorThese tests correctly assert the options passed into
CreateAccountAction.executefor 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 testsThe action correctly resolves the delegator address (explicit or signer), calls
client.delegatorClaimwith typed addresses, and surfaces clear spinner messages on success/failure. It lines up with the expectations intests/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, callsvalidatorDeposit, and reports a detailed success payload; error handling follows the shared pattern. Once theparseAmount/formatAmounthelpers inStakingActionare 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
validatorparameter is appropriate for this operation.src/commands/staking/setIdentity.ts (1)
1-61: Overall structure looks good.The action correctly extends
StakingActionand 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
failSpinnerprevents 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
executemethod 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: TheHashtype cast is correct and does not require changes.The
Hashtype from genlayer-js/types is equivalent to0x${string}(a hex string prefixed with "0x"), which is exactly whatcreateAccountexpects. However, note thatsrc/commands/staking/StakingAction.tsline 47 uses the more explicit0x${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.mdanddocs/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
privateKeyfor 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
promptPasswordfor 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
getClientmethod now uses the centralizedresolveNetworkfunction, 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 tofailSpinner.The optional
shouldExitparameter (defaulting totrue) 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
resolveNetworkfunction 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
StakingInfoOptionsinterface appropriately extendsStakingConfigfor the query methods that need a validator address.
184-226: Well-implemented epoch info retrieval.The
formatDurationhelper 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.
| 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| 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); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
- Requiring explicit units (e.g.,
"10gen"or"10wei") - Using a higher/clearer threshold
- 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.
| 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.
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
Enhancements
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.