hodl-wallet 1.0.6 → 1.1.8
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/README.md +16 -17
- package/index.mjs +197 -133
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
+
## 🚀 Install and try!
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g hodl-wallet
|
|
9
|
+
hodl
|
|
10
|
+
```
|
|
11
|
+
|
|
5
12
|
## 🚀 Why HODL Wallet?
|
|
6
13
|
|
|
7
|
-
Let's face it, Trust Wallet's sluggishness and annoying ads are so last season. HODL Wallet is here to
|
|
14
|
+
Let's face it, Trust Wallet's sluggishness and annoying ads are so last season. HODL Wallet is here to agilize your crypto experience.
|
|
8
15
|
|
|
9
16
|
- 🏎️ Lightning-fast operations
|
|
10
17
|
- 🧊 Cool, minimalist CLI interface
|
|
@@ -12,18 +19,6 @@ Let's face it, Trust Wallet's sluggishness and annoying ads are so last season.
|
|
|
12
19
|
- 🔒 Create wallets offline (because paranoia is just good sense in crypto)
|
|
13
20
|
- 🔍 Fully transparent, open-source code
|
|
14
21
|
|
|
15
|
-
## 🛠️ Installation
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm install -g hodl-wallet
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## 🚀 Quick Start
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
hodl
|
|
25
|
-
```
|
|
26
|
-
|
|
27
22
|
That's it! Follow the prompts and you're in crypto heaven.
|
|
28
23
|
|
|
29
24
|
## 🎮 Features
|
|
@@ -40,17 +35,21 @@ Smoother than sliding into your crush's DMs.
|
|
|
40
35
|
|
|
41
36
|
Because constantly checking your balance is totally healthy.
|
|
42
37
|
|
|
38
|
+
### 📘 Address Book
|
|
39
|
+
|
|
40
|
+
Keep your favorite addresses handy. No more copy-pasting!
|
|
41
|
+
|
|
43
42
|
## 🔒 Security
|
|
44
43
|
|
|
45
|
-
### Private Key Storage
|
|
44
|
+
### 🔑 Private Key Storage
|
|
46
45
|
|
|
47
|
-
Your private key is securely stored in a JSON file, encrypted with your
|
|
46
|
+
Your private key is securely stored in a JSON file, encrypted with a password of your choice. The encryption adds an extra layer of security, making it significantly harder for unauthorized parties to access your private key even if they gain access to the JSON file.
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
### 🔬 Transparency
|
|
50
49
|
|
|
51
50
|
We're as transparent as your ex's excuses. Our code is open-source, and we encourage you to dive in, explore, and contribute. Trust isn't given; it's earned and verified.
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
### 🔍 Security Audit
|
|
54
53
|
|
|
55
54
|
We encourage users to perform their own security audits. One easy way to do this is to copy the entire codebase into ChatGPT or another AI assistant and ask if the code appears secure or if there are any malicious intentions. This is a good practice for any open-source project you're considering using.
|
|
56
55
|
|
package/index.mjs
CHANGED
|
@@ -29,7 +29,7 @@ class Wallet {
|
|
|
29
29
|
try {
|
|
30
30
|
const networkPlugins = await this.loadNetworkPlugins();
|
|
31
31
|
if (networkPlugins.length === 0) {
|
|
32
|
-
|
|
32
|
+
Wallet.displayError('No valid network plugins found.');
|
|
33
33
|
process.exit(1);
|
|
34
34
|
}
|
|
35
35
|
await this.selectNetwork(networkPlugins);
|
|
@@ -37,11 +37,12 @@ class Wallet {
|
|
|
37
37
|
await this.loadAccount();
|
|
38
38
|
|
|
39
39
|
if (!this.account) {
|
|
40
|
-
|
|
40
|
+
Wallet.displayError('Failed to initialize account.');
|
|
41
|
+
process.exit(1);
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
} catch (error) {
|
|
44
|
-
|
|
45
|
+
Wallet.displayError('Initialization failed', error);
|
|
45
46
|
process.exit(1);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
@@ -85,56 +86,88 @@ class Wallet {
|
|
|
85
86
|
async loadAccount(forceReload = false) {
|
|
86
87
|
let account = this.db.secureGet('account');
|
|
87
88
|
|
|
89
|
+
const choices = ['Create New Account', 'Import Mnemonic (12 words)', 'Import private-key'];
|
|
90
|
+
|
|
91
|
+
if (forceReload) {
|
|
92
|
+
choices.push('Export Account');
|
|
93
|
+
choices.push('Go back');
|
|
94
|
+
}
|
|
95
|
+
|
|
88
96
|
if (!account || forceReload) {
|
|
89
97
|
const { accountAction } = await inquirer.prompt({
|
|
90
98
|
type: 'list',
|
|
91
99
|
name: 'accountAction',
|
|
92
100
|
message: 'Select an account option:',
|
|
93
|
-
choices
|
|
101
|
+
choices,
|
|
94
102
|
});
|
|
95
103
|
|
|
96
|
-
if (accountAction === '
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
if (accountAction === 'Go back') {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (account && accountAction !== 'Export Account') {
|
|
109
|
+
const { confirmOverwrite } = await inquirer.prompt({
|
|
110
|
+
type: 'confirm',
|
|
111
|
+
name: 'confirmOverwrite',
|
|
112
|
+
message: 'This action will overwrite the existing account. Are you sure you want to continue?',
|
|
113
|
+
default: false,
|
|
102
114
|
});
|
|
103
|
-
account = this.web3.eth.accounts.privateKeyToAccount(privateKey);
|
|
104
|
-
await this.db.secureSet('account', { privateKey: account.privateKey });
|
|
105
115
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
} else {
|
|
116
|
+
if (!confirmOverwrite) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (accountAction === 'Create New Account') {
|
|
113
122
|
const mnemonic = bip39.generateMnemonic();
|
|
114
123
|
const seed = await bip39.mnemonicToSeed(mnemonic);
|
|
115
124
|
const root = hdkey.fromMasterSeed(seed);
|
|
116
125
|
const addrNode = root.derive("m/44'/60'/0'/0/0");
|
|
117
126
|
const privateKey = addrNode.privateKey.toString('hex');
|
|
118
|
-
account = this.web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
|
|
119
|
-
this.
|
|
127
|
+
this.account = this.web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
|
|
128
|
+
this.account.mnemonic = mnemonic;
|
|
129
|
+
await this.db.secureSet('account', this.account);
|
|
130
|
+
this.displayAccountDetails();
|
|
131
|
+
}
|
|
120
132
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
133
|
+
if (accountAction === 'Import private-key') {
|
|
134
|
+
const { privateKey } = await inquirer.prompt({
|
|
135
|
+
type: 'password',
|
|
136
|
+
name: 'privateKey',
|
|
137
|
+
message: 'Private-key:',
|
|
138
|
+
mask: '*',
|
|
125
139
|
});
|
|
126
140
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
141
|
+
if (!privateKey.trim()) {
|
|
142
|
+
Wallet.displayError('Private-key is empty.');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
this.account = this.web3.eth.accounts.privateKeyToAccount(privateKey);
|
|
148
|
+
await this.db.secureSet('account', this.account);
|
|
149
|
+
this.displayAccountAddress();
|
|
150
|
+
} catch (error) {
|
|
151
|
+
Wallet.displayError('Invalid private-key.');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
133
155
|
|
|
134
|
-
|
|
156
|
+
if (accountAction === 'Import Mnemonic (12 words)') {
|
|
157
|
+
account = await this.importFrom12Words();
|
|
158
|
+
if (!account) {
|
|
159
|
+
Wallet.displayError('Invalid mnemonic.');
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.account = account;
|
|
163
|
+
this.displayAccountAddress();
|
|
135
164
|
}
|
|
136
|
-
|
|
137
|
-
|
|
165
|
+
|
|
166
|
+
if (accountAction === 'Export Account') {
|
|
167
|
+
await this.displayAccountDetails();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
138
171
|
}
|
|
139
172
|
|
|
140
173
|
this.account = account;
|
|
@@ -149,7 +182,6 @@ class Wallet {
|
|
|
149
182
|
});
|
|
150
183
|
|
|
151
184
|
if (!bip39.validateMnemonic(mnemonic)) {
|
|
152
|
-
console.error('Invalid mnemonic phrase');
|
|
153
185
|
return null;
|
|
154
186
|
}
|
|
155
187
|
|
|
@@ -159,14 +191,14 @@ class Wallet {
|
|
|
159
191
|
const privateKey = addrNode.privateKey.toString('hex');
|
|
160
192
|
const account = this.web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
|
|
161
193
|
|
|
162
|
-
|
|
163
|
-
|
|
194
|
+
account.mnemonic = mnemonic;
|
|
195
|
+
await this.db.secureSet('account', account);
|
|
164
196
|
return account;
|
|
165
197
|
}
|
|
166
198
|
|
|
167
199
|
async showBalance() {
|
|
168
200
|
if (!this.account) {
|
|
169
|
-
|
|
201
|
+
Wallet.displayError('Account not initialized.', 'Ï Please try restarting the application.');
|
|
170
202
|
return;
|
|
171
203
|
}
|
|
172
204
|
|
|
@@ -179,9 +211,8 @@ class Wallet {
|
|
|
179
211
|
colWidths: [21, 22]
|
|
180
212
|
});
|
|
181
213
|
|
|
182
|
-
// Add address as the top row
|
|
183
214
|
// table.push([{ colSpan: 2, content: this.account.address }]);
|
|
184
|
-
table.push([this.selectedNetwork.nativeToken, parseFloat(balance).toFixed(
|
|
215
|
+
table.push([this.selectedNetwork.nativeToken, parseFloat(balance).toFixed(3)]);
|
|
185
216
|
|
|
186
217
|
// Check if USDT is available on the selected network
|
|
187
218
|
if (this.selectedNetwork.tokens['USDT']) {
|
|
@@ -212,7 +243,7 @@ class Wallet {
|
|
|
212
243
|
(BigInt(usdtBalance) * 100n) / (10n ** BigInt(decimals))
|
|
213
244
|
) / 100;
|
|
214
245
|
|
|
215
|
-
table.push(['USDT', formattedUsdtBalance.toFixed(
|
|
246
|
+
table.push(['USDT', formattedUsdtBalance.toFixed(3)]);
|
|
216
247
|
}
|
|
217
248
|
|
|
218
249
|
console.log(table.toString());
|
|
@@ -258,7 +289,6 @@ class Wallet {
|
|
|
258
289
|
});
|
|
259
290
|
|
|
260
291
|
if (amount === '') {
|
|
261
|
-
console.log('Transaction cancelled.');
|
|
262
292
|
return;
|
|
263
293
|
}
|
|
264
294
|
|
|
@@ -271,7 +301,7 @@ class Wallet {
|
|
|
271
301
|
}
|
|
272
302
|
|
|
273
303
|
const receipt = await this.web3.eth.sendSignedTransaction(signedTx.rawTransaction);
|
|
274
|
-
|
|
304
|
+
this.displayTransactionResult(address, token, amount, receipt);
|
|
275
305
|
|
|
276
306
|
// Add transaction to history
|
|
277
307
|
this.addToTransactions(address, token, amount, receipt);
|
|
@@ -281,10 +311,40 @@ class Wallet {
|
|
|
281
311
|
}
|
|
282
312
|
|
|
283
313
|
} catch (error) {
|
|
284
|
-
|
|
314
|
+
this.displayTransactionError(error);
|
|
285
315
|
}
|
|
286
316
|
}
|
|
287
317
|
|
|
318
|
+
displayTransactionError(error) {
|
|
319
|
+
const data = error.reason ? error.reason.replace(/(\w+):/g, "\n$1:").trim() : null;
|
|
320
|
+
Wallet.displayError(error.message, data);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
static displayError(message, data) {
|
|
324
|
+
const table = new Table({
|
|
325
|
+
head: [message],
|
|
326
|
+
style: { head: ['red'] },
|
|
327
|
+
wordWrap: true,
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
if (data) {
|
|
331
|
+
table.push([data]);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
console.log(table.toString());
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
formatDate(date) {
|
|
338
|
+
return new Date(date).toLocaleString('en-GB', {
|
|
339
|
+
year: 'numeric',
|
|
340
|
+
month: '2-digit',
|
|
341
|
+
day: '2-digit',
|
|
342
|
+
hour: '2-digit',
|
|
343
|
+
minute: '2-digit',
|
|
344
|
+
hour12: false
|
|
345
|
+
}).replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$2-$1').replace(",", "");
|
|
346
|
+
}
|
|
347
|
+
|
|
288
348
|
addToTransactions(recipient, token, amount, receipt) {
|
|
289
349
|
const transaction = {
|
|
290
350
|
timestamp: new Date().toISOString(),
|
|
@@ -309,15 +369,8 @@ class Wallet {
|
|
|
309
369
|
}
|
|
310
370
|
|
|
311
371
|
history.forEach(tx => {
|
|
312
|
-
const date =
|
|
313
|
-
|
|
314
|
-
month: '2-digit',
|
|
315
|
-
day: '2-digit',
|
|
316
|
-
hour: '2-digit',
|
|
317
|
-
minute: '2-digit',
|
|
318
|
-
hour12: false
|
|
319
|
-
}).replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$2-$1').replace(",", "");
|
|
320
|
-
table.push([date, tx.recipient, tx.token, tx.amount]);
|
|
372
|
+
const date = this.formatDate(tx.timestamp);
|
|
373
|
+
table.push([date, tx.recipient, tx.token, parseFloat(tx.amount).toFixed(3)]);
|
|
321
374
|
table.push([{ colSpan: 4, content: this.selectedNetwork.explorer + tx.hash }]);
|
|
322
375
|
});
|
|
323
376
|
|
|
@@ -389,14 +442,7 @@ class Wallet {
|
|
|
389
442
|
|
|
390
443
|
return this.web3.eth.accounts.signTransaction(tx, this.account.privateKey);
|
|
391
444
|
} catch (error) {
|
|
392
|
-
|
|
393
|
-
const table = new Table({
|
|
394
|
-
head: [{ colSpan: 2, content: 'Error: Invalid Address' }],
|
|
395
|
-
style: { head: ['red'] }
|
|
396
|
-
});
|
|
397
|
-
table.push(['Address', recipient]);
|
|
398
|
-
console.log(table.toString());
|
|
399
|
-
}
|
|
445
|
+
this.displayTransactionError(error);
|
|
400
446
|
}
|
|
401
447
|
}
|
|
402
448
|
|
|
@@ -416,13 +462,12 @@ class Wallet {
|
|
|
416
462
|
if (balance < amountWei + gasCost) {
|
|
417
463
|
const maxAmount = this.web3.utils.fromWei((balance - gasCost).toString(), 'ether');
|
|
418
464
|
const table = new Table({
|
|
419
|
-
head: [{ colSpan: 2, content: 'Insufficient balance for this transaction' }],
|
|
465
|
+
head: [{ colSpan: 2, content: 'Insufficient balance for this transaction.' }],
|
|
420
466
|
style: { head: ['red'] },
|
|
421
467
|
wordWrap: true
|
|
422
468
|
});
|
|
423
469
|
table.push(['Maximum Amount', `${maxAmount} ${this.selectedNetwork.nativeToken}`]);
|
|
424
470
|
console.log(table.toString());
|
|
425
|
-
return;
|
|
426
471
|
}
|
|
427
472
|
|
|
428
473
|
const tx = {
|
|
@@ -436,43 +481,56 @@ class Wallet {
|
|
|
436
481
|
return this.web3.eth.accounts.signTransaction(tx, this.account.privateKey);
|
|
437
482
|
}
|
|
438
483
|
|
|
439
|
-
|
|
440
|
-
if (receipt) {
|
|
441
|
-
const gasUsed = receipt.gasUsed;
|
|
442
|
-
const gasPrice = await this.web3.eth.getGasPrice();
|
|
443
|
-
const transactionFee = this.web3.utils.fromWei((BigInt(gasUsed) * BigInt(gasPrice)).toString(), 'ether');
|
|
484
|
+
displayTransactionResult(address, token, amount, hash) {
|
|
444
485
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
table.push(
|
|
450
|
-
['Explorer', this.selectedNetwork.explorer + receipt.transactionHash],
|
|
451
|
-
['Fee', `${transactionFee} ${this.selectedNetwork.nativeToken}`],
|
|
452
|
-
);
|
|
486
|
+
const table = new Table({
|
|
487
|
+
head: ['Date', 'Recipient', 'Token', 'Amount'],
|
|
488
|
+
style: { head: ['green'] },
|
|
489
|
+
});
|
|
453
490
|
|
|
454
|
-
|
|
455
|
-
} else if (error) {
|
|
456
|
-
const table = new Table({
|
|
457
|
-
head: [error.message],
|
|
458
|
-
style: { head: ['red'] },
|
|
459
|
-
wordWrap: true,
|
|
460
|
-
});
|
|
491
|
+
const date = this.formatDate(new Date());
|
|
461
492
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
493
|
+
table.push([
|
|
494
|
+
date,
|
|
495
|
+
address,
|
|
496
|
+
token,
|
|
497
|
+
amount.toFixed(3)
|
|
498
|
+
]);
|
|
499
|
+
table.push([{ colSpan: 4, content: this.selectedNetwork.explorer + hash }]);
|
|
465
500
|
|
|
466
|
-
|
|
467
|
-
}
|
|
501
|
+
console.log('\n' + table.toString());
|
|
468
502
|
}
|
|
469
503
|
|
|
470
504
|
clearAccountData() {
|
|
471
505
|
if (this.account) {
|
|
472
506
|
this.account.privateKey = '0'.repeat(64);
|
|
507
|
+
this.account.mnemonic = 'x'.repeat(256);
|
|
473
508
|
this.account = null;
|
|
474
509
|
}
|
|
475
510
|
}
|
|
511
|
+
|
|
512
|
+
displayAccountDetails() {
|
|
513
|
+
|
|
514
|
+
const table = new Table({
|
|
515
|
+
head: [{ colSpan: 2, content: 'Account Details' }],
|
|
516
|
+
style: { head: ['green'] },
|
|
517
|
+
wordWrap: true
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
table.push(
|
|
521
|
+
['Address', this.account.address],
|
|
522
|
+
['Private-key', this.account.privateKey]
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
if (this.account.mnemonic) {
|
|
526
|
+
table.push(['Mnemonic Phrase', this.account.mnemonic]);
|
|
527
|
+
table.push(['WARNING', "Please keep your private-key and mnemonic phrase secure. Never share it."]);
|
|
528
|
+
} else {
|
|
529
|
+
table.push(['WARNING', "Please keep your private-key secure. Never share it."]);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
console.log('\n' + table.toString());
|
|
533
|
+
}
|
|
476
534
|
}
|
|
477
535
|
|
|
478
536
|
class UIManager {
|
|
@@ -546,66 +604,72 @@ class UIManager {
|
|
|
546
604
|
}
|
|
547
605
|
}
|
|
548
606
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
607
|
+
UIManager.displayWelcome();
|
|
608
|
+
const encryptionKey = await UIManager.getEncryptionKey();
|
|
609
|
+
const wallet = new Wallet(encryptionKey);
|
|
610
|
+
|
|
611
|
+
// Check if an account exists
|
|
612
|
+
const accountExists = wallet.db.secureGet('account');
|
|
613
|
+
if (accountExists === null) {
|
|
614
|
+
Wallet.displayError('Wrong password.');
|
|
615
|
+
process.exit(1);
|
|
616
|
+
}
|
|
553
617
|
|
|
554
|
-
|
|
555
|
-
const
|
|
556
|
-
if (
|
|
557
|
-
|
|
618
|
+
if (!accountExists) {
|
|
619
|
+
const confirmedKey = await UIManager.confirmEncryptionKey(encryptionKey);
|
|
620
|
+
if (confirmedKey !== encryptionKey) {
|
|
621
|
+
Wallet.displayError('Passwords do not match. Please try again.');
|
|
558
622
|
process.exit(1);
|
|
559
623
|
}
|
|
624
|
+
}
|
|
560
625
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
626
|
+
try {
|
|
627
|
+
await wallet.initialize();
|
|
628
|
+
if (accountExists) wallet.displayAccountAddress();
|
|
629
|
+
} catch (error) {
|
|
630
|
+
Wallet.displayError('Failed to initialize wallet.', error);
|
|
631
|
+
process.exit(1);
|
|
632
|
+
}
|
|
568
633
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
process.exit(1);
|
|
575
|
-
}
|
|
634
|
+
// Register the displayExitPhrase method and account clearing to be called on process exit
|
|
635
|
+
process.on('exit', () => {
|
|
636
|
+
wallet.clearAccountData();
|
|
637
|
+
UIManager.displayExitPhrase();
|
|
638
|
+
});
|
|
576
639
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
640
|
+
while (true) {
|
|
641
|
+
const { action } = await inquirer.prompt({
|
|
642
|
+
type: 'list',
|
|
643
|
+
name: 'action',
|
|
644
|
+
message: 'What would you like to do?',
|
|
645
|
+
choices: [
|
|
646
|
+
{ name: 'Transfer Funds', value: 'transfer' },
|
|
647
|
+
{ name: 'Show Balance', value: 'balance' },
|
|
648
|
+
{ name: 'Show Sents', value: 'history' },
|
|
649
|
+
{ name: 'Account', value: 'account' },
|
|
650
|
+
{ name: 'Exit', value: 'exit' }
|
|
651
|
+
],
|
|
581
652
|
});
|
|
582
653
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
type: 'list',
|
|
586
|
-
name: 'action',
|
|
587
|
-
message: 'What would you like to do?',
|
|
588
|
-
choices: ['Transfer funds', 'Show balance', 'Show transactions', 'Change account', 'Exit'],
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
if (action === 'Transfer funds') {
|
|
592
|
-
await wallet.transferFunds();
|
|
593
|
-
} else if (action === 'Show balance') {
|
|
654
|
+
switch (action) {
|
|
655
|
+
case 'balance':
|
|
594
656
|
await wallet.showBalance();
|
|
595
|
-
|
|
657
|
+
break;
|
|
658
|
+
case 'transfer':
|
|
659
|
+
await wallet.transferFunds();
|
|
660
|
+
break;
|
|
661
|
+
case 'history':
|
|
596
662
|
await wallet.showTransactions();
|
|
597
|
-
|
|
663
|
+
break;
|
|
664
|
+
case 'account':
|
|
598
665
|
await wallet.loadAccount(true);
|
|
599
|
-
|
|
666
|
+
break;
|
|
667
|
+
case 'exit':
|
|
600
668
|
process.exit();
|
|
601
|
-
}
|
|
602
669
|
}
|
|
603
670
|
}
|
|
604
671
|
|
|
605
|
-
|
|
606
|
-
console.error('An unexpected error occurred:', error);
|
|
607
|
-
process.exit(1);
|
|
608
|
-
});
|
|
672
|
+
|
|
609
673
|
|
|
610
674
|
process.on('SIGINT', () => {
|
|
611
675
|
console.log('\n');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hodl-wallet",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "🧊 HODL Wallet - Blazing-fast, transparent, and ad-free crypto wallet!",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"bin": {
|
|
@@ -17,13 +17,16 @@
|
|
|
17
17
|
"ethereum",
|
|
18
18
|
"bsc20",
|
|
19
19
|
"bep20",
|
|
20
|
-
"evm",
|
|
21
20
|
"bnb",
|
|
22
21
|
"eth",
|
|
23
22
|
"binance",
|
|
24
23
|
"trust",
|
|
25
24
|
"blockchain",
|
|
26
25
|
"bitcoin",
|
|
26
|
+
"usdt",
|
|
27
|
+
"stable",
|
|
28
|
+
"coin",
|
|
29
|
+
"evm",
|
|
27
30
|
"clasen"
|
|
28
31
|
],
|
|
29
32
|
"author": "Hodl Wallet",
|