@elytro/cli 0.5.1 → 0.5.2
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/dist/index.js +229 -69
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -233,9 +233,9 @@ var FileStore = class {
|
|
|
233
233
|
return join(this.root, `${key}.json`);
|
|
234
234
|
}
|
|
235
235
|
async load(key) {
|
|
236
|
-
const
|
|
236
|
+
const path2 = this.filePath(key);
|
|
237
237
|
try {
|
|
238
|
-
const raw = await readFile(
|
|
238
|
+
const raw = await readFile(path2, "utf-8");
|
|
239
239
|
return JSON.parse(raw);
|
|
240
240
|
} catch (err) {
|
|
241
241
|
if (err.code === "ENOENT") {
|
|
@@ -245,15 +245,15 @@ var FileStore = class {
|
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
async save(key, data) {
|
|
248
|
-
const
|
|
249
|
-
await mkdir(dirname(
|
|
250
|
-
await writeFile(
|
|
248
|
+
const path2 = this.filePath(key);
|
|
249
|
+
await mkdir(dirname(path2), { recursive: true });
|
|
250
|
+
await writeFile(path2, JSON.stringify(data, null, 2), "utf-8");
|
|
251
251
|
}
|
|
252
252
|
async remove(key) {
|
|
253
|
-
const { unlink } = await import("fs/promises");
|
|
254
|
-
const
|
|
253
|
+
const { unlink: unlink2 } = await import("fs/promises");
|
|
254
|
+
const path2 = this.filePath(key);
|
|
255
255
|
try {
|
|
256
|
-
await
|
|
256
|
+
await unlink2(path2);
|
|
257
257
|
} catch (err) {
|
|
258
258
|
if (err.code !== "ENOENT") {
|
|
259
259
|
throw err;
|
|
@@ -261,9 +261,9 @@ var FileStore = class {
|
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
async exists(key) {
|
|
264
|
-
const
|
|
264
|
+
const path2 = this.filePath(key);
|
|
265
265
|
try {
|
|
266
|
-
await access(
|
|
266
|
+
await access(path2);
|
|
267
267
|
return true;
|
|
268
268
|
} catch {
|
|
269
269
|
return false;
|
|
@@ -1444,6 +1444,27 @@ var AccountService = class {
|
|
|
1444
1444
|
await this.persist();
|
|
1445
1445
|
return account;
|
|
1446
1446
|
}
|
|
1447
|
+
// ─── Rename ───────────────────────────────────────────────────────
|
|
1448
|
+
/**
|
|
1449
|
+
* Rename an account's alias.
|
|
1450
|
+
* @param aliasOrAddress - Current alias or address to identify the account.
|
|
1451
|
+
* @param newAlias - The new alias. Must be unique.
|
|
1452
|
+
*/
|
|
1453
|
+
async renameAccount(aliasOrAddress, newAlias) {
|
|
1454
|
+
const account = this.resolveAccount(aliasOrAddress);
|
|
1455
|
+
if (!account) {
|
|
1456
|
+
throw new Error(`Account "${aliasOrAddress}" not found.`);
|
|
1457
|
+
}
|
|
1458
|
+
const conflict = this.state.accounts.find(
|
|
1459
|
+
(a) => a.alias.toLowerCase() === newAlias.toLowerCase() && a.address !== account.address
|
|
1460
|
+
);
|
|
1461
|
+
if (conflict) {
|
|
1462
|
+
throw new Error(`Alias "${newAlias}" is already taken by ${conflict.address}.`);
|
|
1463
|
+
}
|
|
1464
|
+
account.alias = newAlias;
|
|
1465
|
+
await this.persist();
|
|
1466
|
+
return account;
|
|
1467
|
+
}
|
|
1447
1468
|
// ─── Activation ───────────────────────────────────────────────────
|
|
1448
1469
|
/**
|
|
1449
1470
|
* Mark an account as deployed on-chain.
|
|
@@ -2151,120 +2172,227 @@ var SecurityHookService = class {
|
|
|
2151
2172
|
}
|
|
2152
2173
|
};
|
|
2153
2174
|
|
|
2154
|
-
// src/providers/
|
|
2155
|
-
import {
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
var KeychainProvider = class {
|
|
2159
|
-
name = "macos-keychain";
|
|
2175
|
+
// src/providers/keyringProvider.ts
|
|
2176
|
+
import { Entry } from "@napi-rs/keyring";
|
|
2177
|
+
var KeyringProvider = class {
|
|
2178
|
+
name;
|
|
2160
2179
|
service = "elytro-wallet";
|
|
2161
2180
|
account = "vault-key";
|
|
2181
|
+
constructor() {
|
|
2182
|
+
const platform = process.platform;
|
|
2183
|
+
if (platform === "darwin") this.name = "macos-keychain";
|
|
2184
|
+
else if (platform === "win32") this.name = "windows-credential-manager";
|
|
2185
|
+
else this.name = "linux-secret-service";
|
|
2186
|
+
}
|
|
2162
2187
|
async available() {
|
|
2163
|
-
if (process.platform !== "darwin") return false;
|
|
2164
2188
|
try {
|
|
2165
|
-
|
|
2189
|
+
const entry = new Entry(this.service, this.account);
|
|
2190
|
+
entry.getSecret();
|
|
2166
2191
|
return true;
|
|
2167
|
-
} catch {
|
|
2168
|
-
|
|
2192
|
+
} catch (err) {
|
|
2193
|
+
const msg = err.message || "";
|
|
2194
|
+
if (isNotFoundError(msg)) return true;
|
|
2195
|
+
return false;
|
|
2169
2196
|
}
|
|
2170
2197
|
}
|
|
2171
2198
|
async store(secret) {
|
|
2172
2199
|
validateKeyLength(secret);
|
|
2200
|
+
try {
|
|
2201
|
+
const entry = new Entry(this.service, this.account);
|
|
2202
|
+
entry.setSecret(Buffer.from(secret));
|
|
2203
|
+
} catch (err) {
|
|
2204
|
+
throw new Error(`Failed to store vault key in OS credential store: ${err.message}`);
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
async load() {
|
|
2208
|
+
try {
|
|
2209
|
+
const entry = new Entry(this.service, this.account);
|
|
2210
|
+
const raw = entry.getSecret();
|
|
2211
|
+
if (!raw || raw.length === 0) return null;
|
|
2212
|
+
const key = new Uint8Array(raw);
|
|
2213
|
+
if (key.length !== 32) {
|
|
2214
|
+
throw new Error(
|
|
2215
|
+
`OS credential store returned vault key with invalid length: expected 32 bytes, got ${key.length}.`
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
2218
|
+
return key;
|
|
2219
|
+
} catch (err) {
|
|
2220
|
+
const msg = err.message || "";
|
|
2221
|
+
if (isNotFoundError(msg)) return null;
|
|
2222
|
+
throw new Error(`Failed to load vault key from OS credential store: ${msg}`);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
async delete() {
|
|
2226
|
+
try {
|
|
2227
|
+
const entry = new Entry(this.service, this.account);
|
|
2228
|
+
entry.deleteCredential();
|
|
2229
|
+
} catch {
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
};
|
|
2233
|
+
function isNotFoundError(msg) {
|
|
2234
|
+
const lower = msg.toLowerCase();
|
|
2235
|
+
return lower.includes("not found") || lower.includes("no matching") || lower.includes("no such") || lower.includes("itemnotfound") || lower.includes("element not found") || // Windows
|
|
2236
|
+
lower.includes("no result") || lower.includes("no password");
|
|
2237
|
+
}
|
|
2238
|
+
function validateKeyLength(key) {
|
|
2239
|
+
if (key.length !== 32) {
|
|
2240
|
+
throw new Error(`Invalid vault key: expected 32 bytes, got ${key.length}.`);
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
// src/providers/fileProvider.ts
|
|
2245
|
+
import * as fs from "fs/promises";
|
|
2246
|
+
import * as path from "path";
|
|
2247
|
+
import { constants } from "fs";
|
|
2248
|
+
var FileProvider = class {
|
|
2249
|
+
name = "file-protected";
|
|
2250
|
+
keyPath;
|
|
2251
|
+
/**
|
|
2252
|
+
* @param dataDir — the ~/.elytro/ directory path (from FileStore.dataDir).
|
|
2253
|
+
* Defaults to ~/.elytro if not provided.
|
|
2254
|
+
*/
|
|
2255
|
+
constructor(dataDir) {
|
|
2256
|
+
const base = dataDir ?? path.join(process.env.HOME || "~", ".elytro");
|
|
2257
|
+
this.keyPath = path.join(base, ".vault-key");
|
|
2258
|
+
}
|
|
2259
|
+
/**
|
|
2260
|
+
* FileProvider is always technically available on any OS (filesystem always exists).
|
|
2261
|
+
* But it should only be used on Linux when the KeyringProvider is not available.
|
|
2262
|
+
* The resolution logic in resolveProvider handles this gating — FileProvider
|
|
2263
|
+
* itself does not restrict by platform.
|
|
2264
|
+
*/
|
|
2265
|
+
async available() {
|
|
2266
|
+
try {
|
|
2267
|
+
await fs.access(this.keyPath, constants.R_OK);
|
|
2268
|
+
return true;
|
|
2269
|
+
} catch {
|
|
2270
|
+
try {
|
|
2271
|
+
await fs.access(path.dirname(this.keyPath), constants.W_OK);
|
|
2272
|
+
return true;
|
|
2273
|
+
} catch {
|
|
2274
|
+
return false;
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
async store(secret) {
|
|
2279
|
+
validateKeyLength2(secret);
|
|
2173
2280
|
const b64 = Buffer.from(secret).toString("base64");
|
|
2281
|
+
const tmpPath = this.keyPath + ".tmp";
|
|
2174
2282
|
try {
|
|
2175
|
-
await
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
"-s",
|
|
2179
|
-
this.service,
|
|
2180
|
-
"-a",
|
|
2181
|
-
this.account,
|
|
2182
|
-
"-w",
|
|
2183
|
-
b64
|
|
2184
|
-
]);
|
|
2283
|
+
await fs.writeFile(tmpPath, b64, { encoding: "utf-8", mode: 384 });
|
|
2284
|
+
await fs.rename(tmpPath, this.keyPath);
|
|
2285
|
+
await fs.chmod(this.keyPath, 384);
|
|
2185
2286
|
} catch (err) {
|
|
2186
|
-
|
|
2287
|
+
try {
|
|
2288
|
+
await fs.unlink(tmpPath);
|
|
2289
|
+
} catch {
|
|
2290
|
+
}
|
|
2291
|
+
throw new Error(`Failed to store vault key to file: ${err.message}`);
|
|
2187
2292
|
}
|
|
2188
2293
|
}
|
|
2189
2294
|
async load() {
|
|
2190
2295
|
try {
|
|
2191
|
-
const
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2296
|
+
const stat2 = await fs.stat(this.keyPath);
|
|
2297
|
+
const mode = stat2.mode & 511;
|
|
2298
|
+
if (mode !== 384) {
|
|
2299
|
+
throw new Error(
|
|
2300
|
+
`Vault key file has insecure permissions: ${modeToOctal(mode)} (expected 0600).
|
|
2301
|
+
Fix with: chmod 600 ${this.keyPath}
|
|
2302
|
+
Refusing to load until permissions are corrected.`
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
2305
|
+
const raw = await fs.readFile(this.keyPath, "utf-8");
|
|
2306
|
+
const trimmed = raw.trim();
|
|
2200
2307
|
if (!trimmed) return null;
|
|
2201
2308
|
const key = Buffer.from(trimmed, "base64");
|
|
2202
2309
|
if (key.length !== 32) {
|
|
2203
|
-
throw new Error(
|
|
2310
|
+
throw new Error(
|
|
2311
|
+
`Vault key file has invalid content: expected 32 bytes (base64), got ${key.length}.`
|
|
2312
|
+
);
|
|
2204
2313
|
}
|
|
2205
2314
|
return new Uint8Array(key);
|
|
2206
2315
|
} catch (err) {
|
|
2207
2316
|
const msg = err.message || "";
|
|
2208
|
-
if (msg.includes("
|
|
2209
|
-
|
|
2210
|
-
}
|
|
2211
|
-
throw new Error(`Failed to load vault key from Keychain: ${msg}`);
|
|
2317
|
+
if (msg.includes("ENOENT")) return null;
|
|
2318
|
+
throw err;
|
|
2212
2319
|
}
|
|
2213
2320
|
}
|
|
2214
2321
|
async delete() {
|
|
2215
2322
|
try {
|
|
2216
|
-
await
|
|
2323
|
+
await fs.unlink(this.keyPath);
|
|
2217
2324
|
} catch {
|
|
2218
2325
|
}
|
|
2219
2326
|
}
|
|
2220
2327
|
};
|
|
2221
|
-
function
|
|
2328
|
+
function validateKeyLength2(key) {
|
|
2222
2329
|
if (key.length !== 32) {
|
|
2223
2330
|
throw new Error(`Invalid vault key: expected 32 bytes, got ${key.length}.`);
|
|
2224
2331
|
}
|
|
2225
2332
|
}
|
|
2333
|
+
function modeToOctal(mode) {
|
|
2334
|
+
return "0" + mode.toString(8);
|
|
2335
|
+
}
|
|
2226
2336
|
|
|
2227
2337
|
// src/providers/envVarProvider.ts
|
|
2228
2338
|
var ENV_KEY = "ELYTRO_VAULT_SECRET";
|
|
2339
|
+
var ENV_ALLOW = "ELYTRO_ALLOW_ENV";
|
|
2229
2340
|
var EnvVarProvider = class {
|
|
2230
2341
|
name = "env-var";
|
|
2231
2342
|
async available() {
|
|
2232
|
-
return !!process.env[ENV_KEY];
|
|
2343
|
+
return !!process.env[ENV_KEY] && process.env[ENV_ALLOW] === "1";
|
|
2233
2344
|
}
|
|
2234
2345
|
async store(_secret) {
|
|
2235
2346
|
throw new Error(
|
|
2236
|
-
"EnvVarProvider is read-only. Cannot store vault key in an environment variable
|
|
2347
|
+
"EnvVarProvider is read-only. Cannot store vault key in an environment variable.\nUse a persistent provider (OS keychain or file-protected) or store the secret manually."
|
|
2237
2348
|
);
|
|
2238
2349
|
}
|
|
2239
2350
|
async load() {
|
|
2351
|
+
if (process.env[ENV_ALLOW] !== "1") return null;
|
|
2240
2352
|
const raw = process.env[ENV_KEY];
|
|
2241
2353
|
if (!raw) return null;
|
|
2242
2354
|
delete process.env[ENV_KEY];
|
|
2355
|
+
delete process.env[ENV_ALLOW];
|
|
2243
2356
|
const key = Buffer.from(raw, "base64");
|
|
2244
2357
|
if (key.length !== 32) {
|
|
2245
2358
|
throw new Error(
|
|
2246
|
-
`${ENV_KEY} has invalid length: expected 32 bytes (base64), got ${key.length}.
|
|
2359
|
+
`${ENV_KEY} has invalid length: expected 32 bytes (base64), got ${key.length}.
|
|
2360
|
+
The value must be a base64-encoded 256-bit key.`
|
|
2247
2361
|
);
|
|
2248
2362
|
}
|
|
2249
2363
|
return new Uint8Array(key);
|
|
2250
2364
|
}
|
|
2251
2365
|
async delete() {
|
|
2252
2366
|
delete process.env[ENV_KEY];
|
|
2367
|
+
delete process.env[ENV_ALLOW];
|
|
2253
2368
|
}
|
|
2254
2369
|
};
|
|
2255
2370
|
|
|
2256
2371
|
// src/providers/resolveProvider.ts
|
|
2257
2372
|
async function resolveProvider() {
|
|
2258
|
-
const
|
|
2373
|
+
const keyringProvider = new KeyringProvider();
|
|
2374
|
+
const fileProvider = new FileProvider();
|
|
2259
2375
|
const envProvider = new EnvVarProvider();
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2376
|
+
if (await keyringProvider.available()) {
|
|
2377
|
+
return {
|
|
2378
|
+
initProvider: keyringProvider,
|
|
2379
|
+
loadProvider: keyringProvider
|
|
2380
|
+
};
|
|
2381
|
+
}
|
|
2382
|
+
if (process.platform === "linux" && await fileProvider.available()) {
|
|
2383
|
+
return {
|
|
2384
|
+
initProvider: fileProvider,
|
|
2385
|
+
loadProvider: fileProvider
|
|
2386
|
+
};
|
|
2387
|
+
}
|
|
2388
|
+
if (await envProvider.available()) {
|
|
2389
|
+
return {
|
|
2390
|
+
initProvider: null,
|
|
2391
|
+
// Cannot store via env var
|
|
2392
|
+
loadProvider: envProvider
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
return { initProvider: null, loadProvider: null };
|
|
2268
2396
|
}
|
|
2269
2397
|
|
|
2270
2398
|
// src/context.ts
|
|
@@ -2284,14 +2412,15 @@ async function createAppContext() {
|
|
|
2284
2412
|
if (isInitialized) {
|
|
2285
2413
|
if (!loadProvider) {
|
|
2286
2414
|
throw new Error(
|
|
2287
|
-
"Wallet is initialized but no secret provider is available.\n" + (
|
|
2415
|
+
"Wallet is initialized but no secret provider is available.\n" + noProviderHint()
|
|
2288
2416
|
);
|
|
2289
2417
|
}
|
|
2290
2418
|
const vaultKey = await loadProvider.load();
|
|
2291
2419
|
if (!vaultKey) {
|
|
2292
2420
|
throw new Error(
|
|
2293
2421
|
`Wallet is initialized but vault key not found in ${loadProvider.name}.
|
|
2294
|
-
|
|
2422
|
+
The credential may have been deleted. Re-run \`elytro init\` to create a new wallet,
|
|
2423
|
+
or import a backup with \`elytro import\`.`
|
|
2295
2424
|
);
|
|
2296
2425
|
}
|
|
2297
2426
|
try {
|
|
@@ -2326,6 +2455,16 @@ The vault key may not match the encrypted keyring. Re-run \`elytro init\` or imp
|
|
|
2326
2455
|
}
|
|
2327
2456
|
return { store, keyring, chain, sdk, walletClient, account, secretProvider: loadProvider };
|
|
2328
2457
|
}
|
|
2458
|
+
function noProviderHint() {
|
|
2459
|
+
switch (process.platform) {
|
|
2460
|
+
case "darwin":
|
|
2461
|
+
return "macOS Keychain access failed. Check Keychain permissions or security settings.";
|
|
2462
|
+
case "win32":
|
|
2463
|
+
return "Windows Credential Manager access failed. Run as the same user who initialized the wallet.";
|
|
2464
|
+
default:
|
|
2465
|
+
return "No secret provider available. Options:\n 1. Install and start a Secret Service provider (GNOME Keyring or KWallet)\n 2. The vault key file (~/.elytro/.vault-key) may have been deleted\n 3. For CI: set ELYTRO_VAULT_SECRET and ELYTRO_ALLOW_ENV=1";
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2329
2468
|
|
|
2330
2469
|
// src/commands/init.ts
|
|
2331
2470
|
import { webcrypto as webcrypto2 } from "crypto";
|
|
@@ -2396,7 +2535,9 @@ function registerInitCommand(program2, ctx) {
|
|
|
2396
2535
|
dataDir: ctx.store.dataDir,
|
|
2397
2536
|
secretProvider: providerName,
|
|
2398
2537
|
...vaultSecretB64 ? { vaultSecret: vaultSecretB64 } : {},
|
|
2399
|
-
...vaultSecretB64 ? {
|
|
2538
|
+
...vaultSecretB64 ? {
|
|
2539
|
+
hint: "No persistent secret provider available. Save this vault key securely \u2014 it will NOT be shown again.\nFor CI: set ELYTRO_VAULT_SECRET=<key> and ELYTRO_ALLOW_ENV=1."
|
|
2540
|
+
} : {},
|
|
2400
2541
|
nextStep: "Run `elytro account create --chain <chainId>` to create your first smart account."
|
|
2401
2542
|
});
|
|
2402
2543
|
} catch (err) {
|
|
@@ -2473,6 +2614,14 @@ function registerAccountCommand(program2, ctx) {
|
|
|
2473
2614
|
outputError(ERR_INVALID_PARAMS, "Invalid chain ID.", { chain: opts.chain });
|
|
2474
2615
|
return;
|
|
2475
2616
|
}
|
|
2617
|
+
const chainConfig = ctx.chain.chains.find((c) => c.id === chainId);
|
|
2618
|
+
if (!chainConfig) {
|
|
2619
|
+
const supported = ctx.chain.chains.map((c) => `${c.id} (${c.name})`);
|
|
2620
|
+
outputError(ERR_INVALID_PARAMS, `Chain ${chainId} is not supported.`, {
|
|
2621
|
+
supportedChains: supported
|
|
2622
|
+
});
|
|
2623
|
+
return;
|
|
2624
|
+
}
|
|
2476
2625
|
let dailyLimitUsd;
|
|
2477
2626
|
if (opts.dailyLimit !== void 0) {
|
|
2478
2627
|
dailyLimitUsd = parseFloat(opts.dailyLimit);
|
|
@@ -2487,12 +2636,9 @@ function registerAccountCommand(program2, ctx) {
|
|
|
2487
2636
|
} : void 0;
|
|
2488
2637
|
const spinner = ora2("Creating smart account...").start();
|
|
2489
2638
|
try {
|
|
2490
|
-
const
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
await ctx.sdk.initForChain(chainConfig);
|
|
2494
|
-
ctx.walletClient.initForChain(chainConfig);
|
|
2495
|
-
}
|
|
2639
|
+
const chainName = chainConfig.name;
|
|
2640
|
+
await ctx.sdk.initForChain(chainConfig);
|
|
2641
|
+
ctx.walletClient.initForChain(chainConfig);
|
|
2496
2642
|
const accountInfo = await ctx.account.createAccount(chainId, opts.alias, securityIntent);
|
|
2497
2643
|
spinner.text = "Registering with backend...";
|
|
2498
2644
|
const { guardianHash, guardianSafePeriod } = ctx.sdk.initDefaults;
|
|
@@ -2748,6 +2894,20 @@ function registerAccountCommand(program2, ctx) {
|
|
|
2748
2894
|
outputError(ERR_INTERNAL, err.message);
|
|
2749
2895
|
}
|
|
2750
2896
|
});
|
|
2897
|
+
account.command("rename").description("Rename an account alias").argument("<account>", "Current alias or address").argument("<newAlias>", "New alias").action(async (target, newAlias) => {
|
|
2898
|
+
try {
|
|
2899
|
+
const renamed = await ctx.account.renameAccount(target, newAlias);
|
|
2900
|
+
const chainConfig = ctx.chain.chains.find((c) => c.id === renamed.chainId);
|
|
2901
|
+
outputResult({
|
|
2902
|
+
alias: renamed.alias,
|
|
2903
|
+
address: renamed.address,
|
|
2904
|
+
chain: chainConfig?.name ?? String(renamed.chainId),
|
|
2905
|
+
chainId: renamed.chainId
|
|
2906
|
+
});
|
|
2907
|
+
} catch (err) {
|
|
2908
|
+
outputError(ERR_INTERNAL, err.message);
|
|
2909
|
+
}
|
|
2910
|
+
});
|
|
2751
2911
|
account.command("switch").description("Switch the active account").argument("[account]", "Alias or address").action(async (target) => {
|
|
2752
2912
|
const accounts = ctx.account.allAccounts;
|
|
2753
2913
|
if (accounts.length === 0) {
|
|
@@ -4238,7 +4398,7 @@ import { execSync } from "child_process";
|
|
|
4238
4398
|
import { createRequire } from "module";
|
|
4239
4399
|
function resolveVersion() {
|
|
4240
4400
|
if (true) {
|
|
4241
|
-
return "0.5.
|
|
4401
|
+
return "0.5.2";
|
|
4242
4402
|
}
|
|
4243
4403
|
try {
|
|
4244
4404
|
const require2 = createRequire(import.meta.url);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elytro/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Elytro ERC-4337 Smart Account Wallet CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"@elytro/abi": "latest",
|
|
42
42
|
"@elytro/sdk": "latest",
|
|
43
43
|
"@inquirer/prompts": "^7.0.0",
|
|
44
|
+
"@napi-rs/keyring": "^1.2.0",
|
|
44
45
|
"chalk": "^5.3.0",
|
|
45
46
|
"commander": "^13.0.0",
|
|
46
47
|
"graphql": "^16.9.0",
|