zoa-wallet 0.2.3 → 0.2.5
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 +605 -101
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -22224,6 +22224,63 @@ async function deleteConfigValue(key) {
|
|
|
22224
22224
|
function getConfigFilePath() {
|
|
22225
22225
|
return CONFIG_FILE;
|
|
22226
22226
|
}
|
|
22227
|
+
function generateWalletId() {
|
|
22228
|
+
const hex = Array.from(crypto.getRandomValues(new Uint8Array(4))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
22229
|
+
return `w_${hex}`;
|
|
22230
|
+
}
|
|
22231
|
+
async function getWallets() {
|
|
22232
|
+
const config = await loadConfig();
|
|
22233
|
+
return config.wallets ?? [];
|
|
22234
|
+
}
|
|
22235
|
+
async function getActiveWallet() {
|
|
22236
|
+
const config = await loadConfig();
|
|
22237
|
+
if (!config.activeWalletId || !config.wallets?.length)
|
|
22238
|
+
return null;
|
|
22239
|
+
return config.wallets.find((w) => w.id === config.activeWalletId) ?? null;
|
|
22240
|
+
}
|
|
22241
|
+
async function getActiveAccountIndex() {
|
|
22242
|
+
const config = await loadConfig();
|
|
22243
|
+
return config.activeAccountIndex ?? 0;
|
|
22244
|
+
}
|
|
22245
|
+
async function addWallet(entry) {
|
|
22246
|
+
const config = await loadConfig();
|
|
22247
|
+
config.wallets = config.wallets ?? [];
|
|
22248
|
+
config.wallets.push(entry);
|
|
22249
|
+
if (!config.activeWalletId) {
|
|
22250
|
+
config.activeWalletId = entry.id;
|
|
22251
|
+
}
|
|
22252
|
+
await saveConfig(config);
|
|
22253
|
+
}
|
|
22254
|
+
async function removeWallet(id) {
|
|
22255
|
+
const config = await loadConfig();
|
|
22256
|
+
config.wallets = (config.wallets ?? []).filter((w) => w.id !== id);
|
|
22257
|
+
if (config.activeWalletId === id) {
|
|
22258
|
+
config.activeWalletId = config.wallets[0]?.id;
|
|
22259
|
+
config.activeAccountIndex = 0;
|
|
22260
|
+
}
|
|
22261
|
+
await saveConfig(config);
|
|
22262
|
+
}
|
|
22263
|
+
async function setActiveWallet(id) {
|
|
22264
|
+
const config = await loadConfig();
|
|
22265
|
+
const wallet = (config.wallets ?? []).find((w) => w.id === id);
|
|
22266
|
+
if (!wallet)
|
|
22267
|
+
throw new Error(`Wallet ${id} not found`);
|
|
22268
|
+
config.activeWalletId = id;
|
|
22269
|
+
config.activeAccountIndex = 0;
|
|
22270
|
+
wallet.lastUsedAt = Date.now();
|
|
22271
|
+
await saveConfig(config);
|
|
22272
|
+
}
|
|
22273
|
+
async function updateWallet(id, updates) {
|
|
22274
|
+
const config = await loadConfig();
|
|
22275
|
+
const wallet = (config.wallets ?? []).find((w) => w.id === id);
|
|
22276
|
+
if (!wallet)
|
|
22277
|
+
throw new Error(`Wallet ${id} not found`);
|
|
22278
|
+
if (updates.label !== void 0)
|
|
22279
|
+
wallet.label = updates.label;
|
|
22280
|
+
if (updates.color !== void 0)
|
|
22281
|
+
wallet.color = updates.color;
|
|
22282
|
+
await saveConfig(config);
|
|
22283
|
+
}
|
|
22227
22284
|
|
|
22228
22285
|
// dist/utils/output.js
|
|
22229
22286
|
var _outputMode = "pretty";
|
|
@@ -44074,6 +44131,49 @@ var ChainAdapterRegistry = class {
|
|
|
44074
44131
|
};
|
|
44075
44132
|
var chainRegistry = new ChainAdapterRegistry();
|
|
44076
44133
|
|
|
44134
|
+
// dist/commands/balance.js
|
|
44135
|
+
import inquirer from "inquirer";
|
|
44136
|
+
|
|
44137
|
+
// dist/utils/format.js
|
|
44138
|
+
function truncateAddress(address, chars = 6) {
|
|
44139
|
+
if (address.length <= chars * 2 + 3)
|
|
44140
|
+
return address;
|
|
44141
|
+
return `${address.slice(0, chars + 2)}...${address.slice(-chars)}`;
|
|
44142
|
+
}
|
|
44143
|
+
function formatBalance(balance, decimals = 4) {
|
|
44144
|
+
const num2 = typeof balance === "string" ? Number.parseFloat(balance) : balance;
|
|
44145
|
+
if (num2 === 0)
|
|
44146
|
+
return "0";
|
|
44147
|
+
if (num2 < 1e-4)
|
|
44148
|
+
return "< 0.0001";
|
|
44149
|
+
return num2.toFixed(decimals).replace(/\.?0+$/, "");
|
|
44150
|
+
}
|
|
44151
|
+
function formatUSD(value) {
|
|
44152
|
+
if (value < 0.01)
|
|
44153
|
+
return "< $0.01";
|
|
44154
|
+
return `$${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
44155
|
+
}
|
|
44156
|
+
function timeAgo(timestamp) {
|
|
44157
|
+
const seconds = Math.floor((Date.now() - timestamp * 1e3) / 1e3);
|
|
44158
|
+
if (seconds < 60)
|
|
44159
|
+
return `${seconds}s ago`;
|
|
44160
|
+
const minutes = Math.floor(seconds / 60);
|
|
44161
|
+
if (minutes < 60)
|
|
44162
|
+
return `${minutes}m ago`;
|
|
44163
|
+
const hours = Math.floor(minutes / 60);
|
|
44164
|
+
if (hours < 24)
|
|
44165
|
+
return `${hours}h ago`;
|
|
44166
|
+
const days = Math.floor(hours / 24);
|
|
44167
|
+
if (days < 30)
|
|
44168
|
+
return `${days}d ago`;
|
|
44169
|
+
const months = Math.floor(days / 30);
|
|
44170
|
+
return `${months}mo ago`;
|
|
44171
|
+
}
|
|
44172
|
+
function formatGas(wei, decimals = 18) {
|
|
44173
|
+
const value = Number(wei) / 10 ** decimals;
|
|
44174
|
+
return formatBalance(value, 6);
|
|
44175
|
+
}
|
|
44176
|
+
|
|
44077
44177
|
// ../../packages/wallet-core/dist/storage.js
|
|
44078
44178
|
function uint8ToBase64(bytes) {
|
|
44079
44179
|
let binary = "";
|
|
@@ -47399,17 +47499,17 @@ async function decryptVault(vault, password) {
|
|
|
47399
47499
|
throw new Error("Incorrect password or corrupted vault");
|
|
47400
47500
|
}
|
|
47401
47501
|
}
|
|
47402
|
-
async function saveVault(vault, storage) {
|
|
47502
|
+
async function saveVault(vault, storage, key) {
|
|
47403
47503
|
const backend = storage ?? getDefaultStorage();
|
|
47404
|
-
await backend.save(VAULT_KEY, vault);
|
|
47504
|
+
await backend.save(key ?? VAULT_KEY, vault);
|
|
47405
47505
|
}
|
|
47406
|
-
async function loadVault(storage) {
|
|
47506
|
+
async function loadVault(storage, key) {
|
|
47407
47507
|
const backend = storage ?? getDefaultStorage();
|
|
47408
|
-
return backend.load(VAULT_KEY);
|
|
47508
|
+
return backend.load(key ?? VAULT_KEY);
|
|
47409
47509
|
}
|
|
47410
|
-
async function hasVault(storage) {
|
|
47510
|
+
async function hasVault(storage, key) {
|
|
47411
47511
|
const backend = storage ?? getDefaultStorage();
|
|
47412
|
-
return backend.has(VAULT_KEY);
|
|
47512
|
+
return backend.has(key ?? VAULT_KEY);
|
|
47413
47513
|
}
|
|
47414
47514
|
async function deriveEncryptionKey(password, salt, iterations) {
|
|
47415
47515
|
const encoder5 = new TextEncoder();
|
|
@@ -47449,8 +47549,10 @@ var KeyringManager = class {
|
|
|
47449
47549
|
_seed = null;
|
|
47450
47550
|
_accounts = [];
|
|
47451
47551
|
_storage;
|
|
47452
|
-
|
|
47552
|
+
_vaultKey;
|
|
47553
|
+
constructor(storage, vaultKey) {
|
|
47453
47554
|
this._storage = storage;
|
|
47555
|
+
this._vaultKey = vaultKey;
|
|
47454
47556
|
}
|
|
47455
47557
|
get state() {
|
|
47456
47558
|
return this._state;
|
|
@@ -47464,12 +47566,12 @@ var KeyringManager = class {
|
|
|
47464
47566
|
const account = await this.deriveAccount(0, "Account 1");
|
|
47465
47567
|
this._accounts = [account];
|
|
47466
47568
|
const vault = await encryptVault(this._mnemonic, password, [{ index: 0, label: "Account 1" }]);
|
|
47467
|
-
await saveVault(vault, this._storage);
|
|
47569
|
+
await saveVault(vault, this._storage, this._vaultKey);
|
|
47468
47570
|
this.persistSession();
|
|
47469
47571
|
this._state = "unlocked";
|
|
47470
47572
|
}
|
|
47471
47573
|
async unlock(password) {
|
|
47472
|
-
const vault = await loadVault(this._storage);
|
|
47574
|
+
const vault = await loadVault(this._storage, this._vaultKey);
|
|
47473
47575
|
if (!vault) {
|
|
47474
47576
|
throw new Error("No vault found. Initialize a wallet first.");
|
|
47475
47577
|
}
|
|
@@ -47491,7 +47593,7 @@ var KeyringManager = class {
|
|
|
47491
47593
|
if (!sessionMnemonic)
|
|
47492
47594
|
return false;
|
|
47493
47595
|
try {
|
|
47494
|
-
const vault = await loadVault(this._storage);
|
|
47596
|
+
const vault = await loadVault(this._storage, this._vaultKey);
|
|
47495
47597
|
if (!vault)
|
|
47496
47598
|
return false;
|
|
47497
47599
|
this._mnemonic = sessionMnemonic;
|
|
@@ -47581,7 +47683,7 @@ var KeyringManager = class {
|
|
|
47581
47683
|
return `0x${bytesToHex7(account.keys.evm.privateKey)}`;
|
|
47582
47684
|
}
|
|
47583
47685
|
async hasVault() {
|
|
47584
|
-
return hasVault(this._storage);
|
|
47686
|
+
return hasVault(this._storage, this._vaultKey);
|
|
47585
47687
|
}
|
|
47586
47688
|
requireUnlocked() {
|
|
47587
47689
|
if (this._state !== "unlocked") {
|
|
@@ -47606,13 +47708,13 @@ var KeyringManager = class {
|
|
|
47606
47708
|
async persistAccountMetadata() {
|
|
47607
47709
|
if (!this._mnemonic)
|
|
47608
47710
|
return;
|
|
47609
|
-
const vault = await loadVault(this._storage);
|
|
47711
|
+
const vault = await loadVault(this._storage, this._vaultKey);
|
|
47610
47712
|
if (vault) {
|
|
47611
47713
|
vault.accounts = this._accounts.map((a) => ({
|
|
47612
47714
|
index: a.index,
|
|
47613
47715
|
label: a.label
|
|
47614
47716
|
}));
|
|
47615
|
-
await saveVault(vault, this._storage);
|
|
47717
|
+
await saveVault(vault, this._storage, this._vaultKey);
|
|
47616
47718
|
}
|
|
47617
47719
|
}
|
|
47618
47720
|
persistSession() {
|
|
@@ -47621,8 +47723,8 @@ var KeyringManager = class {
|
|
|
47621
47723
|
}
|
|
47622
47724
|
}
|
|
47623
47725
|
};
|
|
47624
|
-
function createKeyring(storage) {
|
|
47625
|
-
return new KeyringManager(storage);
|
|
47726
|
+
function createKeyring(storage, vaultKey) {
|
|
47727
|
+
return new KeyringManager(storage, vaultKey);
|
|
47626
47728
|
}
|
|
47627
47729
|
var keyring = new KeyringManager();
|
|
47628
47730
|
|
|
@@ -47678,47 +47780,46 @@ var FileStorage = class {
|
|
|
47678
47780
|
}
|
|
47679
47781
|
};
|
|
47680
47782
|
|
|
47681
|
-
// dist/
|
|
47682
|
-
|
|
47683
|
-
|
|
47684
|
-
|
|
47685
|
-
|
|
47686
|
-
if (
|
|
47687
|
-
|
|
47688
|
-
|
|
47689
|
-
|
|
47690
|
-
|
|
47691
|
-
|
|
47692
|
-
|
|
47693
|
-
|
|
47694
|
-
|
|
47695
|
-
|
|
47696
|
-
|
|
47697
|
-
|
|
47698
|
-
|
|
47699
|
-
if (
|
|
47700
|
-
|
|
47701
|
-
|
|
47702
|
-
}
|
|
47703
|
-
|
|
47704
|
-
const seconds = Math.floor((Date.now() - timestamp * 1e3) / 1e3);
|
|
47705
|
-
if (seconds < 60)
|
|
47706
|
-
return `${seconds}s ago`;
|
|
47707
|
-
const minutes = Math.floor(seconds / 60);
|
|
47708
|
-
if (minutes < 60)
|
|
47709
|
-
return `${minutes}m ago`;
|
|
47710
|
-
const hours = Math.floor(minutes / 60);
|
|
47711
|
-
if (hours < 24)
|
|
47712
|
-
return `${hours}h ago`;
|
|
47713
|
-
const days = Math.floor(hours / 24);
|
|
47714
|
-
if (days < 30)
|
|
47715
|
-
return `${days}d ago`;
|
|
47716
|
-
const months = Math.floor(days / 30);
|
|
47717
|
-
return `${months}mo ago`;
|
|
47783
|
+
// dist/utils/wallet.js
|
|
47784
|
+
var LEGACY_VAULT_KEY = "zoa-vault";
|
|
47785
|
+
async function loadActiveWallet(password) {
|
|
47786
|
+
await migrateLegacyVaultIfNeeded();
|
|
47787
|
+
const wallet = await getActiveWallet();
|
|
47788
|
+
if (!wallet) {
|
|
47789
|
+
throw new Error("No wallet configured. Run 'zoa wallet create' or 'zoa init' first.");
|
|
47790
|
+
}
|
|
47791
|
+
const storage = new FileStorage();
|
|
47792
|
+
const kr = createKeyring(storage, wallet.vaultKey);
|
|
47793
|
+
await kr.unlock(password);
|
|
47794
|
+
const accounts = kr.getAccounts();
|
|
47795
|
+
const accountIndex = await getActiveAccountIndex();
|
|
47796
|
+
const account = accounts[accountIndex] ?? accounts[0];
|
|
47797
|
+
if (!account)
|
|
47798
|
+
throw new Error("No accounts found in wallet.");
|
|
47799
|
+
const config = await loadConfig();
|
|
47800
|
+
const entry = (config.wallets ?? []).find((w) => w.id === wallet.id);
|
|
47801
|
+
if (entry) {
|
|
47802
|
+
entry.lastUsedAt = Date.now();
|
|
47803
|
+
await saveConfig(config);
|
|
47804
|
+
}
|
|
47805
|
+
return { keyring: kr, wallet, account };
|
|
47718
47806
|
}
|
|
47719
|
-
function
|
|
47720
|
-
const
|
|
47721
|
-
|
|
47807
|
+
async function migrateLegacyVaultIfNeeded() {
|
|
47808
|
+
const wallets = await getWallets();
|
|
47809
|
+
if (wallets.length > 0)
|
|
47810
|
+
return;
|
|
47811
|
+
const storage = new FileStorage();
|
|
47812
|
+
const hasLegacy = await storage.has(LEGACY_VAULT_KEY);
|
|
47813
|
+
if (!hasLegacy)
|
|
47814
|
+
return;
|
|
47815
|
+
const id = generateWalletId();
|
|
47816
|
+
await addWallet({
|
|
47817
|
+
id,
|
|
47818
|
+
label: "Default Wallet",
|
|
47819
|
+
color: "#00bbf9",
|
|
47820
|
+
vaultKey: LEGACY_VAULT_KEY,
|
|
47821
|
+
createdAt: Date.now()
|
|
47822
|
+
});
|
|
47722
47823
|
}
|
|
47723
47824
|
|
|
47724
47825
|
// dist/commands/balance.js
|
|
@@ -47750,13 +47851,7 @@ function registerBalanceCommand(program2) {
|
|
|
47750
47851
|
const spinner = createSpinner("Unlocking wallet...");
|
|
47751
47852
|
if (!isJsonMode())
|
|
47752
47853
|
spinner.start();
|
|
47753
|
-
const
|
|
47754
|
-
const kr = createKeyring(storage);
|
|
47755
|
-
await kr.unlock(password);
|
|
47756
|
-
const accounts = kr.getAccounts();
|
|
47757
|
-
const account = accounts[0];
|
|
47758
|
-
if (!account)
|
|
47759
|
-
throw new Error("No accounts found.");
|
|
47854
|
+
const { account } = await loadActiveWallet(password);
|
|
47760
47855
|
if (!isJsonMode())
|
|
47761
47856
|
spinner.text = " Fetching balances across networks...";
|
|
47762
47857
|
let chainsToFetch = Object.entries(CHAIN_MAP);
|
|
@@ -47939,9 +48034,7 @@ function registerExportCommand(program2) {
|
|
|
47939
48034
|
const spinner = createSpinner("Unlocking wallet...");
|
|
47940
48035
|
if (!isJsonMode())
|
|
47941
48036
|
spinner.start();
|
|
47942
|
-
const
|
|
47943
|
-
const kr = createKeyring(storage);
|
|
47944
|
-
await kr.unlock(password);
|
|
48037
|
+
const { keyring: kr } = await loadActiveWallet(password);
|
|
47945
48038
|
if (!isJsonMode())
|
|
47946
48039
|
spinner.stop();
|
|
47947
48040
|
let exportType = opts.type;
|
|
@@ -48030,13 +48123,7 @@ function registerHistoryCommand(program2) {
|
|
|
48030
48123
|
const spinner = createSpinner("Unlocking wallet...");
|
|
48031
48124
|
if (!isJsonMode())
|
|
48032
48125
|
spinner.start();
|
|
48033
|
-
const
|
|
48034
|
-
const kr = createKeyring(storage);
|
|
48035
|
-
await kr.unlock(password);
|
|
48036
|
-
const accounts = kr.getAccounts();
|
|
48037
|
-
const account = accounts[0];
|
|
48038
|
-
if (!account)
|
|
48039
|
-
throw new Error("No accounts found.");
|
|
48126
|
+
const { account } = await loadActiveWallet(password);
|
|
48040
48127
|
const chainMap = {
|
|
48041
48128
|
ethereum: ChainId.Ethereum,
|
|
48042
48129
|
base: ChainId.Base,
|
|
@@ -48164,9 +48251,19 @@ function registerInitCommand(program2) {
|
|
|
48164
48251
|
const spinner = createSpinner("Deriving keys and encrypting vault...");
|
|
48165
48252
|
if (!isJsonMode())
|
|
48166
48253
|
spinner.start();
|
|
48254
|
+
const walletId = generateWalletId();
|
|
48255
|
+
const vaultKey = `wallet_${walletId}`;
|
|
48167
48256
|
const storage = new FileStorage();
|
|
48168
|
-
const kr = createKeyring(storage);
|
|
48257
|
+
const kr = createKeyring(storage, vaultKey);
|
|
48169
48258
|
await kr.initialize(mnemonic, password);
|
|
48259
|
+
await addWallet({
|
|
48260
|
+
id: walletId,
|
|
48261
|
+
label: "Default Wallet",
|
|
48262
|
+
color: "#00bbf9",
|
|
48263
|
+
vaultKey,
|
|
48264
|
+
createdAt: Date.now()
|
|
48265
|
+
});
|
|
48266
|
+
await setActiveWallet(walletId);
|
|
48170
48267
|
if (!isJsonMode())
|
|
48171
48268
|
spinner.succeed(" Wallet initialized successfully!");
|
|
48172
48269
|
const accounts = kr.getAccounts();
|
|
@@ -48289,13 +48386,7 @@ function registerReceiveCommand(program2) {
|
|
|
48289
48386
|
const spinner = createSpinner("Unlocking wallet...");
|
|
48290
48387
|
if (!isJsonMode())
|
|
48291
48388
|
spinner.start();
|
|
48292
|
-
const
|
|
48293
|
-
const kr = createKeyring(storage);
|
|
48294
|
-
await kr.unlock(password);
|
|
48295
|
-
const accounts = kr.getAccounts();
|
|
48296
|
-
const account = accounts[0];
|
|
48297
|
-
if (!account)
|
|
48298
|
-
throw new Error("No accounts found.");
|
|
48389
|
+
const { account } = await loadActiveWallet(password);
|
|
48299
48390
|
if (!isJsonMode())
|
|
48300
48391
|
spinner.stop();
|
|
48301
48392
|
const showEvm = !opts.chain || opts.chain === "evm";
|
|
@@ -48393,13 +48484,7 @@ function registerSendCommand(program2) {
|
|
|
48393
48484
|
const spinner = createSpinner("Unlocking wallet...");
|
|
48394
48485
|
if (!isJsonMode())
|
|
48395
48486
|
spinner.start();
|
|
48396
|
-
const
|
|
48397
|
-
const kr = createKeyring(storage);
|
|
48398
|
-
await kr.unlock(password);
|
|
48399
|
-
const accounts = kr.getAccounts();
|
|
48400
|
-
const account = accounts[0];
|
|
48401
|
-
if (!account)
|
|
48402
|
-
throw new Error("No accounts found.");
|
|
48487
|
+
const { account } = await loadActiveWallet(password);
|
|
48403
48488
|
if (!isJsonMode())
|
|
48404
48489
|
spinner.text = " Estimating gas...";
|
|
48405
48490
|
const chainMap = {
|
|
@@ -48480,8 +48565,416 @@ function registerSendCommand(program2) {
|
|
|
48480
48565
|
});
|
|
48481
48566
|
}
|
|
48482
48567
|
|
|
48483
|
-
// dist/
|
|
48568
|
+
// dist/commands/wallet.js
|
|
48484
48569
|
import chalk3 from "chalk";
|
|
48570
|
+
import inquirer7 from "inquirer";
|
|
48571
|
+
var COLOR_PRESETS = [
|
|
48572
|
+
{ name: "Cyan", hex: "#00bbf9" },
|
|
48573
|
+
{ name: "Orange", hex: "#ff6b35" },
|
|
48574
|
+
{ name: "Purple", hex: "#7b2ff7" },
|
|
48575
|
+
{ name: "Green", hex: "#10b981" },
|
|
48576
|
+
{ name: "Pink", hex: "#ec4899" },
|
|
48577
|
+
{ name: "Yellow", hex: "#f59e0b" },
|
|
48578
|
+
{ name: "Red", hex: "#ef4444" },
|
|
48579
|
+
{ name: "Teal", hex: "#14b8a6" }
|
|
48580
|
+
];
|
|
48581
|
+
function registerWalletCommand(program2) {
|
|
48582
|
+
const wallet = program2.command("wallet").description("Manage multiple wallets");
|
|
48583
|
+
wallet.command("list").description("List all wallets").action(async () => {
|
|
48584
|
+
try {
|
|
48585
|
+
await migrateLegacyVaultIfNeeded();
|
|
48586
|
+
const wallets = await getWallets();
|
|
48587
|
+
const active = await getActiveWallet();
|
|
48588
|
+
if (wallets.length === 0) {
|
|
48589
|
+
output({ wallets: [] }, () => {
|
|
48590
|
+
console.log(colors.muted("\n No wallets configured. Run 'zoa wallet create' to get started.\n"));
|
|
48591
|
+
});
|
|
48592
|
+
return;
|
|
48593
|
+
}
|
|
48594
|
+
output({
|
|
48595
|
+
wallets: wallets.map((w) => ({
|
|
48596
|
+
...w,
|
|
48597
|
+
active: w.id === active?.id
|
|
48598
|
+
})),
|
|
48599
|
+
activeWalletId: active?.id
|
|
48600
|
+
}, () => {
|
|
48601
|
+
console.log(sectionHeader("Wallets"));
|
|
48602
|
+
const table = createTable(["", "Label", "ID", "Created", "Last Used"], [4, 22, 14, 14, 14]);
|
|
48603
|
+
for (const w of wallets) {
|
|
48604
|
+
const isActive = w.id === active?.id;
|
|
48605
|
+
const dot = chalk3.hex(w.color)("\u25CF");
|
|
48606
|
+
const indicator = isActive ? ` ${chalk3.hex("#f59e0b")("\u2605")}` : "";
|
|
48607
|
+
const label = isActive ? chalk3.bold(w.label) : w.label;
|
|
48608
|
+
const created = new Date(w.createdAt).toLocaleDateString();
|
|
48609
|
+
const lastUsed = w.lastUsedAt ? new Date(w.lastUsedAt).toLocaleDateString() : colors.muted("never");
|
|
48610
|
+
table.push([
|
|
48611
|
+
`${dot}${indicator}`,
|
|
48612
|
+
label,
|
|
48613
|
+
colors.muted(w.id),
|
|
48614
|
+
colors.muted(created),
|
|
48615
|
+
typeof lastUsed === "string" ? lastUsed : lastUsed
|
|
48616
|
+
]);
|
|
48617
|
+
}
|
|
48618
|
+
console.log(table.toString());
|
|
48619
|
+
console.log();
|
|
48620
|
+
});
|
|
48621
|
+
} catch (error) {
|
|
48622
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48623
|
+
outputError(msg);
|
|
48624
|
+
if (!isJsonMode())
|
|
48625
|
+
console.log(errorMsg(msg));
|
|
48626
|
+
process.exitCode = 1;
|
|
48627
|
+
}
|
|
48628
|
+
});
|
|
48629
|
+
wallet.command("create").description("Create a new wallet").option("--label <label>", "Wallet label").option("--color <hex>", "Wallet color (hex)").option("--mnemonic <phrase>", "Import mnemonic phrase").option("--password <password>", "Set wallet password").option("--word-count <count>", "Word count for new mnemonic: 12 or 24", "12").action(async (opts) => {
|
|
48630
|
+
try {
|
|
48631
|
+
let label;
|
|
48632
|
+
let color;
|
|
48633
|
+
let mnemonic;
|
|
48634
|
+
let password;
|
|
48635
|
+
let isNew = false;
|
|
48636
|
+
if (opts.label && opts.password) {
|
|
48637
|
+
label = opts.label;
|
|
48638
|
+
color = opts.color || "#00bbf9";
|
|
48639
|
+
if (opts.mnemonic) {
|
|
48640
|
+
mnemonic = opts.mnemonic;
|
|
48641
|
+
} else {
|
|
48642
|
+
const wordCount = Number(opts.wordCount) === 24 ? 24 : 12;
|
|
48643
|
+
const result = createMnemonic(wordCount);
|
|
48644
|
+
mnemonic = result.phrase;
|
|
48645
|
+
isNew = true;
|
|
48646
|
+
}
|
|
48647
|
+
password = opts.password;
|
|
48648
|
+
} else {
|
|
48649
|
+
if (!isJsonMode()) {
|
|
48650
|
+
console.log(colors.brandBold(" Create New Wallet"));
|
|
48651
|
+
console.log();
|
|
48652
|
+
}
|
|
48653
|
+
const { walletLabel } = await inquirer7.prompt([{
|
|
48654
|
+
type: "input",
|
|
48655
|
+
name: "walletLabel",
|
|
48656
|
+
message: "Wallet label:",
|
|
48657
|
+
default: "My Wallet",
|
|
48658
|
+
validate: (input) => input.trim().length > 0 || "Label is required"
|
|
48659
|
+
}]);
|
|
48660
|
+
label = walletLabel;
|
|
48661
|
+
const colorChoices = COLOR_PRESETS.map((c) => ({
|
|
48662
|
+
name: `${chalk3.hex(c.hex)("\u25CF")} ${c.name}`,
|
|
48663
|
+
value: c.hex
|
|
48664
|
+
}));
|
|
48665
|
+
colorChoices.push({ name: "Custom hex...", value: "custom" });
|
|
48666
|
+
const { selectedColor } = await inquirer7.prompt([{
|
|
48667
|
+
type: "list",
|
|
48668
|
+
name: "selectedColor",
|
|
48669
|
+
message: "Choose a color:",
|
|
48670
|
+
choices: colorChoices
|
|
48671
|
+
}]);
|
|
48672
|
+
if (selectedColor === "custom") {
|
|
48673
|
+
const { customHex } = await inquirer7.prompt([{
|
|
48674
|
+
type: "input",
|
|
48675
|
+
name: "customHex",
|
|
48676
|
+
message: "Enter hex color (e.g. #ff6b35):",
|
|
48677
|
+
validate: (input) => /^#[0-9a-fA-F]{6}$/.test(input) || "Enter a valid hex color"
|
|
48678
|
+
}]);
|
|
48679
|
+
color = customHex;
|
|
48680
|
+
} else {
|
|
48681
|
+
color = selectedColor;
|
|
48682
|
+
}
|
|
48683
|
+
const { action } = await inquirer7.prompt([{
|
|
48684
|
+
type: "list",
|
|
48685
|
+
name: "action",
|
|
48686
|
+
message: "What would you like to do?",
|
|
48687
|
+
choices: [
|
|
48688
|
+
{ name: "Create a new wallet", value: "create" },
|
|
48689
|
+
{ name: "Import from recovery phrase", value: "import" }
|
|
48690
|
+
]
|
|
48691
|
+
}]);
|
|
48692
|
+
if (action === "create") {
|
|
48693
|
+
isNew = true;
|
|
48694
|
+
const wordCount = Number(opts.wordCount) === 24 ? 24 : 12;
|
|
48695
|
+
const result = createMnemonic(wordCount);
|
|
48696
|
+
mnemonic = result.phrase;
|
|
48697
|
+
if (!isJsonMode()) {
|
|
48698
|
+
console.log();
|
|
48699
|
+
console.log(warningBox("Recovery Phrase \u2014 Save This!", [
|
|
48700
|
+
colors.warning("Write down these words and store them safely."),
|
|
48701
|
+
colors.warning("Anyone with this phrase can access your funds."),
|
|
48702
|
+
"",
|
|
48703
|
+
colors.highlight(mnemonic),
|
|
48704
|
+
"",
|
|
48705
|
+
colors.muted(`${wordCount} words`)
|
|
48706
|
+
]));
|
|
48707
|
+
console.log();
|
|
48708
|
+
}
|
|
48709
|
+
} else {
|
|
48710
|
+
const { phrase } = await inquirer7.prompt([{
|
|
48711
|
+
type: "input",
|
|
48712
|
+
name: "phrase",
|
|
48713
|
+
message: "Enter your recovery phrase:"
|
|
48714
|
+
}]);
|
|
48715
|
+
mnemonic = phrase.trim();
|
|
48716
|
+
}
|
|
48717
|
+
const { pwd } = await inquirer7.prompt([{
|
|
48718
|
+
type: "password",
|
|
48719
|
+
name: "pwd",
|
|
48720
|
+
message: "Set a secure password:",
|
|
48721
|
+
mask: "*",
|
|
48722
|
+
validate: (input) => input.length >= 8 || "Password must be at least 8 characters"
|
|
48723
|
+
}]);
|
|
48724
|
+
await inquirer7.prompt([{
|
|
48725
|
+
type: "password",
|
|
48726
|
+
name: "confirmPwd",
|
|
48727
|
+
message: "Confirm password:",
|
|
48728
|
+
mask: "*",
|
|
48729
|
+
validate: (input) => input === pwd || "Passwords do not match"
|
|
48730
|
+
}]);
|
|
48731
|
+
password = pwd;
|
|
48732
|
+
}
|
|
48733
|
+
const spinner = createSpinner("Creating wallet...");
|
|
48734
|
+
if (!isJsonMode())
|
|
48735
|
+
spinner.start();
|
|
48736
|
+
const walletId = generateWalletId();
|
|
48737
|
+
const vaultKey = `wallet_${walletId}`;
|
|
48738
|
+
const storage = new FileStorage();
|
|
48739
|
+
const kr = createKeyring(storage, vaultKey);
|
|
48740
|
+
await kr.initialize(mnemonic, password);
|
|
48741
|
+
await addWallet({
|
|
48742
|
+
id: walletId,
|
|
48743
|
+
label,
|
|
48744
|
+
color,
|
|
48745
|
+
vaultKey,
|
|
48746
|
+
createdAt: Date.now()
|
|
48747
|
+
});
|
|
48748
|
+
await setActiveWallet(walletId);
|
|
48749
|
+
if (!isJsonMode())
|
|
48750
|
+
spinner.succeed(" Wallet created successfully!");
|
|
48751
|
+
const accounts = kr.getAccounts();
|
|
48752
|
+
const firstAccount = accounts[0];
|
|
48753
|
+
if (firstAccount) {
|
|
48754
|
+
output({
|
|
48755
|
+
success: true,
|
|
48756
|
+
isNew,
|
|
48757
|
+
walletId,
|
|
48758
|
+
label,
|
|
48759
|
+
color,
|
|
48760
|
+
account: {
|
|
48761
|
+
index: firstAccount.index,
|
|
48762
|
+
label: firstAccount.label,
|
|
48763
|
+
evmAddress: firstAccount.evmAddress,
|
|
48764
|
+
solanaAddress: firstAccount.solanaAddress
|
|
48765
|
+
},
|
|
48766
|
+
...isNew ? { mnemonic } : {}
|
|
48767
|
+
}, () => {
|
|
48768
|
+
console.log();
|
|
48769
|
+
console.log(successBox(`Wallet: ${label}`, [
|
|
48770
|
+
kvLine("Wallet ID", walletId),
|
|
48771
|
+
kvLine("EVM Address", firstAccount.evmAddress),
|
|
48772
|
+
kvLine("Solana", firstAccount.solanaAddress),
|
|
48773
|
+
"",
|
|
48774
|
+
colors.muted("Vault encrypted and saved to ~/.zoa/")
|
|
48775
|
+
]));
|
|
48776
|
+
console.log();
|
|
48777
|
+
});
|
|
48778
|
+
}
|
|
48779
|
+
} catch (error) {
|
|
48780
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48781
|
+
outputError(msg);
|
|
48782
|
+
if (!isJsonMode())
|
|
48783
|
+
console.log(errorMsg(msg));
|
|
48784
|
+
process.exitCode = 1;
|
|
48785
|
+
}
|
|
48786
|
+
});
|
|
48787
|
+
wallet.command("switch [id-or-label]").description("Switch active wallet").action(async (idOrLabel) => {
|
|
48788
|
+
try {
|
|
48789
|
+
await migrateLegacyVaultIfNeeded();
|
|
48790
|
+
const wallets = await getWallets();
|
|
48791
|
+
if (wallets.length === 0) {
|
|
48792
|
+
throw new Error("No wallets configured. Run 'zoa wallet create' first.");
|
|
48793
|
+
}
|
|
48794
|
+
let targetId;
|
|
48795
|
+
if (idOrLabel) {
|
|
48796
|
+
const match = wallets.find((w) => w.id === idOrLabel || w.label.toLowerCase() === idOrLabel.toLowerCase() || w.id.includes(idOrLabel) || w.label.toLowerCase().includes(idOrLabel.toLowerCase()));
|
|
48797
|
+
if (!match)
|
|
48798
|
+
throw new Error(`No wallet found matching '${idOrLabel}'`);
|
|
48799
|
+
targetId = match.id;
|
|
48800
|
+
} else {
|
|
48801
|
+
const active = await getActiveWallet();
|
|
48802
|
+
const { selected } = await inquirer7.prompt([{
|
|
48803
|
+
type: "list",
|
|
48804
|
+
name: "selected",
|
|
48805
|
+
message: "Select wallet:",
|
|
48806
|
+
choices: wallets.map((w) => ({
|
|
48807
|
+
name: `${chalk3.hex(w.color)("\u25CF")} ${w.label}${w.id === active?.id ? chalk3.hex("#f59e0b")(" \u2605 active") : ""} ${colors.muted(`(${w.id})`)}`,
|
|
48808
|
+
value: w.id
|
|
48809
|
+
}))
|
|
48810
|
+
}]);
|
|
48811
|
+
targetId = selected;
|
|
48812
|
+
}
|
|
48813
|
+
await setActiveWallet(targetId);
|
|
48814
|
+
const switched = wallets.find((w) => w.id === targetId);
|
|
48815
|
+
output({ success: true, activeWalletId: targetId, label: switched.label }, () => {
|
|
48816
|
+
console.log(`
|
|
48817
|
+
${chalk3.hex(switched.color)("\u25CF")} Switched to ${chalk3.bold(switched.label)} ${colors.muted(`(${switched.id})`)}
|
|
48818
|
+
`);
|
|
48819
|
+
});
|
|
48820
|
+
} catch (error) {
|
|
48821
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48822
|
+
outputError(msg);
|
|
48823
|
+
if (!isJsonMode())
|
|
48824
|
+
console.log(errorMsg(msg));
|
|
48825
|
+
process.exitCode = 1;
|
|
48826
|
+
}
|
|
48827
|
+
});
|
|
48828
|
+
wallet.command("rename <id> <new-label>").description("Rename a wallet").action(async (id, newLabel) => {
|
|
48829
|
+
try {
|
|
48830
|
+
await migrateLegacyVaultIfNeeded();
|
|
48831
|
+
const wallets = await getWallets();
|
|
48832
|
+
const match = wallets.find((w) => w.id === id || w.label.toLowerCase() === id.toLowerCase());
|
|
48833
|
+
if (!match)
|
|
48834
|
+
throw new Error(`No wallet found matching '${id}'`);
|
|
48835
|
+
await updateWallet(match.id, { label: newLabel });
|
|
48836
|
+
output({ success: true, id: match.id, label: newLabel }, () => {
|
|
48837
|
+
console.log(`
|
|
48838
|
+
${chalk3.hex(match.color)("\u25CF")} Renamed to ${chalk3.bold(newLabel)} ${colors.muted(`(${match.id})`)}
|
|
48839
|
+
`);
|
|
48840
|
+
});
|
|
48841
|
+
} catch (error) {
|
|
48842
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48843
|
+
outputError(msg);
|
|
48844
|
+
if (!isJsonMode())
|
|
48845
|
+
console.log(errorMsg(msg));
|
|
48846
|
+
process.exitCode = 1;
|
|
48847
|
+
}
|
|
48848
|
+
});
|
|
48849
|
+
wallet.command("color <id> <hex>").description("Change wallet color").action(async (id, hex) => {
|
|
48850
|
+
try {
|
|
48851
|
+
if (!/^#[0-9a-fA-F]{6}$/.test(hex)) {
|
|
48852
|
+
throw new Error("Invalid hex color. Use format: #ff6b35");
|
|
48853
|
+
}
|
|
48854
|
+
await migrateLegacyVaultIfNeeded();
|
|
48855
|
+
const wallets = await getWallets();
|
|
48856
|
+
const match = wallets.find((w) => w.id === id || w.label.toLowerCase() === id.toLowerCase());
|
|
48857
|
+
if (!match)
|
|
48858
|
+
throw new Error(`No wallet found matching '${id}'`);
|
|
48859
|
+
await updateWallet(match.id, { color: hex });
|
|
48860
|
+
output({ success: true, id: match.id, color: hex }, () => {
|
|
48861
|
+
console.log(`
|
|
48862
|
+
${chalk3.hex(hex)("\u25CF")} Updated color for ${chalk3.bold(match.label)}
|
|
48863
|
+
`);
|
|
48864
|
+
});
|
|
48865
|
+
} catch (error) {
|
|
48866
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48867
|
+
outputError(msg);
|
|
48868
|
+
if (!isJsonMode())
|
|
48869
|
+
console.log(errorMsg(msg));
|
|
48870
|
+
process.exitCode = 1;
|
|
48871
|
+
}
|
|
48872
|
+
});
|
|
48873
|
+
wallet.command("remove <id>").description("Remove a wallet").option("--yes", "Skip confirmation").action(async (id, opts) => {
|
|
48874
|
+
try {
|
|
48875
|
+
await migrateLegacyVaultIfNeeded();
|
|
48876
|
+
const wallets = await getWallets();
|
|
48877
|
+
const match = wallets.find((w) => w.id === id || w.label.toLowerCase() === id.toLowerCase());
|
|
48878
|
+
if (!match)
|
|
48879
|
+
throw new Error(`No wallet found matching '${id}'`);
|
|
48880
|
+
if (!opts.yes && !isJsonMode()) {
|
|
48881
|
+
const { confirm } = await inquirer7.prompt([{
|
|
48882
|
+
type: "confirm",
|
|
48883
|
+
name: "confirm",
|
|
48884
|
+
message: `Remove wallet '${match.label}' (${match.id})? This will delete the vault file.`,
|
|
48885
|
+
default: false
|
|
48886
|
+
}]);
|
|
48887
|
+
if (!confirm) {
|
|
48888
|
+
console.log(colors.muted(" Cancelled."));
|
|
48889
|
+
return;
|
|
48890
|
+
}
|
|
48891
|
+
}
|
|
48892
|
+
const storage = new FileStorage();
|
|
48893
|
+
await storage.delete(match.vaultKey);
|
|
48894
|
+
await removeWallet(match.id);
|
|
48895
|
+
output({ success: true, removed: match.id }, () => {
|
|
48896
|
+
console.log(`
|
|
48897
|
+
${colors.error("\u2716")} Removed wallet ${chalk3.bold(match.label)} ${colors.muted(`(${match.id})`)}
|
|
48898
|
+
`);
|
|
48899
|
+
});
|
|
48900
|
+
} catch (error) {
|
|
48901
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48902
|
+
outputError(msg);
|
|
48903
|
+
if (!isJsonMode())
|
|
48904
|
+
console.log(errorMsg(msg));
|
|
48905
|
+
process.exitCode = 1;
|
|
48906
|
+
}
|
|
48907
|
+
});
|
|
48908
|
+
wallet.command("info").description("Show active wallet details").option("--password <password>", "Wallet password (non-interactive)").action(async (opts) => {
|
|
48909
|
+
try {
|
|
48910
|
+
await migrateLegacyVaultIfNeeded();
|
|
48911
|
+
const active = await getActiveWallet();
|
|
48912
|
+
if (!active) {
|
|
48913
|
+
throw new Error("No active wallet. Run 'zoa wallet create' first.");
|
|
48914
|
+
}
|
|
48915
|
+
let password;
|
|
48916
|
+
if (opts.password) {
|
|
48917
|
+
password = opts.password;
|
|
48918
|
+
} else {
|
|
48919
|
+
const { pwd } = await inquirer7.prompt([{
|
|
48920
|
+
type: "password",
|
|
48921
|
+
name: "pwd",
|
|
48922
|
+
message: "Enter your wallet password:",
|
|
48923
|
+
mask: "*"
|
|
48924
|
+
}]);
|
|
48925
|
+
password = pwd;
|
|
48926
|
+
}
|
|
48927
|
+
const spinner = createSpinner("Unlocking wallet...");
|
|
48928
|
+
if (!isJsonMode())
|
|
48929
|
+
spinner.start();
|
|
48930
|
+
const storage = new FileStorage();
|
|
48931
|
+
const kr = createKeyring(storage, active.vaultKey);
|
|
48932
|
+
await kr.unlock(password);
|
|
48933
|
+
const accounts = kr.getAccounts();
|
|
48934
|
+
if (!isJsonMode())
|
|
48935
|
+
spinner.stop();
|
|
48936
|
+
output({
|
|
48937
|
+
wallet: {
|
|
48938
|
+
id: active.id,
|
|
48939
|
+
label: active.label,
|
|
48940
|
+
color: active.color,
|
|
48941
|
+
createdAt: active.createdAt,
|
|
48942
|
+
lastUsedAt: active.lastUsedAt
|
|
48943
|
+
},
|
|
48944
|
+
accounts: accounts.map((a) => ({
|
|
48945
|
+
index: a.index,
|
|
48946
|
+
label: a.label,
|
|
48947
|
+
evmAddress: a.evmAddress,
|
|
48948
|
+
solanaAddress: a.solanaAddress
|
|
48949
|
+
}))
|
|
48950
|
+
}, () => {
|
|
48951
|
+
console.log(sectionHeader(`${chalk3.hex(active.color)("\u25CF")} ${active.label}`));
|
|
48952
|
+
console.log(kvLine("ID", active.id));
|
|
48953
|
+
console.log(kvLine("Color", chalk3.hex(active.color)(active.color)));
|
|
48954
|
+
console.log(kvLine("Created", new Date(active.createdAt).toLocaleString()));
|
|
48955
|
+
if (active.lastUsedAt) {
|
|
48956
|
+
console.log(kvLine("Last Used", new Date(active.lastUsedAt).toLocaleString()));
|
|
48957
|
+
}
|
|
48958
|
+
console.log();
|
|
48959
|
+
for (const account of accounts) {
|
|
48960
|
+
console.log(colors.brandBold(` Account ${account.index + 1}: ${account.label}`));
|
|
48961
|
+
console.log(kvLine("EVM", account.evmAddress));
|
|
48962
|
+
console.log(kvLine("Solana", account.solanaAddress));
|
|
48963
|
+
console.log();
|
|
48964
|
+
}
|
|
48965
|
+
});
|
|
48966
|
+
} catch (error) {
|
|
48967
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
48968
|
+
outputError(msg);
|
|
48969
|
+
if (!isJsonMode())
|
|
48970
|
+
console.log(errorMsg(msg));
|
|
48971
|
+
process.exitCode = 1;
|
|
48972
|
+
}
|
|
48973
|
+
});
|
|
48974
|
+
}
|
|
48975
|
+
|
|
48976
|
+
// dist/ui/banner.js
|
|
48977
|
+
import chalk4 from "chalk";
|
|
48485
48978
|
import figlet from "figlet";
|
|
48486
48979
|
import gradient2 from "gradient-string";
|
|
48487
48980
|
var zoaGradient2 = gradient2([
|
|
@@ -48492,37 +48985,45 @@ var zoaGradient2 = gradient2([
|
|
|
48492
48985
|
"#c77dff"
|
|
48493
48986
|
]);
|
|
48494
48987
|
var subtleGradient = gradient2(["#6b7280", "#9ca3af", "#6b7280"]);
|
|
48495
|
-
var VERSION = "0.2.
|
|
48496
|
-
function displayBanner() {
|
|
48497
|
-
const banner = figlet.textSync("ZOA", { font: "ANSI Shadow" });
|
|
48988
|
+
var VERSION = "0.2.5";
|
|
48989
|
+
async function displayBanner() {
|
|
48990
|
+
const banner = figlet.textSync("ZOA-wallet", { font: "ANSI Shadow" });
|
|
48498
48991
|
console.log();
|
|
48499
48992
|
console.log(zoaGradient2.multiline(banner));
|
|
48500
|
-
const tagline = " API-First Crypto Wallet for Developers & AI Agents";
|
|
48993
|
+
const tagline = " API-First Crypto Wallet for Power-traders, Developers, & AI Agents";
|
|
48501
48994
|
console.log(subtleGradient(tagline));
|
|
48502
48995
|
console.log();
|
|
48503
|
-
const versionBadge =
|
|
48504
|
-
const
|
|
48505
|
-
const npmBadge =
|
|
48506
|
-
|
|
48996
|
+
const versionBadge = chalk4.bgHex("#5e60ce").white.bold(` v${VERSION} `);
|
|
48997
|
+
const siteLink = chalk4.hex("#ff6b35")("wallet") + chalk4.hex("#00bbf9")(".zoa.fun");
|
|
48998
|
+
const npmBadge = chalk4.hex("#cb3837")("npm") + chalk4.hex("#6b7280")(" zoa-wallet");
|
|
48999
|
+
let walletIndicator = "";
|
|
49000
|
+
try {
|
|
49001
|
+
const active = await getActiveWallet();
|
|
49002
|
+
if (active) {
|
|
49003
|
+
walletIndicator = ` ${chalk4.hex("#3b3b3b")("\u2502")} ${chalk4.hex(active.color)("\u25CF")} ${chalk4.bold(active.label)}`;
|
|
49004
|
+
}
|
|
49005
|
+
} catch {
|
|
49006
|
+
}
|
|
49007
|
+
console.log(` ${versionBadge} ${chalk4.hex("#3b3b3b")("\u2502")} ${siteLink} ${chalk4.hex("#3b3b3b")("\u2502")} ${npmBadge}${walletIndicator}`);
|
|
48507
49008
|
console.log();
|
|
48508
|
-
console.log(
|
|
49009
|
+
console.log(chalk4.hex("#2d2d2d")(" " + "\u2500".repeat(58)));
|
|
48509
49010
|
console.log();
|
|
48510
49011
|
}
|
|
48511
49012
|
|
|
48512
49013
|
// dist/index.js
|
|
48513
49014
|
program.option("--json", "Output results as JSON (for scripts and AI agents)");
|
|
48514
|
-
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
49015
|
+
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
48515
49016
|
const rootOpts = program.opts();
|
|
48516
49017
|
if (rootOpts.json) {
|
|
48517
49018
|
setOutputMode("json");
|
|
48518
49019
|
} else {
|
|
48519
49020
|
const cmdName = actionCommand.name();
|
|
48520
49021
|
if (cmdName !== "help") {
|
|
48521
|
-
displayBanner();
|
|
49022
|
+
await displayBanner();
|
|
48522
49023
|
}
|
|
48523
49024
|
}
|
|
48524
49025
|
});
|
|
48525
|
-
program.name("zoa").description("ZOA Wallet \u2014 API-First Crypto Wallet for Developers & AI Agents").version("0.2.
|
|
49026
|
+
program.name("zoa").description("ZOA Wallet \u2014 API-First Crypto Wallet for Power-traders, Developers, & AI Agents").version("0.2.5");
|
|
48526
49027
|
registerInitCommand(program);
|
|
48527
49028
|
registerBalanceCommand(program);
|
|
48528
49029
|
registerSendCommand(program);
|
|
@@ -48533,9 +49034,12 @@ registerChainsCommand(program);
|
|
|
48533
49034
|
registerPricesCommand(program);
|
|
48534
49035
|
registerConfigCommand(program);
|
|
48535
49036
|
registerApiCommand(program);
|
|
49037
|
+
registerWalletCommand(program);
|
|
49038
|
+
if (!process.argv.slice(2).length) {
|
|
49039
|
+
await displayBanner();
|
|
49040
|
+
}
|
|
48536
49041
|
program.parse(process.argv);
|
|
48537
49042
|
if (!process.argv.slice(2).length) {
|
|
48538
|
-
displayBanner();
|
|
48539
49043
|
program.outputHelp();
|
|
48540
49044
|
console.log();
|
|
48541
49045
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zoa-wallet",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "API-First Crypto Wallet CLI for Developers & AI Agents. Manage multi-chain wallets from your terminal.",
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"description": "API-First Crypto Wallet CLI for Power-traders, Developers, & AI Agents. Manage multi-chain wallets from your terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|