@grimoirelabs/cli 0.14.2 → 0.15.1

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 (111) hide show
  1. package/dist/commands/advisory-handlers.d.ts.map +1 -1
  2. package/dist/commands/advisory-handlers.js +1 -180
  3. package/dist/commands/advisory-handlers.js.map +1 -1
  4. package/dist/commands/advisory-live-trace.d.ts.map +1 -1
  5. package/dist/commands/advisory-live-trace.js +1 -1
  6. package/dist/commands/advisory-live-trace.js.map +1 -1
  7. package/dist/commands/advisory-verbose-trace.d.ts +15 -0
  8. package/dist/commands/advisory-verbose-trace.d.ts.map +1 -0
  9. package/dist/commands/advisory-verbose-trace.js +185 -0
  10. package/dist/commands/advisory-verbose-trace.js.map +1 -0
  11. package/dist/commands/cast-cross-chain.d.ts +69 -0
  12. package/dist/commands/cast-cross-chain.d.ts.map +1 -0
  13. package/dist/commands/cast-cross-chain.js +456 -0
  14. package/dist/commands/cast-cross-chain.js.map +1 -0
  15. package/dist/commands/cast.d.ts +1 -1
  16. package/dist/commands/cast.d.ts.map +1 -1
  17. package/dist/commands/cast.js +84 -709
  18. package/dist/commands/cast.js.map +1 -1
  19. package/dist/commands/compile-all.d.ts +15 -2
  20. package/dist/commands/compile-all.d.ts.map +1 -1
  21. package/dist/commands/compile-all.js +16 -21
  22. package/dist/commands/compile-all.js.map +1 -1
  23. package/dist/commands/compile.d.ts +1 -1
  24. package/dist/commands/compile.d.ts.map +1 -1
  25. package/dist/commands/compile.js +22 -26
  26. package/dist/commands/compile.js.map +1 -1
  27. package/dist/commands/cross-chain-helpers.d.ts +0 -1
  28. package/dist/commands/cross-chain-helpers.d.ts.map +1 -1
  29. package/dist/commands/cross-chain-helpers.js +0 -3
  30. package/dist/commands/cross-chain-helpers.js.map +1 -1
  31. package/dist/commands/history.d.ts +1 -2
  32. package/dist/commands/history.d.ts.map +1 -1
  33. package/dist/commands/history.js +59 -69
  34. package/dist/commands/history.js.map +1 -1
  35. package/dist/commands/init.d.ts +5 -1
  36. package/dist/commands/init.d.ts.map +1 -1
  37. package/dist/commands/init.js +25 -20
  38. package/dist/commands/init.js.map +1 -1
  39. package/dist/commands/log.d.ts +1 -2
  40. package/dist/commands/log.d.ts.map +1 -1
  41. package/dist/commands/log.js +9 -12
  42. package/dist/commands/log.js.map +1 -1
  43. package/dist/commands/resume.d.ts +18 -1
  44. package/dist/commands/resume.d.ts.map +1 -1
  45. package/dist/commands/resume.js +44 -66
  46. package/dist/commands/resume.js.map +1 -1
  47. package/dist/commands/setup-ui.d.ts +46 -0
  48. package/dist/commands/setup-ui.d.ts.map +1 -0
  49. package/dist/commands/setup-ui.js +221 -0
  50. package/dist/commands/setup-ui.js.map +1 -0
  51. package/dist/commands/setup.d.ts +31 -3
  52. package/dist/commands/setup.d.ts.map +1 -1
  53. package/dist/commands/setup.js +27 -270
  54. package/dist/commands/setup.js.map +1 -1
  55. package/dist/commands/simulate-cross-chain.d.ts +53 -0
  56. package/dist/commands/simulate-cross-chain.d.ts.map +1 -0
  57. package/dist/commands/simulate-cross-chain.js +256 -0
  58. package/dist/commands/simulate-cross-chain.js.map +1 -0
  59. package/dist/commands/simulate.d.ts +5 -1
  60. package/dist/commands/simulate.d.ts.map +1 -1
  61. package/dist/commands/simulate.js +16 -364
  62. package/dist/commands/simulate.js.map +1 -1
  63. package/dist/commands/state-helpers.d.ts.map +1 -1
  64. package/dist/commands/state-helpers.js +1 -5
  65. package/dist/commands/state-helpers.js.map +1 -1
  66. package/dist/commands/validate.d.ts +24 -2
  67. package/dist/commands/validate.d.ts.map +1 -1
  68. package/dist/commands/validate.js +40 -42
  69. package/dist/commands/validate.js.map +1 -1
  70. package/dist/commands/venue-doctor-morpho.d.ts +38 -0
  71. package/dist/commands/venue-doctor-morpho.d.ts.map +1 -0
  72. package/dist/commands/venue-doctor-morpho.js +214 -0
  73. package/dist/commands/venue-doctor-morpho.js.map +1 -0
  74. package/dist/commands/venue-doctor.d.ts +2 -26
  75. package/dist/commands/venue-doctor.d.ts.map +1 -1
  76. package/dist/commands/venue-doctor.js +17 -221
  77. package/dist/commands/venue-doctor.js.map +1 -1
  78. package/dist/commands/venue.d.ts.map +1 -1
  79. package/dist/commands/venue.js +11 -19
  80. package/dist/commands/venue.js.map +1 -1
  81. package/dist/commands/venues.d.ts +1 -5
  82. package/dist/commands/venues.d.ts.map +1 -1
  83. package/dist/commands/venues.js +5 -8
  84. package/dist/commands/venues.js.map +1 -1
  85. package/dist/commands/wallet-weth.d.ts +22 -0
  86. package/dist/commands/wallet-weth.d.ts.map +1 -0
  87. package/dist/commands/wallet-weth.js +150 -0
  88. package/dist/commands/wallet-weth.js.map +1 -0
  89. package/dist/commands/wallet.d.ts +65 -3
  90. package/dist/commands/wallet.d.ts.map +1 -1
  91. package/dist/commands/wallet.js +183 -377
  92. package/dist/commands/wallet.js.map +1 -1
  93. package/dist/index.js +375 -170
  94. package/dist/index.js.map +1 -1
  95. package/dist/lib/execution-helpers.d.ts +24 -0
  96. package/dist/lib/execution-helpers.d.ts.map +1 -0
  97. package/dist/lib/execution-helpers.js +133 -0
  98. package/dist/lib/execution-helpers.js.map +1 -0
  99. package/dist/lib/json.d.ts +8 -0
  100. package/dist/lib/json.d.ts.map +1 -0
  101. package/dist/lib/json.js +10 -0
  102. package/dist/lib/json.js.map +1 -0
  103. package/dist/lib/keystore.d.ts +12 -0
  104. package/dist/lib/keystore.d.ts.map +1 -0
  105. package/dist/lib/keystore.js +14 -0
  106. package/dist/lib/keystore.js.map +1 -0
  107. package/dist/lib/prompts.d.ts +16 -0
  108. package/dist/lib/prompts.d.ts.map +1 -0
  109. package/dist/lib/prompts.js +61 -0
  110. package/dist/lib/prompts.js.map +1 -0
  111. package/package.json +4 -4
@@ -1,47 +1,16 @@
1
1
  /**
2
2
  * Wallet Command
3
- * Manage wallet lifecycle: generate, address, balance, import
3
+ * Manage wallet lifecycle: generate, address, balance, import, wrap, unwrap
4
4
  */
5
5
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
- import { homedir } from "node:os";
7
- import { dirname, join } from "node:path";
8
- import * as readline from "node:readline";
9
- import { Writable } from "node:stream";
10
- import { createKeystore, createProvider, createWalletFromConfig, formatWei, generatePrivateKey, getAddressFromConfig, getChainName, getNativeCurrencySymbol, } from "@grimoirelabs/core";
6
+ import { dirname } from "node:path";
7
+ import { createKeystore, createProvider, formatWei, generatePrivateKey, getAddressFromConfig, getChainName, getNativeCurrencySymbol, } from "@grimoirelabs/core";
11
8
  import chalk from "chalk";
12
- import { Command } from "commander";
9
+ import { Cli, z } from "incur";
13
10
  import ora from "ora";
14
- const DEFAULT_KEYSTORE_DIR = join(homedir(), ".grimoire");
15
- const DEFAULT_KEYSTORE_PATH = join(DEFAULT_KEYSTORE_DIR, "keystore.json");
16
- /**
17
- * Resolve the keystore file path from options or default
18
- */
19
- function resolveKeystorePath(options) {
20
- return options.keystore ?? DEFAULT_KEYSTORE_PATH;
21
- }
22
- /**
23
- * Prompt for a password interactively (hides input)
24
- */
25
- async function promptPassword(message) {
26
- return new Promise((resolve) => {
27
- process.stdout.write(message);
28
- const silentOutput = new Writable({
29
- write(_chunk, _encoding, cb) {
30
- cb();
31
- },
32
- });
33
- const rl = readline.createInterface({
34
- input: process.stdin,
35
- output: silentOutput,
36
- terminal: true,
37
- });
38
- rl.question("", (answer) => {
39
- rl.close();
40
- process.stdout.write("\n");
41
- resolve(answer);
42
- });
43
- });
44
- }
11
+ import { resolveKeystorePath } from "../lib/keystore.js";
12
+ import { promptPassword } from "../lib/prompts.js";
13
+ import { unwrapAction, wrapAction } from "./wallet-weth.js";
45
14
  /**
46
15
  * Resolve keystore password from env var, interactive prompt, or error
47
16
  */
@@ -78,360 +47,197 @@ async function resolveNewKeystorePassword(options) {
78
47
  }
79
48
  throw new Error(`No password available. Set ${envName} or run interactively.`);
80
49
  }
81
- // ── Subcommands ─────────────────────────────────────────────────────
82
- async function generateAction(options) {
50
+ // ── Subcommand handlers ────────────────────────────────────────────
51
+ async function generateHandler(options) {
83
52
  const spinner = ora("Generating wallet...").start();
84
- try {
85
- // 1. Generate key
86
- const privateKey = generatePrivateKey();
87
- // 2. Derive address (use viem via getAddressFromConfig with raw key)
88
- const address = getAddressFromConfig({ type: "raw", source: privateKey });
89
- spinner.text = "Waiting for password...";
90
- spinner.stop();
91
- // 3. Prompt password
92
- const password = await resolveNewKeystorePassword(options);
93
- spinner.start("Encrypting keystore...");
94
- // 4. Encrypt
95
- const keystoreJson = await createKeystore(privateKey, password);
96
- // 5. Write file
97
- const keystorePath = resolveKeystorePath(options);
98
- const dir = dirname(keystorePath);
99
- if (!existsSync(dir)) {
100
- mkdirSync(dir, { recursive: true });
101
- }
102
- writeFileSync(keystorePath, keystoreJson, "utf-8");
103
- spinner.succeed(chalk.green("Wallet generated"));
104
- if (options.json) {
105
- const output = {
106
- address,
107
- keystore: keystorePath,
108
- };
109
- if (options.printKey) {
110
- output.privateKey = privateKey;
111
- }
112
- console.log(JSON.stringify(output, null, 2));
113
- }
114
- else {
115
- console.log(` ${chalk.dim("Address:")} ${address}`);
116
- console.log(` ${chalk.dim("Keystore:")} ${keystorePath}`);
117
- if (options.printKey) {
118
- console.log();
119
- console.log(chalk.yellow(" WARNING: Store this private key securely. It will not be shown again."));
120
- console.log(` ${chalk.dim("Private key:")} ${privateKey}`);
121
- }
122
- }
123
- }
124
- catch (error) {
125
- spinner.fail(chalk.red(`Failed: ${error.message}`));
126
- process.exit(1);
127
- }
53
+ const privateKey = generatePrivateKey();
54
+ const address = getAddressFromConfig({ type: "raw", source: privateKey });
55
+ spinner.text = "Waiting for password...";
56
+ spinner.stop();
57
+ const password = await resolveNewKeystorePassword(options);
58
+ spinner.start("Encrypting keystore...");
59
+ const keystoreJson = await createKeystore(privateKey, password);
60
+ const keystorePath = resolveKeystorePath(options);
61
+ const dir = dirname(keystorePath);
62
+ if (!existsSync(dir)) {
63
+ mkdirSync(dir, { recursive: true });
64
+ }
65
+ writeFileSync(keystorePath, keystoreJson, "utf-8");
66
+ spinner.succeed(chalk.green("Wallet generated"));
67
+ const output = { address, keystore: keystorePath };
68
+ if (options.printKey) {
69
+ console.error();
70
+ console.error(chalk.yellow(" WARNING: Store this private key securely. It will not be shown again."));
71
+ console.error(` ${chalk.dim("Private key:")} ${privateKey}`);
72
+ output.privateKey = privateKey;
73
+ }
74
+ else {
75
+ console.error(` ${chalk.dim("Address:")} ${address}`);
76
+ console.error(` ${chalk.dim("Keystore:")} ${keystorePath}`);
77
+ }
78
+ return output;
128
79
  }
129
- async function addressAction(options) {
130
- try {
131
- let keyConfig;
132
- if (options.mnemonic) {
133
- keyConfig = { type: "mnemonic", source: options.mnemonic };
134
- }
135
- else if (options.keyEnv) {
136
- keyConfig = { type: "env", source: options.keyEnv };
137
- }
138
- else {
139
- // Default: keystore
140
- const keystorePath = resolveKeystorePath(options);
141
- if (!existsSync(keystorePath)) {
142
- console.error(chalk.red(`Keystore not found: ${keystorePath}`));
143
- console.error(chalk.dim("Run 'grimoire wallet generate' to create one."));
144
- process.exit(1);
145
- }
146
- const password = await resolveKeystorePassword(options);
147
- const keystoreJson = readFileSync(keystorePath, "utf-8");
148
- keyConfig = { type: "keystore", source: keystoreJson, password };
149
- }
150
- const address = getAddressFromConfig(keyConfig);
151
- if (options.json) {
152
- console.log(JSON.stringify({ address }));
153
- }
154
- else {
155
- console.log(address);
156
- }
80
+ async function addressHandler(options) {
81
+ let keyConfig;
82
+ if (options.mnemonic) {
83
+ keyConfig = { type: "mnemonic", source: options.mnemonic };
157
84
  }
158
- catch (error) {
159
- console.error(chalk.red(`Failed: ${error.message}`));
160
- process.exit(1);
85
+ else if (options.keyEnv) {
86
+ keyConfig = { type: "env", source: options.keyEnv };
161
87
  }
162
- }
163
- async function balanceAction(options) {
164
- try {
165
- let keyConfig;
166
- if (options.mnemonic) {
167
- keyConfig = { type: "mnemonic", source: options.mnemonic };
168
- }
169
- else if (options.keyEnv) {
170
- keyConfig = { type: "env", source: options.keyEnv };
171
- }
172
- else {
173
- const keystorePath = resolveKeystorePath(options);
174
- if (!existsSync(keystorePath)) {
175
- console.error(chalk.red(`Keystore not found: ${keystorePath}`));
176
- console.error(chalk.dim("Run 'grimoire wallet generate' to create one."));
177
- process.exit(1);
178
- }
179
- const password = await resolveKeystorePassword(options);
180
- const keystoreJson = readFileSync(keystorePath, "utf-8");
181
- keyConfig = { type: "keystore", source: keystoreJson, password };
182
- }
183
- const address = getAddressFromConfig(keyConfig);
184
- const chainId = Number.parseInt(options.chain ?? "1", 10);
185
- const chainName = getChainName(chainId);
186
- const spinner = ora(`Fetching balance on ${chainName}...`).start();
187
- const provider = createProvider(chainId, options.rpcUrl);
188
- const balance = await provider.getBalance(address);
189
- spinner.succeed(chalk.green("Balance retrieved"));
190
- if (options.json) {
191
- console.log(JSON.stringify({
192
- address,
193
- chain: chainId,
194
- chainName,
195
- balanceWei: balance.toString(),
196
- balance: formatWei(balance),
197
- }));
198
- }
199
- else {
200
- console.log(` ${chalk.dim("Address:")} ${address}`);
201
- console.log(` ${chalk.dim("Chain:")} ${chainName} (${chainId})`);
202
- console.log(` ${chalk.dim("Balance:")} ${formatWei(balance)} ${getNativeCurrencySymbol(chainId)}`);
203
- }
204
- }
205
- catch (error) {
206
- console.error(chalk.red(`Failed: ${error.message}`));
207
- process.exit(1);
208
- }
209
- }
210
- async function importAction(options) {
211
- const spinner = ora("Importing wallet...").start();
212
- try {
213
- // Load existing key from env
214
- const envName = options.keyEnv ?? "PRIVATE_KEY";
215
- const rawKey = process.env[envName];
216
- if (!rawKey) {
217
- spinner.fail(chalk.red(`Environment variable ${envName} is not set`));
218
- process.exit(1);
219
- }
220
- // Derive address for validation
221
- const address = getAddressFromConfig({ type: "raw", source: rawKey });
222
- spinner.text = "Waiting for password...";
223
- spinner.stop();
224
- // Prompt new keystore password
225
- const password = await resolveNewKeystorePassword(options);
226
- spinner.start("Encrypting keystore...");
227
- // Normalize key
228
- const normalizedKey = rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`;
229
- // Encrypt
230
- const keystoreJson = await createKeystore(normalizedKey, password);
231
- // Write file
232
- const keystorePath = resolveKeystorePath(options);
233
- const dir = dirname(keystorePath);
234
- if (!existsSync(dir)) {
235
- mkdirSync(dir, { recursive: true });
236
- }
237
- writeFileSync(keystorePath, keystoreJson, "utf-8");
238
- spinner.succeed(chalk.green("Wallet imported"));
239
- if (options.json) {
240
- console.log(JSON.stringify({ address, keystore: keystorePath }));
241
- }
242
- else {
243
- console.log(` ${chalk.dim("Address:")} ${address}`);
244
- console.log(` ${chalk.dim("Keystore:")} ${keystorePath}`);
245
- }
246
- }
247
- catch (error) {
248
- spinner.fail(chalk.red(`Failed: ${error.message}`));
249
- process.exit(1);
250
- }
251
- }
252
- // ── WETH Constants ──────────────────────────────────────────────────
253
- const WETH_ADDRESSES = {
254
- 1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
255
- 8453: "0x4200000000000000000000000000000000000006",
256
- 10: "0x4200000000000000000000000000000000000006",
257
- 42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
258
- };
259
- const WETH_DEPOSIT_SELECTOR = "0xd0e30db0";
260
- const WETH_WITHDRAW_SELECTOR = "0x2e1a7d4d";
261
- function ethToWei(eth) {
262
- const [whole = "0", frac = ""] = eth.split(".");
263
- const padded = frac.padEnd(18, "0").slice(0, 18);
264
- return BigInt(whole) * 10n ** 18n + BigInt(padded);
265
- }
266
- async function wrapAction(options) {
267
- try {
88
+ else {
268
89
  const keystorePath = resolveKeystorePath(options);
269
90
  if (!existsSync(keystorePath)) {
270
- console.error(chalk.red(`Keystore not found: ${keystorePath}`));
271
- console.error(chalk.dim("Run 'grimoire wallet generate' to create one."));
272
- process.exit(1);
91
+ throw new Error(`Keystore not found: ${keystorePath}. Run 'grimoire wallet generate' to create one.`);
273
92
  }
274
93
  const password = await resolveKeystorePassword(options);
275
94
  const keystoreJson = readFileSync(keystorePath, "utf-8");
276
- const keyConfig = { type: "keystore", source: keystoreJson, password };
277
- const chainId = Number.parseInt(options.chain ?? "8453", 10);
278
- const nativeSymbol = getNativeCurrencySymbol(chainId);
279
- if (nativeSymbol !== "ETH") {
280
- console.error(chalk.red(`WETH only exists on ETH-native chains. Chain ${chainId} uses ${nativeSymbol}.`));
281
- process.exit(1);
282
- }
283
- const wethAddress = WETH_ADDRESSES[chainId];
284
- if (!wethAddress) {
285
- console.error(chalk.red(`No known WETH address for chain ${chainId}`));
286
- process.exit(1);
287
- }
288
- const provider = createProvider(chainId, options.rpcUrl);
289
- const wallet = createWalletFromConfig(keyConfig, chainId, provider.rpcUrl);
290
- const amountWei = ethToWei(options.amount);
291
- const spinner = ora(`Wrapping ${options.amount} ETH → WETH on chain ${chainId}...`).start();
292
- const receipt = await wallet.sendTransaction({
293
- to: wethAddress,
294
- value: amountWei,
295
- data: WETH_DEPOSIT_SELECTOR,
296
- });
297
- if (receipt.status === "reverted") {
298
- spinner.fail(chalk.red("Transaction reverted"));
299
- console.error(` Tx: ${receipt.hash}`);
300
- process.exit(1);
301
- }
302
- spinner.succeed(chalk.green(`Wrapped ${options.amount} ETH → WETH`));
303
- const balance = await provider.getBalance(wallet.address);
304
- if (options.json) {
305
- console.log(JSON.stringify({
306
- tx: receipt.hash,
307
- amount: options.amount,
308
- chain: chainId,
309
- balance: formatWei(balance),
310
- }));
311
- }
312
- else {
313
- console.log(` ${chalk.dim("Tx:")} ${receipt.hash}`);
314
- console.log(` ${chalk.dim("Balance:")} ${formatWei(balance)} ETH`);
315
- }
316
- }
317
- catch (error) {
318
- console.error(chalk.red(`Failed: ${error.message}`));
319
- process.exit(1);
95
+ keyConfig = { type: "keystore", source: keystoreJson, password };
320
96
  }
97
+ const address = getAddressFromConfig(keyConfig);
98
+ console.error(address);
99
+ return { address };
321
100
  }
322
- async function unwrapAction(options) {
323
- try {
101
+ async function balanceHandler(options) {
102
+ let keyConfig;
103
+ if (options.mnemonic) {
104
+ keyConfig = { type: "mnemonic", source: options.mnemonic };
105
+ }
106
+ else if (options.keyEnv) {
107
+ keyConfig = { type: "env", source: options.keyEnv };
108
+ }
109
+ else {
324
110
  const keystorePath = resolveKeystorePath(options);
325
111
  if (!existsSync(keystorePath)) {
326
- console.error(chalk.red(`Keystore not found: ${keystorePath}`));
327
- console.error(chalk.dim("Run 'grimoire wallet generate' to create one."));
328
- process.exit(1);
112
+ throw new Error(`Keystore not found: ${keystorePath}. Run 'grimoire wallet generate' to create one.`);
329
113
  }
330
114
  const password = await resolveKeystorePassword(options);
331
115
  const keystoreJson = readFileSync(keystorePath, "utf-8");
332
- const keyConfig = { type: "keystore", source: keystoreJson, password };
333
- const chainId = Number.parseInt(options.chain ?? "8453", 10);
334
- const nativeSymbol = getNativeCurrencySymbol(chainId);
335
- if (nativeSymbol !== "ETH") {
336
- console.error(chalk.red(`WETH only exists on ETH-native chains. Chain ${chainId} uses ${nativeSymbol}.`));
337
- process.exit(1);
338
- }
339
- const wethAddress = WETH_ADDRESSES[chainId];
340
- if (!wethAddress) {
341
- console.error(chalk.red(`No known WETH address for chain ${chainId}`));
342
- process.exit(1);
343
- }
344
- const provider = createProvider(chainId, options.rpcUrl);
345
- const wallet = createWalletFromConfig(keyConfig, chainId, provider.rpcUrl);
346
- const amountWei = ethToWei(options.amount);
347
- const amountHex = amountWei.toString(16).padStart(64, "0");
348
- const data = `${WETH_WITHDRAW_SELECTOR}${amountHex}`;
349
- const spinner = ora(`Unwrapping ${options.amount} WETH → ETH on chain ${chainId}...`).start();
350
- const receipt = await wallet.sendTransaction({
351
- to: wethAddress,
352
- data,
353
- });
354
- if (receipt.status === "reverted") {
355
- spinner.fail(chalk.red("Transaction reverted"));
356
- console.error(` Tx: ${receipt.hash}`);
357
- process.exit(1);
358
- }
359
- spinner.succeed(chalk.green(`Unwrapped ${options.amount} WETH → ETH`));
360
- const balance = await provider.getBalance(wallet.address);
361
- if (options.json) {
362
- console.log(JSON.stringify({
363
- tx: receipt.hash,
364
- amount: options.amount,
365
- chain: chainId,
366
- balance: formatWei(balance),
367
- }));
368
- }
369
- else {
370
- console.log(` ${chalk.dim("Tx:")} ${receipt.hash}`);
371
- console.log(` ${chalk.dim("Balance:")} ${formatWei(balance)} ETH`);
372
- }
373
- }
374
- catch (error) {
375
- console.error(chalk.red(`Failed: ${error.message}`));
376
- process.exit(1);
377
- }
116
+ keyConfig = { type: "keystore", source: keystoreJson, password };
117
+ }
118
+ const address = getAddressFromConfig(keyConfig);
119
+ const chainId = Number.parseInt(options.chain ?? "1", 10);
120
+ const chainName = getChainName(chainId);
121
+ const spinner = ora(`Fetching balance on ${chainName}...`).start();
122
+ const provider = createProvider(chainId, options.rpcUrl);
123
+ const balance = await provider.getBalance(address);
124
+ spinner.succeed(chalk.green("Balance retrieved"));
125
+ console.error(` ${chalk.dim("Address:")} ${address}`);
126
+ console.error(` ${chalk.dim("Chain:")} ${chainName} (${chainId})`);
127
+ console.error(` ${chalk.dim("Balance:")} ${formatWei(balance)} ${getNativeCurrencySymbol(chainId)}`);
128
+ return {
129
+ address,
130
+ chain: chainId,
131
+ chainName,
132
+ balanceWei: balance.toString(),
133
+ balance: formatWei(balance),
134
+ };
135
+ }
136
+ async function importHandler(options) {
137
+ const spinner = ora("Importing wallet...").start();
138
+ const envName = options.keyEnv ?? "PRIVATE_KEY";
139
+ const rawKey = process.env[envName];
140
+ if (!rawKey) {
141
+ spinner.fail(chalk.red(`Environment variable ${envName} is not set`));
142
+ throw new Error(`Environment variable ${envName} is not set`);
143
+ }
144
+ const address = getAddressFromConfig({ type: "raw", source: rawKey });
145
+ spinner.text = "Waiting for password...";
146
+ spinner.stop();
147
+ const password = await resolveNewKeystorePassword(options);
148
+ spinner.start("Encrypting keystore...");
149
+ const normalizedKey = rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`;
150
+ const keystoreJson = await createKeystore(normalizedKey, password);
151
+ const keystorePath = resolveKeystorePath(options);
152
+ const dir = dirname(keystorePath);
153
+ if (!existsSync(dir)) {
154
+ mkdirSync(dir, { recursive: true });
155
+ }
156
+ writeFileSync(keystorePath, keystoreJson, "utf-8");
157
+ spinner.succeed(chalk.green("Wallet imported"));
158
+ console.error(` ${chalk.dim("Address:")} ${address}`);
159
+ console.error(` ${chalk.dim("Keystore:")} ${keystorePath}`);
160
+ return { address, keystore: keystorePath };
378
161
  }
379
- // ── Command tree ────────────────────────────────────────────────────
380
- export const walletCommand = new Command("wallet").description("Manage wallets and keystores");
381
- walletCommand
382
- .command("generate")
383
- .description("Generate a new wallet and save to keystore")
384
- .option("--keystore <path>", "Path to keystore file")
385
- .option("--password-env <name>", "Environment variable for keystore password")
386
- .option("--print-key", "Print the private key (one-time backup)")
387
- .option("--json", "Output as JSON")
388
- .action(generateAction);
389
- walletCommand
390
- .command("address")
391
- .description("Show wallet address")
392
- .option("--keystore <path>", "Path to keystore file")
393
- .option("--password-env <name>", "Environment variable for keystore password")
394
- .option("--key-env <name>", "Environment variable containing private key")
395
- .option("--mnemonic <phrase>", "Mnemonic phrase")
396
- .option("--json", "Output as JSON")
397
- .action(addressAction);
398
- walletCommand
399
- .command("balance")
400
- .description("Check wallet balance")
401
- .option("--keystore <path>", "Path to keystore file")
402
- .option("--password-env <name>", "Environment variable for keystore password")
403
- .option("--key-env <name>", "Environment variable containing private key")
404
- .option("--mnemonic <phrase>", "Mnemonic phrase")
405
- .option("--chain <id>", "Chain ID", "1")
406
- .option("--rpc-url <url>", "RPC URL")
407
- .option("--json", "Output as JSON")
408
- .action(balanceAction);
409
- walletCommand
410
- .command("import")
411
- .description("Import an existing private key into a keystore")
412
- .option("--keystore <path>", "Path to keystore file")
413
- .option("--password-env <name>", "Environment variable for keystore password")
414
- .option("--key-env <name>", "Environment variable containing private key", "PRIVATE_KEY")
415
- .option("--json", "Output as JSON")
416
- .action(importAction);
417
- walletCommand
418
- .command("wrap")
419
- .description("Wrap native currency to WETH")
420
- .requiredOption("--amount <eth>", "Amount to wrap")
421
- .option("--chain <id>", "Chain ID", "8453")
422
- .option("--keystore <path>", "Path to keystore file")
423
- .option("--password-env <name>", "Environment variable for keystore password")
424
- .option("--rpc-url <url>", "RPC URL")
425
- .option("--json", "Output as JSON")
426
- .action(wrapAction);
427
- walletCommand
428
- .command("unwrap")
429
- .description("Unwrap WETH to native currency")
430
- .requiredOption("--amount <eth>", "Amount to unwrap")
431
- .option("--chain <id>", "Chain ID", "8453")
432
- .option("--keystore <path>", "Path to keystore file")
433
- .option("--password-env <name>", "Environment variable for keystore password")
434
- .option("--rpc-url <url>", "RPC URL")
435
- .option("--json", "Output as JSON")
436
- .action(unwrapAction);
162
+ // ── Shared option schemas ──────────────────────────────────────────
163
+ const keystoreOptions = z.object({
164
+ keystore: z.string().optional().describe("Path to keystore file"),
165
+ passwordEnv: z.string().optional().describe("Environment variable for keystore password"),
166
+ });
167
+ // ── Incur CLI ──────────────────────────────────────────────────────
168
+ export const walletCli = Cli.create("wallet", {
169
+ description: "Manage wallets and keystores",
170
+ })
171
+ .command("generate", {
172
+ description: "Generate a new wallet and save to keystore",
173
+ options: keystoreOptions.extend({
174
+ printKey: z.boolean().optional().describe("Print the private key (one-time backup)"),
175
+ }),
176
+ async run(c) {
177
+ const result = await generateHandler(c.options);
178
+ return c.ok(result, { cta: { commands: ["wallet address", "wallet balance"] } });
179
+ },
180
+ })
181
+ .command("address", {
182
+ description: "Show wallet address",
183
+ options: keystoreOptions.extend({
184
+ keyEnv: z.string().optional().describe("Environment variable containing private key"),
185
+ mnemonic: z.string().optional().describe("Mnemonic phrase"),
186
+ }),
187
+ async run(c) {
188
+ const result = await addressHandler(c.options);
189
+ return c.ok(result);
190
+ },
191
+ })
192
+ .command("balance", {
193
+ description: "Check wallet balance",
194
+ options: keystoreOptions.extend({
195
+ keyEnv: z.string().optional().describe("Environment variable containing private key"),
196
+ mnemonic: z.string().optional().describe("Mnemonic phrase"),
197
+ chain: z.string().optional().default("1").describe("Chain ID"),
198
+ rpcUrl: z.string().optional().describe("RPC URL"),
199
+ }),
200
+ async run(c) {
201
+ const result = await balanceHandler(c.options);
202
+ return c.ok(result);
203
+ },
204
+ })
205
+ .command("import", {
206
+ description: "Import an existing private key into a keystore",
207
+ options: keystoreOptions.extend({
208
+ keyEnv: z
209
+ .string()
210
+ .optional()
211
+ .default("PRIVATE_KEY")
212
+ .describe("Environment variable containing private key"),
213
+ }),
214
+ async run(c) {
215
+ const result = await importHandler(c.options);
216
+ return c.ok(result, { cta: { commands: ["wallet balance"] } });
217
+ },
218
+ })
219
+ .command("wrap", {
220
+ description: "Wrap native currency to WETH",
221
+ options: keystoreOptions.extend({
222
+ amount: z.string().describe("Amount to wrap"),
223
+ chain: z.string().optional().default("8453").describe("Chain ID"),
224
+ rpcUrl: z.string().optional().describe("RPC URL"),
225
+ }),
226
+ async run(c) {
227
+ await wrapAction(c.options);
228
+ return c.ok({ success: true });
229
+ },
230
+ })
231
+ .command("unwrap", {
232
+ description: "Unwrap WETH to native currency",
233
+ options: keystoreOptions.extend({
234
+ amount: z.string().describe("Amount to unwrap"),
235
+ chain: z.string().optional().default("8453").describe("Chain ID"),
236
+ rpcUrl: z.string().optional().describe("RPC URL"),
237
+ }),
238
+ async run(c) {
239
+ await unwrapAction(c.options);
240
+ return c.ok({ success: true });
241
+ },
242
+ });
437
243
  //# sourceMappingURL=wallet.js.map