genlayer 0.34.0 → 0.34.3

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.
Files changed (128) hide show
  1. package/dist/index.js +13 -3
  2. package/package.json +11 -2
  3. package/.eslintignore +0 -2
  4. package/.github/workflows/cli-docs.yml +0 -121
  5. package/.github/workflows/publish-beta.yml +0 -41
  6. package/.github/workflows/publish.yml +0 -43
  7. package/.github/workflows/validate-code.yml +0 -47
  8. package/.prettierignore +0 -19
  9. package/.prettierrc +0 -12
  10. package/.release-it.json +0 -64
  11. package/CHANGELOG.md +0 -425
  12. package/CLAUDE.md +0 -55
  13. package/CONTRIBUTING.md +0 -117
  14. package/docker-compose.yml +0 -154
  15. package/docs/delegator-guide.md +0 -203
  16. package/docs/validator-guide.md +0 -329
  17. package/esbuild.config.dev.js +0 -17
  18. package/esbuild.config.js +0 -22
  19. package/esbuild.config.prod.js +0 -17
  20. package/eslint.config.js +0 -60
  21. package/renovate.json +0 -22
  22. package/src/commands/account/create.ts +0 -30
  23. package/src/commands/account/export.ts +0 -106
  24. package/src/commands/account/import.ts +0 -135
  25. package/src/commands/account/index.ts +0 -129
  26. package/src/commands/account/list.ts +0 -34
  27. package/src/commands/account/lock.ts +0 -39
  28. package/src/commands/account/remove.ts +0 -30
  29. package/src/commands/account/send.ts +0 -162
  30. package/src/commands/account/show.ts +0 -74
  31. package/src/commands/account/unlock.ts +0 -56
  32. package/src/commands/account/use.ts +0 -21
  33. package/src/commands/config/getSetReset.ts +0 -51
  34. package/src/commands/config/index.ts +0 -30
  35. package/src/commands/contracts/call.ts +0 -39
  36. package/src/commands/contracts/code.ts +0 -33
  37. package/src/commands/contracts/deploy.ts +0 -157
  38. package/src/commands/contracts/index.ts +0 -86
  39. package/src/commands/contracts/schema.ts +0 -31
  40. package/src/commands/contracts/write.ts +0 -49
  41. package/src/commands/general/index.ts +0 -45
  42. package/src/commands/general/init.ts +0 -179
  43. package/src/commands/general/start.ts +0 -116
  44. package/src/commands/general/stop.ts +0 -26
  45. package/src/commands/localnet/index.ts +0 -100
  46. package/src/commands/localnet/validators.ts +0 -269
  47. package/src/commands/network/index.ts +0 -29
  48. package/src/commands/network/setNetwork.ts +0 -77
  49. package/src/commands/scaffold/index.ts +0 -16
  50. package/src/commands/scaffold/new.ts +0 -34
  51. package/src/commands/staking/StakingAction.ts +0 -279
  52. package/src/commands/staking/delegatorClaim.ts +0 -41
  53. package/src/commands/staking/delegatorExit.ts +0 -56
  54. package/src/commands/staking/delegatorJoin.ts +0 -44
  55. package/src/commands/staking/index.ts +0 -357
  56. package/src/commands/staking/setIdentity.ts +0 -78
  57. package/src/commands/staking/setOperator.ts +0 -46
  58. package/src/commands/staking/stakingInfo.ts +0 -584
  59. package/src/commands/staking/validatorClaim.ts +0 -43
  60. package/src/commands/staking/validatorDeposit.ts +0 -48
  61. package/src/commands/staking/validatorExit.ts +0 -63
  62. package/src/commands/staking/validatorHistory.ts +0 -298
  63. package/src/commands/staking/validatorJoin.ts +0 -47
  64. package/src/commands/staking/validatorPrime.ts +0 -73
  65. package/src/commands/staking/wizard.ts +0 -809
  66. package/src/commands/transactions/appeal.ts +0 -39
  67. package/src/commands/transactions/index.ts +0 -39
  68. package/src/commands/transactions/receipt.ts +0 -90
  69. package/src/commands/update/index.ts +0 -25
  70. package/src/commands/update/ollama.ts +0 -103
  71. package/src/lib/actions/BaseAction.ts +0 -299
  72. package/src/lib/clients/jsonRpcClient.ts +0 -41
  73. package/src/lib/clients/system.ts +0 -73
  74. package/src/lib/config/ConfigFileManager.ts +0 -194
  75. package/src/lib/config/KeychainManager.ts +0 -89
  76. package/src/lib/config/simulator.ts +0 -68
  77. package/src/lib/config/text.ts +0 -2
  78. package/src/lib/errors/missingRequirement.ts +0 -9
  79. package/src/lib/errors/versionRequired.ts +0 -9
  80. package/src/lib/interfaces/ISimulatorService.ts +0 -37
  81. package/src/lib/services/simulator.ts +0 -351
  82. package/src/types/node-fetch.d.ts +0 -1
  83. package/tests/actions/appeal.test.ts +0 -99
  84. package/tests/actions/call.test.ts +0 -94
  85. package/tests/actions/code.test.ts +0 -87
  86. package/tests/actions/create.test.ts +0 -65
  87. package/tests/actions/deploy.test.ts +0 -420
  88. package/tests/actions/getSetReset.test.ts +0 -88
  89. package/tests/actions/init.test.ts +0 -467
  90. package/tests/actions/lock.test.ts +0 -86
  91. package/tests/actions/new.test.ts +0 -80
  92. package/tests/actions/ollama.test.ts +0 -193
  93. package/tests/actions/receipt.test.ts +0 -261
  94. package/tests/actions/schema.test.ts +0 -94
  95. package/tests/actions/setNetwork.test.ts +0 -160
  96. package/tests/actions/staking.test.ts +0 -279
  97. package/tests/actions/start.test.ts +0 -235
  98. package/tests/actions/stop.test.ts +0 -77
  99. package/tests/actions/unlock.test.ts +0 -139
  100. package/tests/actions/validators.test.ts +0 -750
  101. package/tests/actions/write.test.ts +0 -102
  102. package/tests/commands/account.test.ts +0 -146
  103. package/tests/commands/appeal.test.ts +0 -58
  104. package/tests/commands/call.test.ts +0 -78
  105. package/tests/commands/code.test.ts +0 -69
  106. package/tests/commands/config.test.ts +0 -54
  107. package/tests/commands/deploy.test.ts +0 -83
  108. package/tests/commands/init.test.ts +0 -101
  109. package/tests/commands/localnet.test.ts +0 -131
  110. package/tests/commands/network.test.ts +0 -60
  111. package/tests/commands/new.test.ts +0 -68
  112. package/tests/commands/receipt.test.ts +0 -142
  113. package/tests/commands/schema.test.ts +0 -67
  114. package/tests/commands/staking.test.ts +0 -329
  115. package/tests/commands/stop.test.ts +0 -27
  116. package/tests/commands/up.test.ts +0 -105
  117. package/tests/commands/update.test.ts +0 -45
  118. package/tests/commands/write.test.ts +0 -76
  119. package/tests/index.test.ts +0 -56
  120. package/tests/libs/baseAction.test.ts +0 -516
  121. package/tests/libs/configFileManager.test.ts +0 -117
  122. package/tests/libs/jsonRpcClient.test.ts +0 -59
  123. package/tests/libs/keychainManager.test.ts +0 -156
  124. package/tests/libs/system.test.ts +0 -148
  125. package/tests/services/simulator.test.ts +0 -705
  126. package/tests/utils.ts +0 -13
  127. package/tsconfig.json +0 -120
  128. package/vitest.config.ts +0 -12
@@ -1,17 +0,0 @@
1
- export default {
2
- context: {
3
- tsconfig: "./tsconfig.json",
4
- entryPoints: ["src/index.ts"],
5
- bundle: true,
6
- outfile: "dist/index.js",
7
- platform: "node",
8
- target: "es2020",
9
- format: "esm",
10
- define: { "import.meta.url": "import.meta.url" },
11
- banner: {
12
- js: `const _importMetaUrl = new URL(import.meta.url).pathname;`,
13
- },
14
- external: ["commander", "dockerode", "dotenv", "ethers", "inquirer", "update-check", "ssh2", "fs-extra", "esbuild", "keytar"]
15
- },
16
- watch: false,
17
- };
package/eslint.config.js DELETED
@@ -1,60 +0,0 @@
1
- import js from "@eslint/js";
2
- import tseslint from "@typescript-eslint/eslint-plugin";
3
- import tsparser from "@typescript-eslint/parser";
4
- import prettier from "eslint-config-prettier";
5
- import importPlugin from "eslint-plugin-import";
6
-
7
- export default [
8
- js.configs.recommended,
9
- prettier,
10
- {
11
- languageOptions: {
12
- parser: tsparser,
13
- parserOptions: {
14
- project: ["./tsconfig.json"],
15
- sourceType: "module",
16
- },
17
- },
18
- ignores: [
19
- "**/dist/**/*",
20
- "esbuild.config.js",
21
- "esbuild.config.dev.js",
22
- "esbuild.config.prod.js",
23
- "jest.config.js",
24
- "eslint.config.js",
25
- "Config.js",
26
- "commitLint.config.ts",
27
- "scripts/postinstall.js",
28
- "templates/**/*"
29
- ],
30
- plugins: {
31
- "@typescript-eslint": tseslint,
32
- import: importPlugin,
33
- },
34
- rules: {
35
- "import/namespace": "off",
36
- "@typescript-eslint/no-empty-function": "off",
37
- "@typescript-eslint/no-empty-interface": "off",
38
- "no-constant-condition": "off",
39
- "@typescript-eslint/no-explicit-any": "off",
40
- "prefer-const": "off",
41
- "@typescript-eslint/no-non-null-assertion": "off",
42
- "@typescript-eslint/ban-ts-ignore": "off",
43
- "@typescript-eslint/no-loss-of-precision": "off",
44
- "@typescript-eslint/ban-types": "off",
45
- "@typescript-eslint/ban-ts-comment": "off",
46
- "@typescript-eslint/no-non-null-asserted-optional-chain": "off",
47
- "@typescript-eslint/no-var-requires": "off",
48
- "import/export": "off",
49
- "no-fallthrough": "off",
50
- "@typescript-eslint/explicit-module-boundary-types": "off",
51
- "@typescript-eslint/no-floating-promises": ["error"],
52
- "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
53
- },
54
- settings: {
55
- "import/resolver": {
56
- typescript: {},
57
- },
58
- },
59
- },
60
- ];
package/renovate.json DELETED
@@ -1,22 +0,0 @@
1
- {
2
- "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
- "extends": [
4
- "config:recommended"
5
- ],
6
- "ignorePaths": [
7
- "templates/**"
8
- ],
9
- "packageRules": [
10
- {
11
- "groupName": "all non-major dependencies",
12
- "groupSlug": "all-minor-patch",
13
- "matchPackageNames": [
14
- "*"
15
- ],
16
- "matchUpdateTypes": [
17
- "minor",
18
- "patch"
19
- ]
20
- }
21
- ]
22
- }
@@ -1,30 +0,0 @@
1
- import {BaseAction} from "../../lib/actions/BaseAction";
2
-
3
- export interface CreateAccountOptions {
4
- name: string;
5
- overwrite: boolean;
6
- setActive?: boolean;
7
- password?: string;
8
- }
9
-
10
- export class CreateAccountAction extends BaseAction {
11
- constructor() {
12
- super();
13
- }
14
-
15
- async execute(options: CreateAccountOptions): Promise<void> {
16
- try {
17
- this.startSpinner(`Creating account '${options.name}'...`);
18
- await this.createKeypairByName(options.name, options.overwrite, options.password);
19
-
20
- if (options.setActive !== false) {
21
- this.setActiveAccount(options.name);
22
- }
23
-
24
- const keystorePath = this.getKeystorePath(options.name);
25
- this.succeedSpinner(`Account '${options.name}' created at: ${keystorePath}`);
26
- } catch (error) {
27
- this.failSpinner("Failed to create account", error);
28
- }
29
- }
30
- }
@@ -1,106 +0,0 @@
1
- import {BaseAction} from "../../lib/actions/BaseAction";
2
- import {ethers} from "ethers";
3
- import {writeFileSync, existsSync, readFileSync} from "fs";
4
- import path from "path";
5
-
6
- export interface ExportAccountOptions {
7
- account?: string;
8
- output: string;
9
- password?: string;
10
- sourcePassword?: string;
11
- overwrite?: boolean;
12
- }
13
-
14
- export class ExportAccountAction extends BaseAction {
15
- constructor() {
16
- super();
17
- }
18
-
19
- async execute(options: ExportAccountOptions): Promise<void> {
20
- try {
21
- if (options.account) {
22
- this.accountOverride = options.account;
23
- }
24
-
25
- const accountName = this.resolveAccountName();
26
- const keystorePath = this.getKeystorePath(accountName);
27
-
28
- if (!existsSync(keystorePath)) {
29
- this.failSpinner(`Account '${accountName}' not found.`);
30
- }
31
-
32
- const outputPath = path.resolve(options.output);
33
-
34
- if (existsSync(outputPath) && !options.overwrite) {
35
- this.failSpinner(`Output file already exists: ${outputPath}`);
36
- }
37
-
38
- // Get the private key
39
- const privateKey = await this.getPrivateKeyForExport(accountName, keystorePath, options.sourcePassword);
40
-
41
- // Get password for the exported keystore
42
- let password: string;
43
- if (options.password) {
44
- password = options.password;
45
- } else {
46
- password = await this.promptPassword("Enter password for exported keystore (minimum 8 characters):");
47
- const confirmPassword = await this.promptPassword("Confirm password:");
48
- if (password !== confirmPassword) {
49
- this.failSpinner("Passwords do not match");
50
- }
51
- }
52
-
53
- if (password.length < BaseAction.MIN_PASSWORD_LENGTH) {
54
- this.failSpinner(`Password must be at least ${BaseAction.MIN_PASSWORD_LENGTH} characters long`);
55
- }
56
-
57
- this.startSpinner(`Exporting account '${accountName}'...`);
58
-
59
- const wallet = new ethers.Wallet(privateKey);
60
- const encryptedJson = await wallet.encrypt(password);
61
-
62
- // Write standard web3 keystore format (compatible with geth, foundry, etc.)
63
- writeFileSync(outputPath, encryptedJson);
64
-
65
- this.succeedSpinner(`Account '${accountName}' exported to: ${outputPath}`);
66
- this.logInfo(`Address: ${wallet.address}`);
67
- } catch (error) {
68
- this.failSpinner("Failed to export account", error);
69
- }
70
- }
71
-
72
- private async getPrivateKeyForExport(
73
- accountName: string,
74
- keystorePath: string,
75
- sourcePassword?: string
76
- ): Promise<string> {
77
- // First check if key is cached in keychain
78
- const isAvailable = await this.keychainManager.isKeychainAvailable();
79
- if (isAvailable) {
80
- const cachedKey = await this.keychainManager.getPrivateKey(accountName);
81
- if (cachedKey) {
82
- return cachedKey;
83
- }
84
- }
85
-
86
- // Need to decrypt the keystore
87
- const fileContent = readFileSync(keystorePath, "utf-8");
88
- const parsed = JSON.parse(fileContent);
89
-
90
- const encryptedJson = parsed.encrypted || fileContent;
91
-
92
- const password = sourcePassword || await this.promptPassword(`Enter password to unlock '${accountName}':`);
93
-
94
- this.startSpinner("Decrypting keystore...");
95
-
96
- try {
97
- const wallet = await ethers.Wallet.fromEncryptedJson(encryptedJson, password);
98
- this.stopSpinner();
99
- return wallet.privateKey;
100
- } catch {
101
- this.failSpinner("Failed to decrypt keystore. Wrong password?");
102
- }
103
-
104
- throw new Error("Unreachable");
105
- }
106
- }
@@ -1,135 +0,0 @@
1
- import {BaseAction} from "../../lib/actions/BaseAction";
2
- import {ethers} from "ethers";
3
- import {writeFileSync, existsSync, readFileSync} from "fs";
4
-
5
- export interface ImportAccountOptions {
6
- privateKey?: string;
7
- keystore?: string;
8
- name: string;
9
- overwrite: boolean;
10
- setActive?: boolean;
11
- password?: string;
12
- sourcePassword?: string;
13
- }
14
-
15
- export class ImportAccountAction extends BaseAction {
16
- constructor() {
17
- super();
18
- }
19
-
20
- async execute(options: ImportAccountOptions): Promise<void> {
21
- try {
22
- const keystorePath = this.getKeystorePath(options.name);
23
-
24
- if (existsSync(keystorePath) && !options.overwrite) {
25
- this.failSpinner(`Account '${options.name}' already exists. Use '--overwrite' to replace.`);
26
- }
27
-
28
- let privateKey: string;
29
-
30
- if (options.keystore) {
31
- privateKey = await this.importFromKeystore(options.keystore, options.sourcePassword);
32
- } else if (options.privateKey) {
33
- const normalizedKey = this.normalizePrivateKey(options.privateKey);
34
- this.validatePrivateKey(normalizedKey);
35
- privateKey = normalizedKey;
36
- } else {
37
- const inputKey = await this.promptPrivateKey();
38
- const normalizedKey = this.normalizePrivateKey(inputKey);
39
- this.validatePrivateKey(normalizedKey);
40
- privateKey = normalizedKey;
41
- }
42
-
43
- const wallet = new ethers.Wallet(privateKey);
44
-
45
- let password: string;
46
- if (options.password) {
47
- password = options.password;
48
- } else {
49
- password = await this.promptPassword("Enter a password to encrypt your keystore (minimum 8 characters):");
50
- const confirmPassword = await this.promptPassword("Confirm password:");
51
- if (password !== confirmPassword) {
52
- this.failSpinner("Passwords do not match");
53
- }
54
- }
55
-
56
- if (password.length < BaseAction.MIN_PASSWORD_LENGTH) {
57
- this.failSpinner(`Password must be at least ${BaseAction.MIN_PASSWORD_LENGTH} characters long`);
58
- }
59
-
60
- this.startSpinner(`Importing account '${options.name}'...`);
61
-
62
- const encryptedJson = await wallet.encrypt(password);
63
-
64
- // Write standard web3 keystore format directly
65
- writeFileSync(keystorePath, encryptedJson);
66
-
67
- if (options.setActive !== false) {
68
- this.setActiveAccount(options.name);
69
- }
70
-
71
- await this.keychainManager.removePrivateKey(options.name);
72
-
73
- this.succeedSpinner(`Account '${options.name}' imported to: ${keystorePath}`);
74
- this.logInfo(`Address: ${wallet.address}`);
75
- } catch (error) {
76
- this.failSpinner("Failed to import account", error);
77
- }
78
- }
79
-
80
- private async importFromKeystore(keystorePath: string, sourcePassword?: string): Promise<string> {
81
- if (!existsSync(keystorePath)) {
82
- this.failSpinner(`Keystore file not found: ${keystorePath}`);
83
- }
84
-
85
- const fileContent = readFileSync(keystorePath, "utf-8");
86
- let encryptedJson: string;
87
-
88
- try {
89
- const parsed = JSON.parse(fileContent);
90
-
91
- // Check if it's our format (with 'encrypted' field) or standard web3 keystore
92
- if (parsed.encrypted) {
93
- // Our format
94
- encryptedJson = parsed.encrypted;
95
- } else if (parsed.crypto || parsed.Crypto) {
96
- // Standard web3 keystore format (geth, foundry, etc.)
97
- encryptedJson = fileContent;
98
- } else {
99
- this.failSpinner("Invalid keystore format. Expected encrypted keystore file.");
100
- }
101
- } catch {
102
- this.failSpinner("Invalid keystore file. Could not parse JSON.");
103
- }
104
-
105
- const password = sourcePassword || await this.promptPassword("Enter password to decrypt keystore:");
106
-
107
- this.startSpinner("Decrypting keystore...");
108
-
109
- try {
110
- const wallet = await ethers.Wallet.fromEncryptedJson(encryptedJson!, password);
111
- this.stopSpinner();
112
- return wallet.privateKey;
113
- } catch {
114
- this.failSpinner("Failed to decrypt keystore. Wrong password?");
115
- }
116
-
117
- // This line is unreachable but TypeScript needs it
118
- throw new Error("Unreachable");
119
- }
120
-
121
- private async promptPrivateKey(): Promise<string> {
122
- return this.promptPassword("Enter private key to import:");
123
- }
124
-
125
- private normalizePrivateKey(key: string): string {
126
- const trimmed = key.trim();
127
- return trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
128
- }
129
-
130
- private validatePrivateKey(key: string): void {
131
- if (!/^0x[0-9a-fA-F]{64}$/.test(key)) {
132
- this.failSpinner("Invalid private key format. Expected 64 hex characters (with or without 0x prefix).");
133
- }
134
- }
135
- }
@@ -1,129 +0,0 @@
1
- import {Command} from "commander";
2
- import {ShowAccountAction, ShowAccountOptions} from "./show";
3
- import {CreateAccountAction, CreateAccountOptions} from "./create";
4
- import {ImportAccountAction, ImportAccountOptions} from "./import";
5
- import {ExportAccountAction, ExportAccountOptions} from "./export";
6
- import {UnlockAccountAction, UnlockAccountOptions} from "./unlock";
7
- import {LockAccountAction, LockAccountOptions} from "./lock";
8
- import {SendAction, SendOptions} from "./send";
9
- import {ListAccountsAction} from "./list";
10
- import {UseAccountAction} from "./use";
11
- import {RemoveAccountAction} from "./remove";
12
-
13
- export function initializeAccountCommands(program: Command) {
14
- const accountCommand = program
15
- .command("account")
16
- .description("Manage your accounts (address, balance, keys)")
17
- .action(async () => {
18
- // Default action: show account info (use 'account show' for options)
19
- const showAction = new ShowAccountAction();
20
- await showAction.execute({});
21
- });
22
-
23
- accountCommand
24
- .command("list")
25
- .description("List all accounts")
26
- .action(async () => {
27
- const listAction = new ListAccountsAction();
28
- await listAction.execute();
29
- });
30
-
31
- accountCommand
32
- .command("show")
33
- .description("Show account details (address, balance)")
34
- .option("--rpc <rpcUrl>", "RPC URL for the network")
35
- .option("--account <name>", "Account to show")
36
- .action(async (options: ShowAccountOptions) => {
37
- const showAction = new ShowAccountAction();
38
- await showAction.execute(options);
39
- });
40
-
41
- accountCommand
42
- .command("create")
43
- .description("Create a new account with encrypted keystore")
44
- .requiredOption("--name <name>", "Name for the account")
45
- .option("--password <password>", "Password for the keystore (skips interactive prompt)")
46
- .option("--overwrite", "Overwrite existing account", false)
47
- .option("--no-set-active", "Do not set as active account")
48
- .action(async (options: CreateAccountOptions) => {
49
- const createAction = new CreateAccountAction();
50
- await createAction.execute(options);
51
- });
52
-
53
- accountCommand
54
- .command("import")
55
- .description("Import an account from a private key or keystore file")
56
- .requiredOption("--name <name>", "Name for the account")
57
- .option("--private-key <key>", "Private key to import")
58
- .option("--keystore <path>", "Path to keystore file to import (geth, foundry, etc.)")
59
- .option("--password <password>", "Password for the new keystore (skips confirmation prompt)")
60
- .option("--source-password <password>", "Password to decrypt source keystore (with --keystore)")
61
- .option("--overwrite", "Overwrite existing account", false)
62
- .option("--no-set-active", "Do not set as active account")
63
- .action(async (options: ImportAccountOptions) => {
64
- const importAction = new ImportAccountAction();
65
- await importAction.execute(options);
66
- });
67
-
68
- accountCommand
69
- .command("export")
70
- .description("Export an account to a keystore file (web3/geth/foundry compatible)")
71
- .requiredOption("--output <path>", "Output path for the keystore file")
72
- .option("--account <name>", "Account to export (defaults to active account)")
73
- .option("--password <password>", "Password for exported keystore (skips confirmation)")
74
- .option("--source-password <password>", "Password to decrypt account (if not unlocked)")
75
- .action(async (options: ExportAccountOptions) => {
76
- const exportAction = new ExportAccountAction();
77
- await exportAction.execute(options);
78
- });
79
-
80
- accountCommand
81
- .command("use <name>")
82
- .description("Set the active account")
83
- .action(async (name: string) => {
84
- const useAction = new UseAccountAction();
85
- await useAction.execute(name);
86
- });
87
-
88
- accountCommand
89
- .command("remove <name>")
90
- .description("Remove an account")
91
- .option("--force", "Skip confirmation prompt", false)
92
- .action(async (name: string, options: {force?: boolean}) => {
93
- const removeAction = new RemoveAccountAction();
94
- await removeAction.execute(name, options);
95
- });
96
-
97
- accountCommand
98
- .command("send <to> <amount>")
99
- .description("Send GEN to an address")
100
- .option("--rpc <rpcUrl>", "RPC URL for the network")
101
- .option("--network <network>", "Network to use (localnet, testnet-asimov)")
102
- .option("--account <name>", "Account to send from")
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}) => {
105
- const sendAction = new SendAction();
106
- await sendAction.execute({to, amount, rpc: options.rpc, network: options.network, account: options.account, password: options.password});
107
- });
108
-
109
- accountCommand
110
- .command("unlock")
111
- .description("Unlock account by caching private key in OS keychain")
112
- .option("--account <name>", "Account to unlock")
113
- .option("--password <password>", "Password to unlock account (skips interactive prompt)")
114
- .action(async (options: UnlockAccountOptions) => {
115
- const unlockAction = new UnlockAccountAction();
116
- await unlockAction.execute(options);
117
- });
118
-
119
- accountCommand
120
- .command("lock")
121
- .description("Lock account by removing private key from OS keychain")
122
- .option("--account <name>", "Account to lock")
123
- .action(async (options: LockAccountOptions) => {
124
- const lockAction = new LockAccountAction();
125
- await lockAction.execute(options);
126
- });
127
-
128
- return program;
129
- }
@@ -1,34 +0,0 @@
1
- import {BaseAction} from "../../lib/actions/BaseAction";
2
-
3
- export class ListAccountsAction extends BaseAction {
4
- constructor() {
5
- super();
6
- }
7
-
8
- async execute(): Promise<void> {
9
- try {
10
- const accounts = this.listAccounts();
11
- const activeAccount = this.getActiveAccount();
12
- const unlockedAccounts = await this.keychainManager.listUnlockedAccounts();
13
-
14
- if (accounts.length === 0) {
15
- this.logInfo("No accounts found. Run 'genlayer account create --name <name>' to create one.");
16
- return;
17
- }
18
-
19
- console.log("");
20
- for (const account of accounts) {
21
- const isActive = account.name === activeAccount;
22
- const isUnlocked = unlockedAccounts.includes(account.name);
23
- const marker = isActive ? "*" : " ";
24
- const status = isUnlocked ? "(unlocked)" : "";
25
- const activeLabel = isActive ? "(active)" : "";
26
-
27
- console.log(`${marker} ${account.name.padEnd(16)} ${account.address} ${activeLabel} ${status}`.trim());
28
- }
29
- console.log("");
30
- } catch (error) {
31
- this.failSpinner("Failed to list accounts", error);
32
- }
33
- }
34
- }
@@ -1,39 +0,0 @@
1
- import {BaseAction} from "../../lib/actions/BaseAction";
2
-
3
- export interface LockAccountOptions {
4
- account?: string;
5
- }
6
-
7
- export class LockAccountAction extends BaseAction {
8
- async execute(options?: LockAccountOptions): Promise<void> {
9
- this.startSpinner("Checking keychain availability...");
10
-
11
- const keychainAvailable = await this.keychainManager.isKeychainAvailable();
12
- if (!keychainAvailable) {
13
- this.failSpinner("OS keychain is not available. This command requires a supported keychain (e.g. macOS Keychain, Windows Credential Manager, or GNOME Keyring).");
14
- return;
15
- }
16
-
17
- if (options?.account) {
18
- this.accountOverride = options.account;
19
- }
20
-
21
- const accountName = this.resolveAccountName();
22
- this.setSpinnerText(`Checking for cached private key for '${accountName}'...`);
23
-
24
- const hasCachedKey = await this.keychainManager.getPrivateKey(accountName);
25
- if (!hasCachedKey) {
26
- this.succeedSpinner(`Account '${accountName}' is already locked.`);
27
- return;
28
- }
29
-
30
- this.setSpinnerText(`Removing private key for '${accountName}' from OS keychain...`);
31
-
32
- try {
33
- await this.keychainManager.removePrivateKey(accountName);
34
- this.succeedSpinner(`Account '${accountName}' locked! Private key removed from OS keychain.`);
35
- } catch (error) {
36
- this.failSpinner("Failed to lock account.", error);
37
- }
38
- }
39
- }
@@ -1,30 +0,0 @@
1
- import {BaseAction} from "../../lib/actions/BaseAction";
2
-
3
- export class RemoveAccountAction extends BaseAction {
4
- constructor() {
5
- super();
6
- }
7
-
8
- async execute(name: string, options: {force?: boolean}): Promise<void> {
9
- try {
10
- if (!this.accountExists(name)) {
11
- this.failSpinner(`Account '${name}' does not exist.`);
12
- return;
13
- }
14
-
15
- if (!options.force) {
16
- await this.confirmPrompt(`Are you sure you want to remove account '${name}'? This cannot be undone.`);
17
- }
18
-
19
- // Remove from keychain if unlocked
20
- await this.keychainManager.removePrivateKey(name);
21
-
22
- // Remove keystore file
23
- this.removeAccount(name);
24
-
25
- this.logSuccess(`Account '${name}' removed`);
26
- } catch (error) {
27
- this.failSpinner("Failed to remove account", error);
28
- }
29
- }
30
- }