genlayer 0.33.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.34.0 (2026-02-08)
4
+
5
+ ### Features
6
+
7
+ * add --password flag for non-interactive CLI usage ([#275](https://github.com/yeagerai/genlayer-cli/issues/275)) ([c5fffa6](https://github.com/yeagerai/genlayer-cli/commit/c5fffa6faaf0133ad83dd47279e3383d0a0cbacb))
8
+
9
+ ## 0.33.1 (2026-02-07)
10
+
11
+ ### Bug Fixes
12
+
13
+ * bump genlayer-js to 0.18.10 with phase4 testnet addresses ([#274](https://github.com/yeagerai/genlayer-cli/issues/274)) ([faa9a9b](https://github.com/yeagerai/genlayer-cli/commit/faa9a9bfaadf3ff158e2b21457330bc629d977e9))
14
+
3
15
  ## 0.33.0 (2026-01-13)
4
16
 
5
17
  ### Features
package/dist/index.js CHANGED
@@ -20078,7 +20078,7 @@ var require_cli_table3 = __commonJS({
20078
20078
  import { program } from "commander";
20079
20079
 
20080
20080
  // package.json
20081
- var version = "0.33.0";
20081
+ var version = "0.34.0";
20082
20082
  var package_default = {
20083
20083
  name: "genlayer",
20084
20084
  version,
@@ -20147,7 +20147,7 @@ var package_default = {
20147
20147
  dotenv: "^17.0.0",
20148
20148
  ethers: "^6.13.4",
20149
20149
  "fs-extra": "^11.3.0",
20150
- "genlayer-js": "^0.18.9",
20150
+ "genlayer-js": "^0.18.10",
20151
20151
  inquirer: "^12.0.0",
20152
20152
  keytar: "^7.9.0",
20153
20153
  "node-fetch": "^3.0.0",
@@ -33734,7 +33734,7 @@ init_fromHex();
33734
33734
  init_toHex();
33735
33735
  init_formatEther();
33736
33736
 
33737
- // node_modules/genlayer-js/dist/chunk-V3MYVW3P.js
33737
+ // node_modules/genlayer-js/dist/chunk-WZNF2WK4.js
33738
33738
  var chains_exports = {};
33739
33739
  __export2(chains_exports, {
33740
33740
  localnet: () => localnet,
@@ -42423,14 +42423,15 @@ var STAKING_ABI = [
42423
42423
  ]
42424
42424
  }
42425
42425
  ];
42426
- var TESTNET_JSON_RPC_URL = "https://genlayer-testnet.rpc.caldera.xyz/http";
42426
+ var TESTNET_JSON_RPC_URL = "https://zksync-os-testnet-genlayer.zksync.dev";
42427
+ var TESTNET_WS_URL = "wss://zksync-os-testnet-alpha.zksync.dev/ws";
42427
42428
  var STAKING_CONTRACT = {
42428
- address: "0x03f410748EBdb4026a6b8299E9B6603A273709D1",
42429
+ address: "0x63Fa5E0bb10fb6fA98F44726C5518223F767687A",
42429
42430
  abi: STAKING_ABI
42430
42431
  };
42431
42432
  var EXPLORER_URL2 = "https://explorer-asimov.genlayer.com/";
42432
42433
  var CONSENSUS_MAIN_CONTRACT3 = {
42433
- address: "0x67fd4aC71530FB220E0B7F90668BAF977B88fF07",
42434
+ address: "0x6CAFF6769d70824745AD895663409DC70aB5B28E",
42434
42435
  abi: [
42435
42436
  {
42436
42437
  inputs: [],
@@ -43819,7 +43820,7 @@ var CONSENSUS_MAIN_CONTRACT3 = {
43819
43820
  bytecode: ""
43820
43821
  };
43821
43822
  var CONSENSUS_DATA_CONTRACT3 = {
43822
- address: "0xB6E1316E57d47d82FDcEa5002028a554754EF243",
43823
+ address: "0x0D9d1d74d72Fa5eB94bcf746C8FCcb312a722c9B",
43823
43824
  abi: [
43824
43825
  {
43825
43826
  inputs: [],
@@ -46405,7 +46406,8 @@ var testnetAsimov = defineChain({
46405
46406
  name: "Genlayer Asimov Testnet",
46406
46407
  rpcUrls: {
46407
46408
  default: {
46408
- http: [TESTNET_JSON_RPC_URL]
46409
+ http: [TESTNET_JSON_RPC_URL],
46410
+ webSocket: [TESTNET_WS_URL]
46409
46411
  }
46410
46412
  },
46411
46413
  nativeCurrency: {
@@ -48672,17 +48674,22 @@ var _BaseAction = class _BaseAction extends ConfigFileManager {
48672
48674
  getAddress(keystoreData) {
48673
48675
  return keystoreData.address;
48674
48676
  }
48675
- async createKeypairByName(accountName, overwrite) {
48677
+ async createKeypairByName(accountName, overwrite, passwordInput) {
48676
48678
  const keystorePath = this.getKeystorePath(accountName);
48677
48679
  this.stopSpinner();
48678
48680
  if (existsSync(keystorePath) && !overwrite) {
48679
48681
  this.failSpinner(`Account '${accountName}' already exists. Use '--overwrite' to replace it.`);
48680
48682
  }
48681
48683
  const wallet = ethers.Wallet.createRandom();
48682
- const password = await this.promptPassword("Enter a password to encrypt your keystore (minimum 8 characters):");
48683
- const confirmPassword = await this.promptPassword("Confirm password:");
48684
- if (password !== confirmPassword) {
48685
- this.failSpinner("Passwords do not match");
48684
+ let password;
48685
+ if (passwordInput) {
48686
+ password = passwordInput;
48687
+ } else {
48688
+ password = await this.promptPassword("Enter a password to encrypt your keystore (minimum 8 characters):");
48689
+ const confirmPassword = await this.promptPassword("Confirm password:");
48690
+ if (password !== confirmPassword) {
48691
+ this.failSpinner("Passwords do not match");
48692
+ }
48686
48693
  }
48687
48694
  if (password.length < _BaseAction.MIN_PASSWORD_LENGTH) {
48688
48695
  this.failSpinner(`Password must be at least ${_BaseAction.MIN_PASSWORD_LENGTH} characters long`);
@@ -50009,7 +50016,7 @@ var CreateAccountAction = class extends BaseAction {
50009
50016
  async execute(options) {
50010
50017
  try {
50011
50018
  this.startSpinner(`Creating account '${options.name}'...`);
50012
- await this.createKeypairByName(options.name, options.overwrite);
50019
+ await this.createKeypairByName(options.name, options.overwrite, options.password);
50013
50020
  if (options.setActive !== false) {
50014
50021
  this.setActiveAccount(options.name);
50015
50022
  }
@@ -50214,9 +50221,14 @@ var UnlockAccountAction = class extends BaseAction {
50214
50221
  this.failSpinner("Invalid keystore format.");
50215
50222
  return;
50216
50223
  }
50217
- this.stopSpinner();
50218
50224
  try {
50219
- const password = await this.promptPassword(`Enter password to unlock '${accountName}':`);
50225
+ let password;
50226
+ if (options?.password) {
50227
+ password = options.password;
50228
+ } else {
50229
+ this.stopSpinner();
50230
+ password = await this.promptPassword(`Enter password to unlock '${accountName}':`);
50231
+ }
50220
50232
  const wallet = await ethers4.Wallet.fromEncryptedJson(keystoreJson, password);
50221
50233
  await this.keychainManager.storePrivateKey(accountName, wallet.privateKey);
50222
50234
  this.succeedSpinner(`Account '${accountName}' unlocked! Private key cached in OS keychain.`);
@@ -50306,9 +50318,14 @@ var SendAction = class extends BaseAction {
50306
50318
  if (cachedKey) {
50307
50319
  privateKey = cachedKey;
50308
50320
  } else {
50309
- this.stopSpinner();
50310
- const password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
50311
- this.startSpinner("Preparing transfer...");
50321
+ let password;
50322
+ if (options.password) {
50323
+ password = options.password;
50324
+ } else {
50325
+ this.stopSpinner();
50326
+ password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
50327
+ this.startSpinner("Preparing transfer...");
50328
+ }
50312
50329
  const wallet = await ethers5.Wallet.fromEncryptedJson(keystoreJson, password);
50313
50330
  privateKey = wallet.privateKey;
50314
50331
  }
@@ -50456,7 +50473,7 @@ function initializeAccountCommands(program2) {
50456
50473
  const showAction = new ShowAccountAction();
50457
50474
  await showAction.execute(options);
50458
50475
  });
50459
- accountCommand.command("create").description("Create a new account with encrypted keystore").requiredOption("--name <name>", "Name for the account").option("--overwrite", "Overwrite existing account", false).option("--no-set-active", "Do not set as active account").action(async (options) => {
50476
+ accountCommand.command("create").description("Create a new account with encrypted keystore").requiredOption("--name <name>", "Name for the account").option("--password <password>", "Password for the keystore (skips interactive prompt)").option("--overwrite", "Overwrite existing account", false).option("--no-set-active", "Do not set as active account").action(async (options) => {
50460
50477
  const createAction = new CreateAccountAction();
50461
50478
  await createAction.execute(options);
50462
50479
  });
@@ -50476,11 +50493,11 @@ function initializeAccountCommands(program2) {
50476
50493
  const removeAction = new RemoveAccountAction();
50477
50494
  await removeAction.execute(name, options);
50478
50495
  });
50479
- accountCommand.command("send <to> <amount>").description("Send GEN to an address").option("--rpc <rpcUrl>", "RPC URL for the network").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--account <name>", "Account to send from").action(async (to, amount, options) => {
50496
+ accountCommand.command("send <to> <amount>").description("Send GEN to an address").option("--rpc <rpcUrl>", "RPC URL for the network").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--account <name>", "Account to send from").option("--password <password>", "Password to unlock account (skips interactive prompt)").action(async (to, amount, options) => {
50480
50497
  const sendAction = new SendAction();
50481
- await sendAction.execute({ to, amount, rpc: options.rpc, network: options.network, account: options.account });
50498
+ await sendAction.execute({ to, amount, rpc: options.rpc, network: options.network, account: options.account, password: options.password });
50482
50499
  });
50483
- accountCommand.command("unlock").description("Unlock account by caching private key in OS keychain").option("--account <name>", "Account to unlock").action(async (options) => {
50500
+ accountCommand.command("unlock").description("Unlock account by caching private key in OS keychain").option("--account <name>", "Account to unlock").option("--password <password>", "Password to unlock account (skips interactive prompt)").action(async (options) => {
50484
50501
  const unlockAction = new UnlockAccountAction();
50485
50502
  await unlockAction.execute(options);
50486
50503
  });
@@ -51319,6 +51336,7 @@ var StakingAction = class extends BaseAction {
51319
51336
  constructor() {
51320
51337
  super();
51321
51338
  __publicField(this, "_stakingClient", null);
51339
+ __publicField(this, "_passwordOverride");
51322
51340
  }
51323
51341
  getNetwork(config) {
51324
51342
  if (config.network) {
@@ -51335,6 +51353,9 @@ var StakingAction = class extends BaseAction {
51335
51353
  if (config.account) {
51336
51354
  this.accountOverride = config.account;
51337
51355
  }
51356
+ if (config.password) {
51357
+ this._passwordOverride = config.password;
51358
+ }
51338
51359
  const network = this.getNetwork(config);
51339
51360
  if (config.stakingAddress) {
51340
51361
  network.stakingContract = {
@@ -51399,8 +51420,13 @@ var StakingAction = class extends BaseAction {
51399
51420
  return cachedKey;
51400
51421
  }
51401
51422
  }
51402
- this.stopSpinner();
51403
- const password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
51423
+ let password;
51424
+ if (this._passwordOverride) {
51425
+ password = this._passwordOverride;
51426
+ } else {
51427
+ this.stopSpinner();
51428
+ password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
51429
+ }
51404
51430
  this.startSpinner("Unlocking account...");
51405
51431
  const wallet = await ethers6.Wallet.fromEncryptedJson(keystoreJson, password);
51406
51432
  return wallet.privateKey;
@@ -51429,6 +51455,9 @@ var StakingAction = class extends BaseAction {
51429
51455
  if (config.account) {
51430
51456
  this.accountOverride = config.account;
51431
51457
  }
51458
+ if (config.password) {
51459
+ this._passwordOverride = config.password;
51460
+ }
51432
51461
  const network = this.getNetwork(config);
51433
51462
  const rpcUrl = config.rpc || network.rpcUrls.default.http[0];
51434
51463
  const privateKey = await this.getPrivateKeyForStaking();
@@ -53160,11 +53189,11 @@ function initializeStakingCommands(program2) {
53160
53189
  const wizard = new ValidatorWizardAction();
53161
53190
  await wizard.execute(options);
53162
53191
  });
53163
- staking.command("validator-join").description("Join as a validator by staking tokens").requiredOption("--amount <amount>", "Amount to stake (in wei or with 'eth'/'gen' suffix, e.g., '42000gen')").option("--operator <address>", "Operator address (defaults to signer)").option("--account <name>", "Account to use").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (options) => {
53192
+ staking.command("validator-join").description("Join as a validator by staking tokens").requiredOption("--amount <amount>", "Amount to stake (in wei or with 'eth'/'gen' suffix, e.g., '42000gen')").option("--operator <address>", "Operator address (defaults to signer)").option("--account <name>", "Account to use").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (options) => {
53164
53193
  const action = new ValidatorJoinAction();
53165
53194
  await action.execute(options);
53166
53195
  });
53167
- staking.command("validator-deposit [validator]").description("Make an additional deposit to a validator wallet").option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)").requiredOption("--amount <amount>", "Amount to deposit (in wei or with 'eth'/'gen' suffix)").option("--account <name>", "Account to use (must be validator owner)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, options) => {
53196
+ staking.command("validator-deposit [validator]").description("Make an additional deposit to a validator wallet").option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)").requiredOption("--amount <amount>", "Amount to deposit (in wei or with 'eth'/'gen' suffix)").option("--account <name>", "Account to use (must be validator owner)").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, options) => {
53168
53197
  const validator = validatorArg || options.validator;
53169
53198
  if (!validator) {
53170
53199
  console.error("Error: validator address is required");
@@ -53173,7 +53202,7 @@ function initializeStakingCommands(program2) {
53173
53202
  const action = new ValidatorDepositAction();
53174
53203
  await action.execute({ ...options, validator });
53175
53204
  });
53176
- staking.command("validator-exit [validator]").description("Exit as a validator by withdrawing shares").option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)").requiredOption("--shares <shares>", "Number of shares to withdraw").option("--account <name>", "Account to use (must be validator owner)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, options) => {
53205
+ staking.command("validator-exit [validator]").description("Exit as a validator by withdrawing shares").option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)").requiredOption("--shares <shares>", "Number of shares to withdraw").option("--account <name>", "Account to use (must be validator owner)").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, options) => {
53177
53206
  const validator = validatorArg || options.validator;
53178
53207
  if (!validator) {
53179
53208
  console.error("Error: validator address is required");
@@ -53182,7 +53211,7 @@ function initializeStakingCommands(program2) {
53182
53211
  const action = new ValidatorExitAction();
53183
53212
  await action.execute({ ...options, validator });
53184
53213
  });
53185
- staking.command("validator-claim [validator]").description("Claim validator withdrawals after unbonding period").option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)").option("--account <name>", "Account to use").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, options) => {
53214
+ staking.command("validator-claim [validator]").description("Claim validator withdrawals after unbonding period").option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)").option("--account <name>", "Account to use").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, options) => {
53186
53215
  const validator = validatorArg || options.validator;
53187
53216
  if (!validator) {
53188
53217
  console.error("Error: validator address is required");
@@ -53191,7 +53220,7 @@ function initializeStakingCommands(program2) {
53191
53220
  const action = new ValidatorClaimAction();
53192
53221
  await action.execute({ ...options, validator });
53193
53222
  });
53194
- staking.command("validator-prime [validator]").description("Prime a validator to prepare their stake record for the next epoch").option("--validator <address>", "Validator address to prime (deprecated, use positional arg)").option("--account <name>", "Account to use").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (validatorArg, options) => {
53223
+ staking.command("validator-prime [validator]").description("Prime a validator to prepare their stake record for the next epoch").option("--validator <address>", "Validator address to prime (deprecated, use positional arg)").option("--account <name>", "Account to use").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (validatorArg, options) => {
53195
53224
  const validator = validatorArg || options.validator;
53196
53225
  if (!validator) {
53197
53226
  console.error("Error: validator address is required");
@@ -53200,11 +53229,11 @@ function initializeStakingCommands(program2) {
53200
53229
  const action = new ValidatorPrimeAction();
53201
53230
  await action.execute({ ...options, validator });
53202
53231
  });
53203
- staking.command("prime-all").description("Prime all validators that need priming").option("--account <name>", "Account to use (pays gas)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (options) => {
53232
+ staking.command("prime-all").description("Prime all validators that need priming").option("--account <name>", "Account to use (pays gas)").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (options) => {
53204
53233
  const action = new ValidatorPrimeAction();
53205
53234
  await action.primeAll(options);
53206
53235
  });
53207
- staking.command("set-operator [validator] [operator]").description("Change the operator address for a validator wallet").option("--validator <address>", "Validator wallet address (deprecated, use positional arg)").option("--operator <address>", "New operator address (deprecated, use positional arg)").option("--account <name>", "Account to use (must be validator owner)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, operatorArg, options) => {
53236
+ staking.command("set-operator [validator] [operator]").description("Change the operator address for a validator wallet").option("--validator <address>", "Validator wallet address (deprecated, use positional arg)").option("--operator <address>", "New operator address (deprecated, use positional arg)").option("--account <name>", "Account to use (must be validator owner)").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, operatorArg, options) => {
53208
53237
  const validator = validatorArg || options.validator;
53209
53238
  const operator = operatorArg || options.operator;
53210
53239
  if (!validator || !operator) {
@@ -53214,7 +53243,7 @@ function initializeStakingCommands(program2) {
53214
53243
  const action = new SetOperatorAction();
53215
53244
  await action.execute({ ...options, validator, operator });
53216
53245
  });
53217
- staking.command("set-identity [validator]").description("Set validator identity metadata (moniker, website, socials, etc.)").option("--validator <address>", "Validator wallet address (deprecated, use positional arg)").requiredOption("--moniker <name>", "Validator display name").option("--logo-uri <uri>", "Logo URI").option("--website <url>", "Website URL").option("--description <text>", "Description").option("--email <email>", "Contact email").option("--twitter <handle>", "Twitter handle").option("--telegram <handle>", "Telegram handle").option("--github <handle>", "GitHub handle").option("--extra-cid <cid>", "Extra data as IPFS CID or hex bytes (0x...)").option("--account <name>", "Account to use (must be validator operator)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, options) => {
53246
+ staking.command("set-identity [validator]").description("Set validator identity metadata (moniker, website, socials, etc.)").option("--validator <address>", "Validator wallet address (deprecated, use positional arg)").requiredOption("--moniker <name>", "Validator display name").option("--logo-uri <uri>", "Logo URI").option("--website <url>", "Website URL").option("--description <text>", "Description").option("--email <email>", "Contact email").option("--twitter <handle>", "Twitter handle").option("--telegram <handle>", "Telegram handle").option("--github <handle>", "GitHub handle").option("--extra-cid <cid>", "Extra data as IPFS CID or hex bytes (0x...)").option("--account <name>", "Account to use (must be validator operator)").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (validatorArg, options) => {
53218
53247
  const validator = validatorArg || options.validator;
53219
53248
  if (!validator) {
53220
53249
  console.error("Error: validator address is required");
@@ -53223,7 +53252,7 @@ function initializeStakingCommands(program2) {
53223
53252
  const action = new SetIdentityAction();
53224
53253
  await action.execute({ ...options, validator });
53225
53254
  });
53226
- staking.command("delegator-join [validator]").description("Join as a delegator by staking with a validator").option("--validator <address>", "Validator address to delegate to (deprecated, use positional arg)").requiredOption("--amount <amount>", "Amount to stake (in wei or with 'eth'/'gen' suffix)").option("--account <name>", "Account to use").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (validatorArg, options) => {
53255
+ staking.command("delegator-join [validator]").description("Join as a delegator by staking with a validator").option("--validator <address>", "Validator address to delegate to (deprecated, use positional arg)").requiredOption("--amount <amount>", "Amount to stake (in wei or with 'eth'/'gen' suffix)").option("--account <name>", "Account to use").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (validatorArg, options) => {
53227
53256
  const validator = validatorArg || options.validator;
53228
53257
  if (!validator) {
53229
53258
  console.error("Error: validator address is required");
@@ -53232,7 +53261,7 @@ function initializeStakingCommands(program2) {
53232
53261
  const action = new DelegatorJoinAction();
53233
53262
  await action.execute({ ...options, validator });
53234
53263
  });
53235
- staking.command("delegator-exit [validator]").description("Exit as a delegator by withdrawing shares from a validator").option("--validator <address>", "Validator address to exit from (deprecated, use positional arg)").requiredOption("--shares <shares>", "Number of shares to withdraw").option("--account <name>", "Account to use").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (validatorArg, options) => {
53264
+ staking.command("delegator-exit [validator]").description("Exit as a delegator by withdrawing shares from a validator").option("--validator <address>", "Validator address to exit from (deprecated, use positional arg)").requiredOption("--shares <shares>", "Number of shares to withdraw").option("--account <name>", "Account to use").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (validatorArg, options) => {
53236
53265
  const validator = validatorArg || options.validator;
53237
53266
  if (!validator) {
53238
53267
  console.error("Error: validator address is required");
@@ -53241,7 +53270,7 @@ function initializeStakingCommands(program2) {
53241
53270
  const action = new DelegatorExitAction();
53242
53271
  await action.execute({ ...options, validator });
53243
53272
  });
53244
- staking.command("delegator-claim [validator]").description("Claim delegator withdrawals after unbonding period").option("--validator <address>", "Validator address (deprecated, use positional arg)").option("--delegator <address>", "Delegator address (defaults to signer)").option("--account <name>", "Account to use").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (validatorArg, options) => {
53273
+ staking.command("delegator-claim [validator]").description("Claim delegator withdrawals after unbonding period").option("--validator <address>", "Validator address (deprecated, use positional arg)").option("--delegator <address>", "Delegator address (defaults to signer)").option("--account <name>", "Account to use").option("--password <password>", "Password to unlock account (skips interactive prompt)").option("--network <network>", "Network to use (localnet, testnet-asimov)").option("--rpc <rpcUrl>", "RPC URL for the network").option("--staking-address <address>", "Staking contract address (overrides chain config)").action(async (validatorArg, options) => {
53245
53274
  const validator = validatorArg || options.validator;
53246
53275
  if (!validator) {
53247
53276
  console.error("Error: validator address is required");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genlayer",
3
- "version": "0.33.0",
3
+ "version": "0.34.0",
4
4
  "description": "GenLayer Command Line Tool",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -66,7 +66,7 @@
66
66
  "dotenv": "^17.0.0",
67
67
  "ethers": "^6.13.4",
68
68
  "fs-extra": "^11.3.0",
69
- "genlayer-js": "^0.18.9",
69
+ "genlayer-js": "^0.18.10",
70
70
  "inquirer": "^12.0.0",
71
71
  "keytar": "^7.9.0",
72
72
  "node-fetch": "^3.0.0",
@@ -4,6 +4,7 @@ export interface CreateAccountOptions {
4
4
  name: string;
5
5
  overwrite: boolean;
6
6
  setActive?: boolean;
7
+ password?: string;
7
8
  }
8
9
 
9
10
  export class CreateAccountAction extends BaseAction {
@@ -14,7 +15,7 @@ export class CreateAccountAction extends BaseAction {
14
15
  async execute(options: CreateAccountOptions): Promise<void> {
15
16
  try {
16
17
  this.startSpinner(`Creating account '${options.name}'...`);
17
- await this.createKeypairByName(options.name, options.overwrite);
18
+ await this.createKeypairByName(options.name, options.overwrite, options.password);
18
19
 
19
20
  if (options.setActive !== false) {
20
21
  this.setActiveAccount(options.name);
@@ -42,6 +42,7 @@ export function initializeAccountCommands(program: Command) {
42
42
  .command("create")
43
43
  .description("Create a new account with encrypted keystore")
44
44
  .requiredOption("--name <name>", "Name for the account")
45
+ .option("--password <password>", "Password for the keystore (skips interactive prompt)")
45
46
  .option("--overwrite", "Overwrite existing account", false)
46
47
  .option("--no-set-active", "Do not set as active account")
47
48
  .action(async (options: CreateAccountOptions) => {
@@ -99,15 +100,17 @@ export function initializeAccountCommands(program: Command) {
99
100
  .option("--rpc <rpcUrl>", "RPC URL for the network")
100
101
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
101
102
  .option("--account <name>", "Account to send from")
102
- .action(async (to: string, amount: string, options: {rpc?: string; network?: string; account?: string}) => {
103
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
104
+ .action(async (to: string, amount: string, options: {rpc?: string; network?: string; account?: string; password?: string}) => {
103
105
  const sendAction = new SendAction();
104
- await sendAction.execute({to, amount, rpc: options.rpc, network: options.network, account: options.account});
106
+ await sendAction.execute({to, amount, rpc: options.rpc, network: options.network, account: options.account, password: options.password});
105
107
  });
106
108
 
107
109
  accountCommand
108
110
  .command("unlock")
109
111
  .description("Unlock account by caching private key in OS keychain")
110
112
  .option("--account <name>", "Account to unlock")
113
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
111
114
  .action(async (options: UnlockAccountOptions) => {
112
115
  const unlockAction = new UnlockAccountAction();
113
116
  await unlockAction.execute(options);
@@ -11,6 +11,7 @@ export interface SendOptions {
11
11
  rpc?: string;
12
12
  network?: string;
13
13
  account?: string;
14
+ password?: string;
14
15
  }
15
16
 
16
17
  export class SendAction extends BaseAction {
@@ -75,9 +76,14 @@ export class SendAction extends BaseAction {
75
76
  if (cachedKey) {
76
77
  privateKey = cachedKey;
77
78
  } else {
78
- this.stopSpinner();
79
- const password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
80
- this.startSpinner("Preparing transfer...");
79
+ let password: string;
80
+ if (options.password) {
81
+ password = options.password;
82
+ } else {
83
+ this.stopSpinner();
84
+ password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
85
+ this.startSpinner("Preparing transfer...");
86
+ }
81
87
  const wallet = await ethers.Wallet.fromEncryptedJson(keystoreJson, password);
82
88
  privateKey = wallet.privateKey;
83
89
  }
@@ -4,6 +4,7 @@ import {ethers} from "ethers";
4
4
 
5
5
  export interface UnlockAccountOptions {
6
6
  account?: string;
7
+ password?: string;
7
8
  }
8
9
 
9
10
  export class UnlockAccountAction extends BaseAction {
@@ -36,10 +37,14 @@ export class UnlockAccountAction extends BaseAction {
36
37
  return;
37
38
  }
38
39
 
39
- this.stopSpinner();
40
-
41
40
  try {
42
- const password = await this.promptPassword(`Enter password to unlock '${accountName}':`);
41
+ let password: string;
42
+ if (options?.password) {
43
+ password = options.password;
44
+ } else {
45
+ this.stopSpinner();
46
+ password = await this.promptPassword(`Enter password to unlock '${accountName}':`);
47
+ }
43
48
  const wallet = await ethers.Wallet.fromEncryptedJson(keystoreJson, password);
44
49
 
45
50
  await this.keychainManager.storePrivateKey(accountName, wallet.privateKey);
@@ -25,10 +25,12 @@ export interface StakingConfig {
25
25
  stakingAddress?: string;
26
26
  network?: string;
27
27
  account?: string;
28
+ password?: string;
28
29
  }
29
30
 
30
31
  export class StakingAction extends BaseAction {
31
32
  private _stakingClient: GenLayerClient<GenLayerChain> | null = null;
33
+ private _passwordOverride: string | undefined;
32
34
 
33
35
  constructor() {
34
36
  super();
@@ -53,6 +55,9 @@ export class StakingAction extends BaseAction {
53
55
  if (config.account) {
54
56
  this.accountOverride = config.account;
55
57
  }
58
+ if (config.password) {
59
+ this._passwordOverride = config.password;
60
+ }
56
61
 
57
62
  const network = this.getNetwork(config);
58
63
 
@@ -140,9 +145,13 @@ export class StakingAction extends BaseAction {
140
145
  }
141
146
  }
142
147
 
143
- // Stop spinner before prompting for password
144
- this.stopSpinner();
145
- const password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
148
+ let password: string;
149
+ if (this._passwordOverride) {
150
+ password = this._passwordOverride;
151
+ } else {
152
+ this.stopSpinner();
153
+ password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
154
+ }
146
155
  this.startSpinner("Unlocking account...");
147
156
 
148
157
  const wallet = await ethers.Wallet.fromEncryptedJson(keystoreJson, password);
@@ -180,6 +189,9 @@ export class StakingAction extends BaseAction {
180
189
  if (config.account) {
181
190
  this.accountOverride = config.account;
182
191
  }
192
+ if (config.password) {
193
+ this._passwordOverride = config.password;
194
+ }
183
195
 
184
196
  const network = this.getNetwork(config);
185
197
  const rpcUrl = config.rpc || network.rpcUrls.default.http[0];
@@ -37,6 +37,7 @@ export function initializeStakingCommands(program: Command) {
37
37
  .requiredOption("--amount <amount>", "Amount to stake (in wei or with 'eth'/'gen' suffix, e.g., '42000gen')")
38
38
  .option("--operator <address>", "Operator address (defaults to signer)")
39
39
  .option("--account <name>", "Account to use")
40
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
40
41
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
41
42
  .option("--rpc <rpcUrl>", "RPC URL for the network")
42
43
  .option("--staking-address <address>", "Staking contract address (overrides chain config)")
@@ -51,6 +52,7 @@ export function initializeStakingCommands(program: Command) {
51
52
  .option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)")
52
53
  .requiredOption("--amount <amount>", "Amount to deposit (in wei or with 'eth'/'gen' suffix)")
53
54
  .option("--account <name>", "Account to use (must be validator owner)")
55
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
54
56
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
55
57
  .option("--rpc <rpcUrl>", "RPC URL for the network")
56
58
  .action(async (validatorArg: string | undefined, options: ValidatorDepositOptions) => {
@@ -69,6 +71,7 @@ export function initializeStakingCommands(program: Command) {
69
71
  .option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)")
70
72
  .requiredOption("--shares <shares>", "Number of shares to withdraw")
71
73
  .option("--account <name>", "Account to use (must be validator owner)")
74
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
72
75
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
73
76
  .option("--rpc <rpcUrl>", "RPC URL for the network")
74
77
  .action(async (validatorArg: string | undefined, options: ValidatorExitOptions) => {
@@ -86,6 +89,7 @@ export function initializeStakingCommands(program: Command) {
86
89
  .description("Claim validator withdrawals after unbonding period")
87
90
  .option("--validator <address>", "Validator wallet contract address (deprecated, use positional arg)")
88
91
  .option("--account <name>", "Account to use")
92
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
89
93
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
90
94
  .option("--rpc <rpcUrl>", "RPC URL for the network")
91
95
  .action(async (validatorArg: string | undefined, options: ValidatorClaimOptions) => {
@@ -103,6 +107,7 @@ export function initializeStakingCommands(program: Command) {
103
107
  .description("Prime a validator to prepare their stake record for the next epoch")
104
108
  .option("--validator <address>", "Validator address to prime (deprecated, use positional arg)")
105
109
  .option("--account <name>", "Account to use")
110
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
106
111
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
107
112
  .option("--rpc <rpcUrl>", "RPC URL for the network")
108
113
  .option("--staking-address <address>", "Staking contract address (overrides chain config)")
@@ -120,6 +125,7 @@ export function initializeStakingCommands(program: Command) {
120
125
  .command("prime-all")
121
126
  .description("Prime all validators that need priming")
122
127
  .option("--account <name>", "Account to use (pays gas)")
128
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
123
129
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
124
130
  .option("--rpc <rpcUrl>", "RPC URL for the network")
125
131
  .option("--staking-address <address>", "Staking contract address (overrides chain config)")
@@ -134,6 +140,7 @@ export function initializeStakingCommands(program: Command) {
134
140
  .option("--validator <address>", "Validator wallet address (deprecated, use positional arg)")
135
141
  .option("--operator <address>", "New operator address (deprecated, use positional arg)")
136
142
  .option("--account <name>", "Account to use (must be validator owner)")
143
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
137
144
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
138
145
  .option("--rpc <rpcUrl>", "RPC URL for the network")
139
146
  .action(async (validatorArg: string | undefined, operatorArg: string | undefined, options: SetOperatorOptions) => {
@@ -161,6 +168,7 @@ export function initializeStakingCommands(program: Command) {
161
168
  .option("--github <handle>", "GitHub handle")
162
169
  .option("--extra-cid <cid>", "Extra data as IPFS CID or hex bytes (0x...)")
163
170
  .option("--account <name>", "Account to use (must be validator operator)")
171
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
164
172
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
165
173
  .option("--rpc <rpcUrl>", "RPC URL for the network")
166
174
  .action(async (validatorArg: string | undefined, options: SetIdentityOptions) => {
@@ -180,6 +188,7 @@ export function initializeStakingCommands(program: Command) {
180
188
  .option("--validator <address>", "Validator address to delegate to (deprecated, use positional arg)")
181
189
  .requiredOption("--amount <amount>", "Amount to stake (in wei or with 'eth'/'gen' suffix)")
182
190
  .option("--account <name>", "Account to use")
191
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
183
192
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
184
193
  .option("--rpc <rpcUrl>", "RPC URL for the network")
185
194
  .option("--staking-address <address>", "Staking contract address (overrides chain config)")
@@ -199,6 +208,7 @@ export function initializeStakingCommands(program: Command) {
199
208
  .option("--validator <address>", "Validator address to exit from (deprecated, use positional arg)")
200
209
  .requiredOption("--shares <shares>", "Number of shares to withdraw")
201
210
  .option("--account <name>", "Account to use")
211
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
202
212
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
203
213
  .option("--rpc <rpcUrl>", "RPC URL for the network")
204
214
  .option("--staking-address <address>", "Staking contract address (overrides chain config)")
@@ -218,6 +228,7 @@ export function initializeStakingCommands(program: Command) {
218
228
  .option("--validator <address>", "Validator address (deprecated, use positional arg)")
219
229
  .option("--delegator <address>", "Delegator address (defaults to signer)")
220
230
  .option("--account <name>", "Account to use")
231
+ .option("--password <password>", "Password to unlock account (skips interactive prompt)")
221
232
  .option("--network <network>", "Network to use (localnet, testnet-asimov)")
222
233
  .option("--rpc <rpcUrl>", "RPC URL for the network")
223
234
  .option("--staking-address <address>", "Staking contract address (overrides chain config)")
@@ -171,7 +171,7 @@ export class BaseAction extends ConfigFileManager {
171
171
  return keystoreData.address as Address;
172
172
  }
173
173
 
174
- protected async createKeypairByName(accountName: string, overwrite: boolean): Promise<string> {
174
+ protected async createKeypairByName(accountName: string, overwrite: boolean, passwordInput?: string): Promise<string> {
175
175
  const keystorePath = this.getKeystorePath(accountName);
176
176
  this.stopSpinner();
177
177
 
@@ -181,11 +181,15 @@ export class BaseAction extends ConfigFileManager {
181
181
 
182
182
  const wallet = ethers.Wallet.createRandom();
183
183
 
184
- const password = await this.promptPassword("Enter a password to encrypt your keystore (minimum 8 characters):");
185
- const confirmPassword = await this.promptPassword("Confirm password:");
186
-
187
- if (password !== confirmPassword) {
188
- this.failSpinner("Passwords do not match");
184
+ let password: string;
185
+ if (passwordInput) {
186
+ password = passwordInput;
187
+ } else {
188
+ password = await this.promptPassword("Enter a password to encrypt your keystore (minimum 8 characters):");
189
+ const confirmPassword = await this.promptPassword("Confirm password:");
190
+ if (password !== confirmPassword) {
191
+ this.failSpinner("Passwords do not match");
192
+ }
189
193
  }
190
194
 
191
195
  if (password.length < BaseAction.MIN_PASSWORD_LENGTH) {
@@ -38,7 +38,7 @@ describe("CreateAccountAction", () => {
38
38
  await createAction.execute(options);
39
39
 
40
40
  expect(createAction["startSpinner"]).toHaveBeenCalledWith("Creating account 'main'...");
41
- expect(createAction["createKeypairByName"]).toHaveBeenCalledWith("main", false);
41
+ expect(createAction["createKeypairByName"]).toHaveBeenCalledWith("main", false, undefined);
42
42
  expect(createAction["setActiveAccount"]).toHaveBeenCalledWith("main");
43
43
  expect(createAction["succeedSpinner"]).toHaveBeenCalledWith(
44
44
  `Account 'main' created at: ${mockKeystorePath}`,