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 +12 -0
- package/dist/index.js +65 -36
- package/package.json +2 -2
- package/src/commands/account/create.ts +2 -1
- package/src/commands/account/index.ts +5 -2
- package/src/commands/account/send.ts +9 -3
- package/src/commands/account/unlock.ts +8 -3
- package/src/commands/staking/StakingAction.ts +15 -3
- package/src/commands/staking/index.ts +11 -0
- package/src/lib/actions/BaseAction.ts +10 -6
- package/tests/actions/create.test.ts +1 -1
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.
|
|
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.
|
|
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-
|
|
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://
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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
|
-
|
|
48683
|
-
|
|
48684
|
-
|
|
48685
|
-
|
|
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
|
-
|
|
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
|
-
|
|
50310
|
-
|
|
50311
|
-
|
|
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
|
-
|
|
51403
|
-
|
|
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.
|
|
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.
|
|
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
|
-
.
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
144
|
-
this.
|
|
145
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
this.
|
|
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}`,
|