zoa-wallet 0.2.8 → 0.2.9
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.mjs +186 -320
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -48182,184 +48182,6 @@ function registerHistoryCommand(program2) {
|
|
|
48182
48182
|
});
|
|
48183
48183
|
}
|
|
48184
48184
|
|
|
48185
|
-
// dist/commands/init.js
|
|
48186
|
-
import chalk3 from "chalk";
|
|
48187
|
-
import inquirer4 from "inquirer";
|
|
48188
|
-
var COLOR_PRESETS = [
|
|
48189
|
-
{ name: "Cyan", hex: "#00bbf9" },
|
|
48190
|
-
{ name: "Orange", hex: "#ff6b35" },
|
|
48191
|
-
{ name: "Purple", hex: "#7b2ff7" },
|
|
48192
|
-
{ name: "Green", hex: "#10b981" },
|
|
48193
|
-
{ name: "Pink", hex: "#ec4899" },
|
|
48194
|
-
{ name: "Yellow", hex: "#f59e0b" },
|
|
48195
|
-
{ name: "Red", hex: "#ef4444" },
|
|
48196
|
-
{ name: "Teal", hex: "#14b8a6" }
|
|
48197
|
-
];
|
|
48198
|
-
function registerInitCommand(program2) {
|
|
48199
|
-
program2.command("init").description("Create a new wallet or import an existing one").option("--mnemonic <phrase>", "Provide a mnemonic phrase (non-interactive)").option("--password <password>", "Set wallet password (non-interactive)").option("--label <label>", "Wallet label (non-interactive)").option("--color <hex>", "Wallet color hex (non-interactive)").option("--word-count <count>", "Word count for new mnemonic: 12 or 24", "12").action(async (opts) => {
|
|
48200
|
-
try {
|
|
48201
|
-
let mnemonic;
|
|
48202
|
-
let password;
|
|
48203
|
-
let label;
|
|
48204
|
-
let walletColor;
|
|
48205
|
-
let isNew = false;
|
|
48206
|
-
if (opts.mnemonic && opts.password) {
|
|
48207
|
-
mnemonic = opts.mnemonic;
|
|
48208
|
-
password = opts.password;
|
|
48209
|
-
label = opts.label || "Default Wallet";
|
|
48210
|
-
walletColor = opts.color || "#00bbf9";
|
|
48211
|
-
} else {
|
|
48212
|
-
if (!isJsonMode()) {
|
|
48213
|
-
console.log(colors.brandBold(" Create or Import Wallet"));
|
|
48214
|
-
console.log();
|
|
48215
|
-
}
|
|
48216
|
-
const { walletLabel } = await inquirer4.prompt([{
|
|
48217
|
-
type: "input",
|
|
48218
|
-
name: "walletLabel",
|
|
48219
|
-
message: "Wallet name:",
|
|
48220
|
-
default: "My Wallet",
|
|
48221
|
-
validate: (input) => input.trim().length > 0 || "Label is required"
|
|
48222
|
-
}]);
|
|
48223
|
-
label = walletLabel;
|
|
48224
|
-
const colorChoices = COLOR_PRESETS.map((c) => ({
|
|
48225
|
-
name: `${chalk3.hex(c.hex)("\u25CF")} ${c.name}`,
|
|
48226
|
-
value: c.hex
|
|
48227
|
-
}));
|
|
48228
|
-
colorChoices.push({ name: "Custom hex...", value: "custom" });
|
|
48229
|
-
const { selectedColor } = await inquirer4.prompt([{
|
|
48230
|
-
type: "list",
|
|
48231
|
-
name: "selectedColor",
|
|
48232
|
-
message: "Choose a color:",
|
|
48233
|
-
choices: colorChoices
|
|
48234
|
-
}]);
|
|
48235
|
-
if (selectedColor === "custom") {
|
|
48236
|
-
const { customHex } = await inquirer4.prompt([{
|
|
48237
|
-
type: "input",
|
|
48238
|
-
name: "customHex",
|
|
48239
|
-
message: "Enter hex color (e.g. #ff6b35):",
|
|
48240
|
-
validate: (input) => /^#[0-9a-fA-F]{6}$/.test(input) || "Enter a valid hex color"
|
|
48241
|
-
}]);
|
|
48242
|
-
walletColor = customHex;
|
|
48243
|
-
} else {
|
|
48244
|
-
walletColor = selectedColor;
|
|
48245
|
-
}
|
|
48246
|
-
const { action } = await inquirer4.prompt([
|
|
48247
|
-
{
|
|
48248
|
-
type: "list",
|
|
48249
|
-
name: "action",
|
|
48250
|
-
message: "What would you like to do?",
|
|
48251
|
-
choices: [
|
|
48252
|
-
{ name: "Create a new wallet", value: "create" },
|
|
48253
|
-
{ name: "Import from recovery phrase", value: "import" }
|
|
48254
|
-
]
|
|
48255
|
-
}
|
|
48256
|
-
]);
|
|
48257
|
-
if (action === "create") {
|
|
48258
|
-
isNew = true;
|
|
48259
|
-
const wordCount = Number(opts.wordCount) === 24 ? 24 : 12;
|
|
48260
|
-
const result = createMnemonic(wordCount);
|
|
48261
|
-
mnemonic = result.phrase;
|
|
48262
|
-
if (!isJsonMode()) {
|
|
48263
|
-
console.log();
|
|
48264
|
-
console.log(warningBox("Recovery Phrase \u2014 Save This!", [
|
|
48265
|
-
colors.warning("Write down these words and store them safely."),
|
|
48266
|
-
colors.warning("Anyone with this phrase can access your funds."),
|
|
48267
|
-
"",
|
|
48268
|
-
colors.highlight(mnemonic),
|
|
48269
|
-
"",
|
|
48270
|
-
colors.muted(`${wordCount} words`)
|
|
48271
|
-
]));
|
|
48272
|
-
console.log();
|
|
48273
|
-
}
|
|
48274
|
-
} else {
|
|
48275
|
-
const { phrase } = await inquirer4.prompt([
|
|
48276
|
-
{
|
|
48277
|
-
type: "input",
|
|
48278
|
-
name: "phrase",
|
|
48279
|
-
message: "Enter your recovery phrase:"
|
|
48280
|
-
}
|
|
48281
|
-
]);
|
|
48282
|
-
mnemonic = phrase.trim();
|
|
48283
|
-
}
|
|
48284
|
-
const { pwd } = await inquirer4.prompt([
|
|
48285
|
-
{
|
|
48286
|
-
type: "password",
|
|
48287
|
-
name: "pwd",
|
|
48288
|
-
message: "Set a secure password:",
|
|
48289
|
-
mask: "*",
|
|
48290
|
-
validate: (input) => input.length >= 8 || "Password must be at least 8 characters"
|
|
48291
|
-
}
|
|
48292
|
-
]);
|
|
48293
|
-
await inquirer4.prompt([
|
|
48294
|
-
{
|
|
48295
|
-
type: "password",
|
|
48296
|
-
name: "confirmPwd",
|
|
48297
|
-
message: "Confirm password:",
|
|
48298
|
-
mask: "*",
|
|
48299
|
-
validate: (input) => input === pwd || "Passwords do not match"
|
|
48300
|
-
}
|
|
48301
|
-
]);
|
|
48302
|
-
password = pwd;
|
|
48303
|
-
}
|
|
48304
|
-
const spinner = createSpinner("Deriving keys and encrypting vault...");
|
|
48305
|
-
if (!isJsonMode())
|
|
48306
|
-
spinner.start();
|
|
48307
|
-
const walletId = generateWalletId();
|
|
48308
|
-
const vaultKey = `wallet_${walletId}`;
|
|
48309
|
-
const storage = new FileStorage();
|
|
48310
|
-
const kr = createKeyring(storage, vaultKey);
|
|
48311
|
-
await kr.initialize(mnemonic, password);
|
|
48312
|
-
const accounts = kr.getAccounts();
|
|
48313
|
-
const firstAccount = accounts[0];
|
|
48314
|
-
await addWallet({
|
|
48315
|
-
id: walletId,
|
|
48316
|
-
label,
|
|
48317
|
-
color: walletColor,
|
|
48318
|
-
vaultKey,
|
|
48319
|
-
createdAt: Date.now(),
|
|
48320
|
-
evmAddress: firstAccount?.evmAddress,
|
|
48321
|
-
solanaAddress: firstAccount?.solanaAddress
|
|
48322
|
-
});
|
|
48323
|
-
await setActiveWallet(walletId);
|
|
48324
|
-
if (!isJsonMode())
|
|
48325
|
-
spinner.succeed(" Wallet initialized successfully!");
|
|
48326
|
-
if (firstAccount) {
|
|
48327
|
-
output({
|
|
48328
|
-
success: true,
|
|
48329
|
-
isNew,
|
|
48330
|
-
walletId,
|
|
48331
|
-
label,
|
|
48332
|
-
color: walletColor,
|
|
48333
|
-
account: {
|
|
48334
|
-
index: firstAccount.index,
|
|
48335
|
-
label: firstAccount.label,
|
|
48336
|
-
evmAddress: firstAccount.evmAddress,
|
|
48337
|
-
solanaAddress: firstAccount.solanaAddress
|
|
48338
|
-
},
|
|
48339
|
-
...isNew ? { mnemonic } : {}
|
|
48340
|
-
}, () => {
|
|
48341
|
-
console.log();
|
|
48342
|
-
console.log(successBox(`Wallet: ${label}`, [
|
|
48343
|
-
kvLine("Wallet ID", walletId),
|
|
48344
|
-
kvLine("Color", chalk3.hex(walletColor)("\u25CF ") + walletColor),
|
|
48345
|
-
kvLine("EVM Address", firstAccount.evmAddress),
|
|
48346
|
-
kvLine("Solana", firstAccount.solanaAddress),
|
|
48347
|
-
"",
|
|
48348
|
-
colors.muted("Vault encrypted and saved to ~/.zoa/")
|
|
48349
|
-
]));
|
|
48350
|
-
console.log();
|
|
48351
|
-
});
|
|
48352
|
-
}
|
|
48353
|
-
} catch (error) {
|
|
48354
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
48355
|
-
outputError(msg);
|
|
48356
|
-
if (!isJsonMode())
|
|
48357
|
-
console.log(errorMsg(msg));
|
|
48358
|
-
process.exitCode = 1;
|
|
48359
|
-
}
|
|
48360
|
-
});
|
|
48361
|
-
}
|
|
48362
|
-
|
|
48363
48185
|
// dist/commands/prices.js
|
|
48364
48186
|
var DEFAULT_TOKENS = ["ethereum", "solana", "bitcoin"];
|
|
48365
48187
|
var COINGECKO_API = "https://api.coingecko.com/api/v3";
|
|
@@ -48412,7 +48234,7 @@ function registerPricesCommand(program2) {
|
|
|
48412
48234
|
}
|
|
48413
48235
|
|
|
48414
48236
|
// dist/commands/receive.js
|
|
48415
|
-
import
|
|
48237
|
+
import inquirer4 from "inquirer";
|
|
48416
48238
|
|
|
48417
48239
|
// dist/ui/qrcode.js
|
|
48418
48240
|
async function renderQRCode(data) {
|
|
@@ -48433,7 +48255,7 @@ function registerReceiveCommand(program2) {
|
|
|
48433
48255
|
if (opts.password) {
|
|
48434
48256
|
password = opts.password;
|
|
48435
48257
|
} else {
|
|
48436
|
-
const { pwd } = await
|
|
48258
|
+
const { pwd } = await inquirer4.prompt([
|
|
48437
48259
|
{
|
|
48438
48260
|
type: "password",
|
|
48439
48261
|
name: "pwd",
|
|
@@ -48485,7 +48307,7 @@ function registerReceiveCommand(program2) {
|
|
|
48485
48307
|
}
|
|
48486
48308
|
|
|
48487
48309
|
// dist/commands/send.js
|
|
48488
|
-
import
|
|
48310
|
+
import inquirer5 from "inquirer";
|
|
48489
48311
|
function registerSendCommand(program2) {
|
|
48490
48312
|
program2.command("send").description("Send tokens to an address").option("--password <password>", "Wallet password (non-interactive)").option("--to <address>", "Recipient address").option("--amount <amount>", "Amount to send").option("--chain <chain>", "Chain to use (base, ethereum, solana, etc.)", "base").option("--yes", "Skip confirmation prompt").action(async (opts) => {
|
|
48491
48313
|
try {
|
|
@@ -48503,7 +48325,7 @@ function registerSendCommand(program2) {
|
|
|
48503
48325
|
console.log(colors.brandBold(" Send Tokens"));
|
|
48504
48326
|
console.log();
|
|
48505
48327
|
}
|
|
48506
|
-
const answers = await
|
|
48328
|
+
const answers = await inquirer5.prompt([
|
|
48507
48329
|
{
|
|
48508
48330
|
type: "password",
|
|
48509
48331
|
name: "password",
|
|
@@ -48581,7 +48403,7 @@ function registerSendCommand(program2) {
|
|
|
48581
48403
|
kvLine("Est. Gas", gasLine)
|
|
48582
48404
|
]));
|
|
48583
48405
|
console.log();
|
|
48584
|
-
const { confirm } = await
|
|
48406
|
+
const { confirm } = await inquirer5.prompt([
|
|
48585
48407
|
{
|
|
48586
48408
|
type: "confirm",
|
|
48587
48409
|
name: "confirm",
|
|
@@ -48626,9 +48448,9 @@ function registerSendCommand(program2) {
|
|
|
48626
48448
|
}
|
|
48627
48449
|
|
|
48628
48450
|
// dist/commands/wallet.js
|
|
48629
|
-
import
|
|
48630
|
-
import
|
|
48631
|
-
var
|
|
48451
|
+
import chalk3 from "chalk";
|
|
48452
|
+
import inquirer6 from "inquirer";
|
|
48453
|
+
var COLOR_PRESETS = [
|
|
48632
48454
|
{ name: "Cyan", hex: "#00bbf9" },
|
|
48633
48455
|
{ name: "Orange", hex: "#ff6b35" },
|
|
48634
48456
|
{ name: "Purple", hex: "#7b2ff7" },
|
|
@@ -48638,8 +48460,84 @@ var COLOR_PRESETS2 = [
|
|
|
48638
48460
|
{ name: "Red", hex: "#ef4444" },
|
|
48639
48461
|
{ name: "Teal", hex: "#14b8a6" }
|
|
48640
48462
|
];
|
|
48463
|
+
async function promptLabelColorPassword(opts) {
|
|
48464
|
+
const { walletLabel } = await inquirer6.prompt([{
|
|
48465
|
+
type: "input",
|
|
48466
|
+
name: "walletLabel",
|
|
48467
|
+
message: "Wallet name:",
|
|
48468
|
+
default: opts.label || "My Wallet",
|
|
48469
|
+
validate: (input) => input.trim().length > 0 || "Label is required"
|
|
48470
|
+
}]);
|
|
48471
|
+
const colorChoices = COLOR_PRESETS.map((c) => ({
|
|
48472
|
+
name: `${chalk3.hex(c.hex)("\u25CF")} ${c.name}`,
|
|
48473
|
+
value: c.hex
|
|
48474
|
+
}));
|
|
48475
|
+
colorChoices.push({ name: "Custom hex...", value: "custom" });
|
|
48476
|
+
let color;
|
|
48477
|
+
if (opts.color) {
|
|
48478
|
+
color = opts.color;
|
|
48479
|
+
} else {
|
|
48480
|
+
const { selectedColor } = await inquirer6.prompt([{
|
|
48481
|
+
type: "list",
|
|
48482
|
+
name: "selectedColor",
|
|
48483
|
+
message: "Choose a color:",
|
|
48484
|
+
choices: colorChoices
|
|
48485
|
+
}]);
|
|
48486
|
+
if (selectedColor === "custom") {
|
|
48487
|
+
const { customHex } = await inquirer6.prompt([{
|
|
48488
|
+
type: "input",
|
|
48489
|
+
name: "customHex",
|
|
48490
|
+
message: "Enter hex color (e.g. #ff6b35):",
|
|
48491
|
+
validate: (input) => /^#[0-9a-fA-F]{6}$/.test(input) || "Enter a valid hex color"
|
|
48492
|
+
}]);
|
|
48493
|
+
color = customHex;
|
|
48494
|
+
} else {
|
|
48495
|
+
color = selectedColor;
|
|
48496
|
+
}
|
|
48497
|
+
}
|
|
48498
|
+
const { pwd } = await inquirer6.prompt([{
|
|
48499
|
+
type: "password",
|
|
48500
|
+
name: "pwd",
|
|
48501
|
+
message: "Set a secure password:",
|
|
48502
|
+
mask: "*",
|
|
48503
|
+
validate: (input) => input.length >= 8 || "Password must be at least 8 characters"
|
|
48504
|
+
}]);
|
|
48505
|
+
await inquirer6.prompt([{
|
|
48506
|
+
type: "password",
|
|
48507
|
+
name: "confirmPwd",
|
|
48508
|
+
message: "Confirm password:",
|
|
48509
|
+
mask: "*",
|
|
48510
|
+
validate: (input) => input === pwd || "Passwords do not match"
|
|
48511
|
+
}]);
|
|
48512
|
+
return { label: walletLabel, color, password: pwd };
|
|
48513
|
+
}
|
|
48514
|
+
async function initializeAndRegisterWallet(label, color, mnemonic, password) {
|
|
48515
|
+
const spinner = createSpinner("Deriving keys and encrypting vault...");
|
|
48516
|
+
if (!isJsonMode())
|
|
48517
|
+
spinner.start();
|
|
48518
|
+
const walletId = generateWalletId();
|
|
48519
|
+
const vaultKey = `wallet_${walletId}`;
|
|
48520
|
+
const storage = new FileStorage();
|
|
48521
|
+
const kr = createKeyring(storage, vaultKey);
|
|
48522
|
+
await kr.initialize(mnemonic, password);
|
|
48523
|
+
const accounts = kr.getAccounts();
|
|
48524
|
+
const firstAccount = accounts[0];
|
|
48525
|
+
await addWallet({
|
|
48526
|
+
id: walletId,
|
|
48527
|
+
label,
|
|
48528
|
+
color,
|
|
48529
|
+
vaultKey,
|
|
48530
|
+
createdAt: Date.now(),
|
|
48531
|
+
evmAddress: firstAccount?.evmAddress,
|
|
48532
|
+
solanaAddress: firstAccount?.solanaAddress
|
|
48533
|
+
});
|
|
48534
|
+
await setActiveWallet(walletId);
|
|
48535
|
+
if (!isJsonMode())
|
|
48536
|
+
spinner.succeed(" Wallet ready!");
|
|
48537
|
+
return { walletId, firstAccount };
|
|
48538
|
+
}
|
|
48641
48539
|
function registerWalletCommand(program2) {
|
|
48642
|
-
const wallet = program2.command("wallet").description("
|
|
48540
|
+
const wallet = program2.command("wallet").description("Create, import, and manage multiple wallets");
|
|
48643
48541
|
wallet.command("list").description("List all wallets").option("--password <password>", "Wallet password (to resolve missing addresses)").action(async (opts) => {
|
|
48644
48542
|
try {
|
|
48645
48543
|
await migrateLegacyVaultIfNeeded();
|
|
@@ -48655,7 +48553,7 @@ function registerWalletCommand(program2) {
|
|
|
48655
48553
|
if (walletsNeedingAddresses.length > 0) {
|
|
48656
48554
|
let password = opts.password;
|
|
48657
48555
|
if (!password && !isJsonMode()) {
|
|
48658
|
-
const { pwd } = await
|
|
48556
|
+
const { pwd } = await inquirer6.prompt([{
|
|
48659
48557
|
type: "password",
|
|
48660
48558
|
name: "pwd",
|
|
48661
48559
|
message: "Enter wallet password to resolve addresses:",
|
|
@@ -48695,9 +48593,9 @@ function registerWalletCommand(program2) {
|
|
|
48695
48593
|
const table = createTable(["", "Label", "ID", "EVM Address", "Solana Address", "Created", "Last Used"], [4, 22, 14, 14, 14, 14, 14]);
|
|
48696
48594
|
for (const w of wallets) {
|
|
48697
48595
|
const isActive = w.id === active?.id;
|
|
48698
|
-
const dot =
|
|
48699
|
-
const indicator = isActive ? ` ${
|
|
48700
|
-
const label = isActive ?
|
|
48596
|
+
const dot = chalk3.hex(w.color)("\u25CF");
|
|
48597
|
+
const indicator = isActive ? ` ${chalk3.hex("#f59e0b")("\u2605")}` : "";
|
|
48598
|
+
const label = isActive ? chalk3.bold(w.label) : w.label;
|
|
48701
48599
|
const created = new Date(w.createdAt).toLocaleDateString();
|
|
48702
48600
|
const lastUsed = w.lastUsedAt ? new Date(w.lastUsedAt).toLocaleDateString() : colors.muted("never");
|
|
48703
48601
|
table.push([
|
|
@@ -48721,136 +48619,106 @@ function registerWalletCommand(program2) {
|
|
|
48721
48619
|
process.exitCode = 1;
|
|
48722
48620
|
}
|
|
48723
48621
|
});
|
|
48724
|
-
wallet.command("create").description("Create a new wallet").option("--label <label>", "Wallet label").option("--color <hex>", "Wallet color (hex)").option("--
|
|
48622
|
+
wallet.command("create").description("Create a new wallet").option("--label <label>", "Wallet label").option("--color <hex>", "Wallet color (hex)").option("--password <password>", "Set wallet password").option("--word-count <count>", "Word count for new mnemonic: 12 or 24", "12").action(async (opts) => {
|
|
48725
48623
|
try {
|
|
48726
48624
|
let label;
|
|
48727
48625
|
let color;
|
|
48728
|
-
let mnemonic;
|
|
48729
48626
|
let password;
|
|
48730
|
-
let isNew = false;
|
|
48731
48627
|
if (opts.label && opts.password) {
|
|
48732
48628
|
label = opts.label;
|
|
48733
48629
|
color = opts.color || "#00bbf9";
|
|
48734
|
-
if (opts.mnemonic) {
|
|
48735
|
-
mnemonic = opts.mnemonic;
|
|
48736
|
-
} else {
|
|
48737
|
-
const wordCount = Number(opts.wordCount) === 24 ? 24 : 12;
|
|
48738
|
-
const result = createMnemonic(wordCount);
|
|
48739
|
-
mnemonic = result.phrase;
|
|
48740
|
-
isNew = true;
|
|
48741
|
-
}
|
|
48742
48630
|
password = opts.password;
|
|
48743
48631
|
} else {
|
|
48744
48632
|
if (!isJsonMode()) {
|
|
48745
48633
|
console.log(colors.brandBold(" Create New Wallet"));
|
|
48746
48634
|
console.log();
|
|
48747
48635
|
}
|
|
48748
|
-
|
|
48749
|
-
|
|
48750
|
-
|
|
48751
|
-
|
|
48752
|
-
|
|
48753
|
-
|
|
48754
|
-
|
|
48755
|
-
|
|
48756
|
-
|
|
48757
|
-
|
|
48758
|
-
|
|
48759
|
-
|
|
48760
|
-
|
|
48761
|
-
|
|
48762
|
-
|
|
48763
|
-
|
|
48764
|
-
|
|
48765
|
-
|
|
48766
|
-
|
|
48767
|
-
|
|
48768
|
-
|
|
48769
|
-
|
|
48770
|
-
|
|
48771
|
-
|
|
48772
|
-
|
|
48773
|
-
|
|
48774
|
-
|
|
48775
|
-
|
|
48776
|
-
|
|
48777
|
-
|
|
48778
|
-
|
|
48779
|
-
type: "list",
|
|
48780
|
-
name: "action",
|
|
48781
|
-
message: "What would you like to do?",
|
|
48782
|
-
choices: [
|
|
48783
|
-
{ name: "Create a new wallet", value: "create" },
|
|
48784
|
-
{ name: "Import from recovery phrase", value: "import" }
|
|
48785
|
-
]
|
|
48786
|
-
}]);
|
|
48787
|
-
if (action === "create") {
|
|
48788
|
-
isNew = true;
|
|
48789
|
-
const wordCount = Number(opts.wordCount) === 24 ? 24 : 12;
|
|
48790
|
-
const result = createMnemonic(wordCount);
|
|
48791
|
-
mnemonic = result.phrase;
|
|
48792
|
-
if (!isJsonMode()) {
|
|
48793
|
-
console.log();
|
|
48794
|
-
console.log(warningBox("Recovery Phrase \u2014 Save This!", [
|
|
48795
|
-
colors.warning("Write down these words and store them safely."),
|
|
48796
|
-
colors.warning("Anyone with this phrase can access your funds."),
|
|
48797
|
-
"",
|
|
48798
|
-
colors.highlight(mnemonic),
|
|
48799
|
-
"",
|
|
48800
|
-
colors.muted(`${wordCount} words`)
|
|
48801
|
-
]));
|
|
48802
|
-
console.log();
|
|
48636
|
+
({ label, color, password } = await promptLabelColorPassword(opts));
|
|
48637
|
+
}
|
|
48638
|
+
const wordCount = Number(opts.wordCount) === 24 ? 24 : 12;
|
|
48639
|
+
const result = createMnemonic(wordCount);
|
|
48640
|
+
const mnemonic = result.phrase;
|
|
48641
|
+
if (!isJsonMode()) {
|
|
48642
|
+
console.log();
|
|
48643
|
+
console.log(warningBox("Recovery Phrase \u2014 Save This!", [
|
|
48644
|
+
colors.warning("Write down these words and store them safely."),
|
|
48645
|
+
colors.warning("Anyone with this phrase can access your funds."),
|
|
48646
|
+
"",
|
|
48647
|
+
colors.highlight(mnemonic),
|
|
48648
|
+
"",
|
|
48649
|
+
colors.muted(`${wordCount} words`)
|
|
48650
|
+
]));
|
|
48651
|
+
console.log();
|
|
48652
|
+
}
|
|
48653
|
+
const { walletId, firstAccount } = await initializeAndRegisterWallet(label, color, mnemonic, password);
|
|
48654
|
+
if (firstAccount) {
|
|
48655
|
+
output({
|
|
48656
|
+
success: true,
|
|
48657
|
+
isNew: true,
|
|
48658
|
+
walletId,
|
|
48659
|
+
label,
|
|
48660
|
+
color,
|
|
48661
|
+
mnemonic,
|
|
48662
|
+
account: {
|
|
48663
|
+
index: firstAccount.index,
|
|
48664
|
+
label: firstAccount.label,
|
|
48665
|
+
evmAddress: firstAccount.evmAddress,
|
|
48666
|
+
solanaAddress: firstAccount.solanaAddress
|
|
48803
48667
|
}
|
|
48668
|
+
}, () => {
|
|
48669
|
+
console.log();
|
|
48670
|
+
console.log(successBox(`Wallet: ${label}`, [
|
|
48671
|
+
kvLine("Wallet ID", walletId),
|
|
48672
|
+
kvLine("EVM Address", firstAccount.evmAddress),
|
|
48673
|
+
kvLine("Solana", firstAccount.solanaAddress),
|
|
48674
|
+
"",
|
|
48675
|
+
colors.muted("Vault encrypted and saved to ~/.zoa/")
|
|
48676
|
+
]));
|
|
48677
|
+
console.log();
|
|
48678
|
+
});
|
|
48679
|
+
}
|
|
48680
|
+
} catch (error) {
|
|
48681
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48682
|
+
outputError(msg);
|
|
48683
|
+
if (!isJsonMode())
|
|
48684
|
+
console.log(errorMsg(msg));
|
|
48685
|
+
process.exitCode = 1;
|
|
48686
|
+
}
|
|
48687
|
+
});
|
|
48688
|
+
wallet.command("import").description("Import a wallet from a recovery phrase").option("--label <label>", "Wallet label").option("--color <hex>", "Wallet color (hex)").option("--mnemonic <phrase>", "Recovery phrase").option("--password <password>", "Set wallet password").action(async (opts) => {
|
|
48689
|
+
try {
|
|
48690
|
+
let label;
|
|
48691
|
+
let color;
|
|
48692
|
+
let mnemonic;
|
|
48693
|
+
let password;
|
|
48694
|
+
if (opts.mnemonic && opts.password) {
|
|
48695
|
+
label = opts.label || "Imported Wallet";
|
|
48696
|
+
color = opts.color || "#00bbf9";
|
|
48697
|
+
mnemonic = opts.mnemonic;
|
|
48698
|
+
password = opts.password;
|
|
48699
|
+
} else {
|
|
48700
|
+
if (!isJsonMode()) {
|
|
48701
|
+
console.log(colors.brandBold(" Import Wallet from Recovery Phrase"));
|
|
48702
|
+
console.log();
|
|
48703
|
+
}
|
|
48704
|
+
({ label, color, password } = await promptLabelColorPassword(opts));
|
|
48705
|
+
if (opts.mnemonic) {
|
|
48706
|
+
mnemonic = opts.mnemonic;
|
|
48804
48707
|
} else {
|
|
48805
|
-
const { phrase } = await
|
|
48708
|
+
const { phrase } = await inquirer6.prompt([{
|
|
48806
48709
|
type: "input",
|
|
48807
48710
|
name: "phrase",
|
|
48808
|
-
message: "Enter your recovery phrase:"
|
|
48711
|
+
message: "Enter your recovery phrase:",
|
|
48712
|
+
validate: (input) => input.trim().split(/\s+/).length >= 12 || "Enter a valid 12 or 24 word recovery phrase"
|
|
48809
48713
|
}]);
|
|
48810
48714
|
mnemonic = phrase.trim();
|
|
48811
48715
|
}
|
|
48812
|
-
const { pwd } = await inquirer7.prompt([{
|
|
48813
|
-
type: "password",
|
|
48814
|
-
name: "pwd",
|
|
48815
|
-
message: "Set a secure password:",
|
|
48816
|
-
mask: "*",
|
|
48817
|
-
validate: (input) => input.length >= 8 || "Password must be at least 8 characters"
|
|
48818
|
-
}]);
|
|
48819
|
-
await inquirer7.prompt([{
|
|
48820
|
-
type: "password",
|
|
48821
|
-
name: "confirmPwd",
|
|
48822
|
-
message: "Confirm password:",
|
|
48823
|
-
mask: "*",
|
|
48824
|
-
validate: (input) => input === pwd || "Passwords do not match"
|
|
48825
|
-
}]);
|
|
48826
|
-
password = pwd;
|
|
48827
48716
|
}
|
|
48828
|
-
const
|
|
48829
|
-
if (!isJsonMode())
|
|
48830
|
-
spinner.start();
|
|
48831
|
-
const walletId = generateWalletId();
|
|
48832
|
-
const vaultKey = `wallet_${walletId}`;
|
|
48833
|
-
const storage = new FileStorage();
|
|
48834
|
-
const kr = createKeyring(storage, vaultKey);
|
|
48835
|
-
await kr.initialize(mnemonic, password);
|
|
48836
|
-
const accounts = kr.getAccounts();
|
|
48837
|
-
const firstAccount = accounts[0];
|
|
48838
|
-
await addWallet({
|
|
48839
|
-
id: walletId,
|
|
48840
|
-
label,
|
|
48841
|
-
color,
|
|
48842
|
-
vaultKey,
|
|
48843
|
-
createdAt: Date.now(),
|
|
48844
|
-
evmAddress: firstAccount?.evmAddress,
|
|
48845
|
-
solanaAddress: firstAccount?.solanaAddress
|
|
48846
|
-
});
|
|
48847
|
-
await setActiveWallet(walletId);
|
|
48848
|
-
if (!isJsonMode())
|
|
48849
|
-
spinner.succeed(" Wallet created successfully!");
|
|
48717
|
+
const { walletId, firstAccount } = await initializeAndRegisterWallet(label, color, mnemonic, password);
|
|
48850
48718
|
if (firstAccount) {
|
|
48851
48719
|
output({
|
|
48852
48720
|
success: true,
|
|
48853
|
-
isNew,
|
|
48721
|
+
isNew: false,
|
|
48854
48722
|
walletId,
|
|
48855
48723
|
label,
|
|
48856
48724
|
color,
|
|
@@ -48859,11 +48727,10 @@ function registerWalletCommand(program2) {
|
|
|
48859
48727
|
label: firstAccount.label,
|
|
48860
48728
|
evmAddress: firstAccount.evmAddress,
|
|
48861
48729
|
solanaAddress: firstAccount.solanaAddress
|
|
48862
|
-
}
|
|
48863
|
-
...isNew ? { mnemonic } : {}
|
|
48730
|
+
}
|
|
48864
48731
|
}, () => {
|
|
48865
48732
|
console.log();
|
|
48866
|
-
console.log(successBox(`Wallet: ${label}`, [
|
|
48733
|
+
console.log(successBox(`Wallet Imported: ${label}`, [
|
|
48867
48734
|
kvLine("Wallet ID", walletId),
|
|
48868
48735
|
kvLine("EVM Address", firstAccount.evmAddress),
|
|
48869
48736
|
kvLine("Solana", firstAccount.solanaAddress),
|
|
@@ -48896,12 +48763,12 @@ function registerWalletCommand(program2) {
|
|
|
48896
48763
|
targetId = match.id;
|
|
48897
48764
|
} else {
|
|
48898
48765
|
const active = await getActiveWallet();
|
|
48899
|
-
const { selected } = await
|
|
48766
|
+
const { selected } = await inquirer6.prompt([{
|
|
48900
48767
|
type: "list",
|
|
48901
48768
|
name: "selected",
|
|
48902
48769
|
message: "Select wallet:",
|
|
48903
48770
|
choices: wallets.map((w) => ({
|
|
48904
|
-
name: `${
|
|
48771
|
+
name: `${chalk3.hex(w.color)("\u25CF")} ${w.label}${w.id === active?.id ? chalk3.hex("#f59e0b")(" \u2605 active") : ""} ${colors.muted(`(${w.id})`)}`,
|
|
48905
48772
|
value: w.id
|
|
48906
48773
|
}))
|
|
48907
48774
|
}]);
|
|
@@ -48911,7 +48778,7 @@ function registerWalletCommand(program2) {
|
|
|
48911
48778
|
const switched = wallets.find((w) => w.id === targetId);
|
|
48912
48779
|
output({ success: true, activeWalletId: targetId, label: switched.label }, () => {
|
|
48913
48780
|
console.log(`
|
|
48914
|
-
${
|
|
48781
|
+
${chalk3.hex(switched.color)("\u25CF")} Switched to ${chalk3.bold(switched.label)} ${colors.muted(`(${switched.id})`)}
|
|
48915
48782
|
`);
|
|
48916
48783
|
});
|
|
48917
48784
|
} catch (error) {
|
|
@@ -48932,7 +48799,7 @@ function registerWalletCommand(program2) {
|
|
|
48932
48799
|
await updateWallet(match.id, { label: newLabel });
|
|
48933
48800
|
output({ success: true, id: match.id, label: newLabel }, () => {
|
|
48934
48801
|
console.log(`
|
|
48935
|
-
${
|
|
48802
|
+
${chalk3.hex(match.color)("\u25CF")} Renamed to ${chalk3.bold(newLabel)} ${colors.muted(`(${match.id})`)}
|
|
48936
48803
|
`);
|
|
48937
48804
|
});
|
|
48938
48805
|
} catch (error) {
|
|
@@ -48956,7 +48823,7 @@ function registerWalletCommand(program2) {
|
|
|
48956
48823
|
await updateWallet(match.id, { color: hex });
|
|
48957
48824
|
output({ success: true, id: match.id, color: hex }, () => {
|
|
48958
48825
|
console.log(`
|
|
48959
|
-
${
|
|
48826
|
+
${chalk3.hex(hex)("\u25CF")} Updated color for ${chalk3.bold(match.label)}
|
|
48960
48827
|
`);
|
|
48961
48828
|
});
|
|
48962
48829
|
} catch (error) {
|
|
@@ -48975,7 +48842,7 @@ function registerWalletCommand(program2) {
|
|
|
48975
48842
|
if (!match)
|
|
48976
48843
|
throw new Error(`No wallet found matching '${id}'`);
|
|
48977
48844
|
if (!opts.yes && !isJsonMode()) {
|
|
48978
|
-
const { confirm } = await
|
|
48845
|
+
const { confirm } = await inquirer6.prompt([{
|
|
48979
48846
|
type: "confirm",
|
|
48980
48847
|
name: "confirm",
|
|
48981
48848
|
message: `Remove wallet '${match.label}' (${match.id})? This will delete the vault file.`,
|
|
@@ -48991,7 +48858,7 @@ function registerWalletCommand(program2) {
|
|
|
48991
48858
|
await removeWallet(match.id);
|
|
48992
48859
|
output({ success: true, removed: match.id }, () => {
|
|
48993
48860
|
console.log(`
|
|
48994
|
-
${colors.error("\u2716")} Removed wallet ${
|
|
48861
|
+
${colors.error("\u2716")} Removed wallet ${chalk3.bold(match.label)} ${colors.muted(`(${match.id})`)}
|
|
48995
48862
|
`);
|
|
48996
48863
|
});
|
|
48997
48864
|
} catch (error) {
|
|
@@ -49013,7 +48880,7 @@ function registerWalletCommand(program2) {
|
|
|
49013
48880
|
if (opts.password) {
|
|
49014
48881
|
password = opts.password;
|
|
49015
48882
|
} else {
|
|
49016
|
-
const { pwd } = await
|
|
48883
|
+
const { pwd } = await inquirer6.prompt([{
|
|
49017
48884
|
type: "password",
|
|
49018
48885
|
name: "pwd",
|
|
49019
48886
|
message: "Enter your wallet password:",
|
|
@@ -49045,9 +48912,9 @@ function registerWalletCommand(program2) {
|
|
|
49045
48912
|
solanaAddress: a.solanaAddress
|
|
49046
48913
|
}))
|
|
49047
48914
|
}, () => {
|
|
49048
|
-
console.log(sectionHeader(`${
|
|
48915
|
+
console.log(sectionHeader(`${chalk3.hex(active.color)("\u25CF")} ${active.label}`));
|
|
49049
48916
|
console.log(kvLine("ID", active.id));
|
|
49050
|
-
console.log(kvLine("Color",
|
|
48917
|
+
console.log(kvLine("Color", chalk3.hex(active.color)(active.color)));
|
|
49051
48918
|
console.log(kvLine("Created", new Date(active.createdAt).toLocaleString()));
|
|
49052
48919
|
if (active.lastUsedAt) {
|
|
49053
48920
|
console.log(kvLine("Last Used", new Date(active.lastUsedAt).toLocaleString()));
|
|
@@ -49071,7 +48938,7 @@ function registerWalletCommand(program2) {
|
|
|
49071
48938
|
}
|
|
49072
48939
|
|
|
49073
48940
|
// dist/ui/banner.js
|
|
49074
|
-
import
|
|
48941
|
+
import chalk4 from "chalk";
|
|
49075
48942
|
import figlet from "figlet";
|
|
49076
48943
|
import gradient2 from "gradient-string";
|
|
49077
48944
|
var zoaGradient2 = gradient2([
|
|
@@ -49082,7 +48949,7 @@ var zoaGradient2 = gradient2([
|
|
|
49082
48949
|
"#c77dff"
|
|
49083
48950
|
]);
|
|
49084
48951
|
var subtleGradient = gradient2(["#6b7280", "#9ca3af", "#6b7280"]);
|
|
49085
|
-
var VERSION = "0.2.
|
|
48952
|
+
var VERSION = "0.2.9";
|
|
49086
48953
|
async function displayBanner() {
|
|
49087
48954
|
const banner = figlet.textSync("ZOA-wallet", { font: "ANSI Shadow" });
|
|
49088
48955
|
console.log();
|
|
@@ -49090,20 +48957,20 @@ async function displayBanner() {
|
|
|
49090
48957
|
const tagline = " API-First Crypto Wallet for Power-traders, Developers, & AI Agents";
|
|
49091
48958
|
console.log(subtleGradient(tagline));
|
|
49092
48959
|
console.log();
|
|
49093
|
-
const versionBadge =
|
|
49094
|
-
const siteLink =
|
|
49095
|
-
const npmBadge =
|
|
48960
|
+
const versionBadge = chalk4.bgHex("#5e60ce").white.bold(` v${VERSION} `);
|
|
48961
|
+
const siteLink = chalk4.hex("#9ca3af")("https://") + chalk4.hex("#ff6b35")("wallet") + chalk4.hex("#00bbf9")(".zoa.fun");
|
|
48962
|
+
const npmBadge = chalk4.hex("#cb3837")("npm") + chalk4.hex("#6b7280")(" zoa-wallet");
|
|
49096
48963
|
let walletIndicator = "";
|
|
49097
48964
|
try {
|
|
49098
48965
|
const active = await getActiveWallet();
|
|
49099
48966
|
if (active) {
|
|
49100
|
-
walletIndicator = ` ${
|
|
48967
|
+
walletIndicator = ` ${chalk4.hex("#3b3b3b")("\u2502")} ${chalk4.hex(active.color)("\u25CF")} ${chalk4.bold(active.label)}`;
|
|
49101
48968
|
}
|
|
49102
48969
|
} catch {
|
|
49103
48970
|
}
|
|
49104
|
-
console.log(` ${versionBadge} ${
|
|
48971
|
+
console.log(` ${versionBadge} ${chalk4.hex("#3b3b3b")("\u2502")} ${siteLink} ${chalk4.hex("#3b3b3b")("\u2502")} ${npmBadge}${walletIndicator}`);
|
|
49105
48972
|
console.log();
|
|
49106
|
-
console.log(
|
|
48973
|
+
console.log(chalk4.hex("#2d2d2d")(" " + "\u2500".repeat(58)));
|
|
49107
48974
|
console.log();
|
|
49108
48975
|
}
|
|
49109
48976
|
|
|
@@ -49120,8 +48987,7 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
49120
48987
|
}
|
|
49121
48988
|
}
|
|
49122
48989
|
});
|
|
49123
|
-
program.name("zoa").description("ZOA Wallet \u2014 API-First Crypto Wallet for Power-traders, Developers, & AI Agents").version("0.2.
|
|
49124
|
-
registerInitCommand(program);
|
|
48990
|
+
program.name("zoa").description("ZOA Wallet \u2014 API-First Crypto Wallet for Power-traders, Developers, & AI Agents").version("0.2.9");
|
|
49125
48991
|
registerWalletCommand(program);
|
|
49126
48992
|
registerBalanceCommand(program);
|
|
49127
48993
|
registerSendCommand(program);
|
package/package.json
CHANGED