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