tetsuo-blockchain-wallet 1.2.3 → 1.2.4
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/cli.js +62 -53
- package/package.json +1 -1
- package/src/cli.ts +62 -53
- package/src/cli.ts.bak +569 -0
package/dist/cli.js
CHANGED
|
@@ -94,16 +94,16 @@ function saveWallets(store) {
|
|
|
94
94
|
async function createWallet(rl) {
|
|
95
95
|
const name = await question(rl, 'Wallet name: ');
|
|
96
96
|
if (!name.trim()) {
|
|
97
|
-
console.log(chalk_1.default.red('
|
|
97
|
+
console.log(chalk_1.default.red('[ERROR] Wallet name cannot be empty'));
|
|
98
98
|
return;
|
|
99
99
|
}
|
|
100
100
|
try {
|
|
101
|
-
console.log(chalk_1.default.yellow('
|
|
101
|
+
console.log(chalk_1.default.yellow('[...] Generating wallet...'));
|
|
102
102
|
const wallet = await (0, index_1.generateWallet)();
|
|
103
103
|
const store = loadWallets();
|
|
104
104
|
const exists = store.wallets.some(w => w.name === name);
|
|
105
105
|
if (exists) {
|
|
106
|
-
console.log(chalk_1.default.red('
|
|
106
|
+
console.log(chalk_1.default.red('[ERROR] Wallet with this name already exists'));
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
109
|
store.wallets.push({
|
|
@@ -118,21 +118,21 @@ async function createWallet(rl) {
|
|
|
118
118
|
store.selectedWallet = name;
|
|
119
119
|
}
|
|
120
120
|
saveWallets(store);
|
|
121
|
-
console.log(chalk_1.default.green('
|
|
122
|
-
console.log(chalk_1.default.cyan('\n
|
|
121
|
+
console.log(chalk_1.default.green('[OK] Wallet created successfully!'));
|
|
122
|
+
console.log(chalk_1.default.cyan('\n[NOTE] Mnemonic (BACKUP THIS):'));
|
|
123
123
|
console.log(chalk_1.default.yellow(wallet.mnemonic));
|
|
124
|
-
console.log(chalk_1.default.cyan('\n
|
|
124
|
+
console.log(chalk_1.default.cyan('\n[ADDR] Address:'));
|
|
125
125
|
console.log(chalk_1.default.yellow(wallet.address));
|
|
126
126
|
}
|
|
127
127
|
catch (error) {
|
|
128
|
-
console.log(chalk_1.default.red(
|
|
128
|
+
console.log(chalk_1.default.red(`[ERROR] Error: ${error.message}`));
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
async function importWallet(rl) {
|
|
132
132
|
const name = await question(rl, 'Wallet name: ');
|
|
133
133
|
const type = await question(rl, 'Import from (mnemonic/privatekey): ');
|
|
134
134
|
if (!name.trim()) {
|
|
135
|
-
console.log(chalk_1.default.red('
|
|
135
|
+
console.log(chalk_1.default.red('[ERROR] Wallet name cannot be empty'));
|
|
136
136
|
return;
|
|
137
137
|
}
|
|
138
138
|
try {
|
|
@@ -140,25 +140,25 @@ async function importWallet(rl) {
|
|
|
140
140
|
if (type.toLowerCase() === 'mnemonic') {
|
|
141
141
|
const mnemonic = await question(rl, 'Enter mnemonic (12 words): ');
|
|
142
142
|
if (!(0, index_1.isValidMnemonic)(mnemonic)) {
|
|
143
|
-
console.log(chalk_1.default.red('
|
|
143
|
+
console.log(chalk_1.default.red('[ERROR] Invalid mnemonic'));
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
|
-
console.log(chalk_1.default.yellow('
|
|
146
|
+
console.log(chalk_1.default.yellow('[...] Importing wallet...'));
|
|
147
147
|
wallet = await (0, index_1.importFromMnemonic)(mnemonic);
|
|
148
148
|
}
|
|
149
149
|
else if (type.toLowerCase() === 'privatekey') {
|
|
150
150
|
const privateKey = await question(rl, 'Enter private key (hex): ');
|
|
151
|
-
console.log(chalk_1.default.yellow('
|
|
151
|
+
console.log(chalk_1.default.yellow('[...] Importing wallet...'));
|
|
152
152
|
wallet = (0, index_1.importFromPrivateKey)(privateKey);
|
|
153
153
|
}
|
|
154
154
|
else {
|
|
155
|
-
console.log(chalk_1.default.red('
|
|
155
|
+
console.log(chalk_1.default.red('[ERROR] Invalid import type'));
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
158
|
const store = loadWallets();
|
|
159
159
|
const exists = store.wallets.some(w => w.name === name);
|
|
160
160
|
if (exists) {
|
|
161
|
-
console.log(chalk_1.default.red('
|
|
161
|
+
console.log(chalk_1.default.red('[ERROR] Wallet with this name already exists'));
|
|
162
162
|
return;
|
|
163
163
|
}
|
|
164
164
|
store.wallets.push({
|
|
@@ -173,12 +173,12 @@ async function importWallet(rl) {
|
|
|
173
173
|
store.selectedWallet = name;
|
|
174
174
|
}
|
|
175
175
|
saveWallets(store);
|
|
176
|
-
console.log(chalk_1.default.green('
|
|
177
|
-
console.log(chalk_1.default.cyan('
|
|
176
|
+
console.log(chalk_1.default.green('[OK] Wallet imported successfully!'));
|
|
177
|
+
console.log(chalk_1.default.cyan('[ADDR] Address:'));
|
|
178
178
|
console.log(chalk_1.default.yellow(wallet.address));
|
|
179
179
|
}
|
|
180
180
|
catch (error) {
|
|
181
|
-
console.log(chalk_1.default.red(
|
|
181
|
+
console.log(chalk_1.default.red(`[ERROR] Error: ${error.message}`));
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
async function listWallets() {
|
|
@@ -187,10 +187,10 @@ async function listWallets() {
|
|
|
187
187
|
console.log(chalk_1.default.yellow('No wallets found. Create one first!'));
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
|
-
console.log(chalk_1.default.cyan('\n
|
|
190
|
+
console.log(chalk_1.default.cyan('\n[INFO] Your Wallets:'));
|
|
191
191
|
console.log('─'.repeat(80));
|
|
192
192
|
store.wallets.forEach((wallet, index) => {
|
|
193
|
-
const selected = store.selectedWallet === wallet.name ? '
|
|
193
|
+
const selected = store.selectedWallet === wallet.name ? ' [SELECTED]' : '';
|
|
194
194
|
const created = new Date(wallet.createdAt).toLocaleDateString();
|
|
195
195
|
console.log(`${index + 1}. ${chalk_1.default.bold(wallet.name)}${selected}`);
|
|
196
196
|
console.log(` Address: ${chalk_1.default.green(wallet.address)}`);
|
|
@@ -211,24 +211,24 @@ async function selectWallet(rl) {
|
|
|
211
211
|
if (index >= 0 && index < store.wallets.length) {
|
|
212
212
|
store.selectedWallet = store.wallets[index].name;
|
|
213
213
|
saveWallets(store);
|
|
214
|
-
console.log(chalk_1.default.green(
|
|
214
|
+
console.log(chalk_1.default.green(`[OK] Selected: ${store.wallets[index].name}`));
|
|
215
215
|
}
|
|
216
216
|
else {
|
|
217
|
-
console.log(chalk_1.default.red('
|
|
217
|
+
console.log(chalk_1.default.red('[ERROR] Invalid selection'));
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
async function getBalance() {
|
|
221
221
|
const store = loadWallets();
|
|
222
222
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
223
223
|
if (!wallet) {
|
|
224
|
-
console.log(chalk_1.default.red('
|
|
224
|
+
console.log(chalk_1.default.red('[ERROR] No wallet selected'));
|
|
225
225
|
return;
|
|
226
226
|
}
|
|
227
227
|
try {
|
|
228
|
-
console.log(chalk_1.default.yellow('
|
|
228
|
+
console.log(chalk_1.default.yellow('[...] Fetching balance...'));
|
|
229
229
|
const rpc = (0, index_1.createRPCClient)(RPC_URL);
|
|
230
230
|
const balance = await rpc.getBalance(wallet.address);
|
|
231
|
-
console.log(chalk_1.default.cyan('\n
|
|
231
|
+
console.log(chalk_1.default.cyan('\n[BALANCE] Balance Information:'));
|
|
232
232
|
console.log('─'.repeat(50));
|
|
233
233
|
console.log(chalk_1.default.yellow(' Wallet: ') + chalk_1.default.white(wallet.name));
|
|
234
234
|
console.log(chalk_1.default.yellow(' Address: ') + chalk_1.default.white(wallet.address));
|
|
@@ -236,27 +236,27 @@ async function getBalance() {
|
|
|
236
236
|
console.log('─'.repeat(50));
|
|
237
237
|
}
|
|
238
238
|
catch (error) {
|
|
239
|
-
console.log(chalk_1.default.red(
|
|
239
|
+
console.log(chalk_1.default.red(`[ERROR] Error: ${error.message}`));
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
async function getTransactions() {
|
|
243
243
|
const store = loadWallets();
|
|
244
244
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
245
245
|
if (!wallet) {
|
|
246
|
-
console.log(chalk_1.default.red('
|
|
246
|
+
console.log(chalk_1.default.red('[ERROR] No wallet selected'));
|
|
247
247
|
return;
|
|
248
248
|
}
|
|
249
249
|
try {
|
|
250
|
-
console.log(chalk_1.default.yellow('
|
|
250
|
+
console.log(chalk_1.default.yellow('[...] Fetching transactions...'));
|
|
251
251
|
const rpc = (0, index_1.createRPCClient)(RPC_URL);
|
|
252
252
|
const transactions = await rpc.getTransactionHistory(wallet.address);
|
|
253
253
|
if (transactions.length === 0) {
|
|
254
|
-
console.log(chalk_1.default.cyan('\n
|
|
254
|
+
console.log(chalk_1.default.cyan('\n[HISTORY] Transaction History:'));
|
|
255
255
|
console.log(chalk_1.default.yellow(' Wallet: ') + wallet.name);
|
|
256
256
|
console.log(chalk_1.default.yellow('No transactions found'));
|
|
257
257
|
return;
|
|
258
258
|
}
|
|
259
|
-
console.log(chalk_1.default.cyan('\n
|
|
259
|
+
console.log(chalk_1.default.cyan('\n[HISTORY] Transaction History:'));
|
|
260
260
|
console.log(chalk_1.default.yellow(' Wallet: ') + wallet.name);
|
|
261
261
|
console.log('─'.repeat(80));
|
|
262
262
|
transactions.forEach((tx) => {
|
|
@@ -268,17 +268,17 @@ async function getTransactions() {
|
|
|
268
268
|
console.log('─'.repeat(80));
|
|
269
269
|
}
|
|
270
270
|
catch (error) {
|
|
271
|
-
console.log(chalk_1.default.red(
|
|
271
|
+
console.log(chalk_1.default.red(`[ERROR] Error: ${error.message}`));
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
async function receiveTokens() {
|
|
275
275
|
const store = loadWallets();
|
|
276
276
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
277
277
|
if (!wallet) {
|
|
278
|
-
console.log(chalk_1.default.red('
|
|
278
|
+
console.log(chalk_1.default.red('[ERROR] No wallet selected'));
|
|
279
279
|
return;
|
|
280
280
|
}
|
|
281
|
-
console.log(chalk_1.default.cyan('\n
|
|
281
|
+
console.log(chalk_1.default.cyan('\n[ADDR] Receive Address:'));
|
|
282
282
|
console.log(chalk_1.default.green(wallet.address));
|
|
283
283
|
console.log(chalk_1.default.yellow('\nShare this address to receive TETSUO'));
|
|
284
284
|
}
|
|
@@ -286,34 +286,34 @@ async function sendTokens(rl) {
|
|
|
286
286
|
const store = loadWallets();
|
|
287
287
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
288
288
|
if (!wallet) {
|
|
289
|
-
console.log(chalk_1.default.red('
|
|
289
|
+
console.log(chalk_1.default.red('[ERROR] No wallet selected'));
|
|
290
290
|
return;
|
|
291
291
|
}
|
|
292
292
|
const toAddress = await question(rl, 'Recipient address: ');
|
|
293
293
|
if (!(0, index_1.isValidAddress)(toAddress)) {
|
|
294
|
-
console.log(chalk_1.default.red('
|
|
294
|
+
console.log(chalk_1.default.red('[ERROR] Invalid recipient address'));
|
|
295
295
|
return;
|
|
296
296
|
}
|
|
297
297
|
const amount = await question(rl, 'Amount (TETSUO): ');
|
|
298
298
|
const numAmount = parseFloat(amount);
|
|
299
299
|
if (isNaN(numAmount) || numAmount <= 0) {
|
|
300
|
-
console.log(chalk_1.default.red('
|
|
300
|
+
console.log(chalk_1.default.red('[ERROR] Invalid amount'));
|
|
301
301
|
return;
|
|
302
302
|
}
|
|
303
303
|
try {
|
|
304
|
-
console.log(chalk_1.default.yellow('\n
|
|
304
|
+
console.log(chalk_1.default.yellow('\n[...] Preparing transaction...'));
|
|
305
305
|
const rpc = (0, index_1.createRPCClient)(RPC_URL);
|
|
306
306
|
// Get UTXOs
|
|
307
307
|
console.log(chalk_1.default.yellow(' Fetching UTXOs...'));
|
|
308
308
|
const utxos = await rpc.getUTXOs(wallet.address);
|
|
309
309
|
if (utxos.length === 0) {
|
|
310
|
-
console.log(chalk_1.default.red('
|
|
310
|
+
console.log(chalk_1.default.red('[ERROR] No UTXOs available to spend'));
|
|
311
311
|
return;
|
|
312
312
|
}
|
|
313
313
|
// Build transaction
|
|
314
314
|
const txData = (0, index_1.buildTransaction)(wallet.address, toAddress, numAmount, utxos, wallet.address);
|
|
315
315
|
// Show transaction details
|
|
316
|
-
console.log(chalk_1.default.cyan('\n
|
|
316
|
+
console.log(chalk_1.default.cyan('\n[HISTORY] Transaction Details:'));
|
|
317
317
|
console.log('─'.repeat(60));
|
|
318
318
|
console.log(chalk_1.default.yellow(' From: ') + wallet.address);
|
|
319
319
|
console.log(chalk_1.default.yellow(' To: ') + toAddress);
|
|
@@ -324,11 +324,11 @@ async function sendTokens(rl) {
|
|
|
324
324
|
// Ask for confirmation
|
|
325
325
|
const confirm = await question(rl, chalk_1.default.cyan('\nConfirm transaction? (yes/no): '));
|
|
326
326
|
if (confirm.toLowerCase() !== 'yes' && confirm.toLowerCase() !== 'y') {
|
|
327
|
-
console.log(chalk_1.default.yellow('
|
|
327
|
+
console.log(chalk_1.default.yellow('[CANCEL] Transaction cancelled'));
|
|
328
328
|
return;
|
|
329
329
|
}
|
|
330
330
|
// Create and sign transaction
|
|
331
|
-
console.log(chalk_1.default.yellow('\n
|
|
331
|
+
console.log(chalk_1.default.yellow('\n[...] Signing transaction...'));
|
|
332
332
|
const txHex = (0, index_1.createTransactionHex)(txData.inputs, txData.outputs);
|
|
333
333
|
const signedTxHex = (0, index_1.signTransaction)(txHex, wallet.privateKey, txData.inputs, utxos);
|
|
334
334
|
// Broadcast or use server fallback
|
|
@@ -343,8 +343,8 @@ async function sendTokens(rl) {
|
|
|
343
343
|
// Fallback: Use server to sign and broadcast
|
|
344
344
|
txid = await rpc.signAndBroadcast(txHex, wallet.privateKey);
|
|
345
345
|
}
|
|
346
|
-
console.log(chalk_1.default.green('\n
|
|
347
|
-
console.log(chalk_1.default.cyan('\n
|
|
346
|
+
console.log(chalk_1.default.green('\n[OK] Transaction sent successfully!'));
|
|
347
|
+
console.log(chalk_1.default.cyan('\n[INFO] Transaction Info:'));
|
|
348
348
|
console.log('─'.repeat(60));
|
|
349
349
|
console.log(chalk_1.default.yellow(' TXID: ') + chalk_1.default.green(txid));
|
|
350
350
|
console.log(chalk_1.default.yellow(' Amount: ') + chalk_1.default.green(numAmount.toFixed(8) + ' TETSUO'));
|
|
@@ -353,17 +353,17 @@ async function sendTokens(rl) {
|
|
|
353
353
|
console.log(chalk_1.default.cyan('\nCheck transaction status at: https://tetsuoarena.com/tx/' + txid));
|
|
354
354
|
}
|
|
355
355
|
catch (error) {
|
|
356
|
-
console.log(chalk_1.default.red('\n
|
|
356
|
+
console.log(chalk_1.default.red('\n[ERROR] Error: ' + error.message));
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
359
|
async function walletData() {
|
|
360
360
|
const store = loadWallets();
|
|
361
361
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
362
362
|
if (!wallet) {
|
|
363
|
-
console.log(chalk_1.default.red('
|
|
363
|
+
console.log(chalk_1.default.red('[ERROR] No wallet selected'));
|
|
364
364
|
return;
|
|
365
365
|
}
|
|
366
|
-
console.log(chalk_1.default.cyan('\n
|
|
366
|
+
console.log(chalk_1.default.cyan('\n[INFO] Wallet Data:'));
|
|
367
367
|
console.log('─'.repeat(80));
|
|
368
368
|
console.log(`Name: ${chalk_1.default.yellow(wallet.name)}`);
|
|
369
369
|
console.log(`Address: ${chalk_1.default.green(wallet.address)}`);
|
|
@@ -379,7 +379,7 @@ async function deleteWallet(rl) {
|
|
|
379
379
|
const store = loadWallets();
|
|
380
380
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
381
381
|
if (!wallet) {
|
|
382
|
-
console.log(chalk_1.default.red('
|
|
382
|
+
console.log(chalk_1.default.red('[ERROR] No wallet selected'));
|
|
383
383
|
return;
|
|
384
384
|
}
|
|
385
385
|
const confirm = await question(rl, `Delete ${wallet.name}? (yes/no): `);
|
|
@@ -392,17 +392,17 @@ async function deleteWallet(rl) {
|
|
|
392
392
|
store.selectedWallet = store.wallets[0]?.name;
|
|
393
393
|
}
|
|
394
394
|
saveWallets(store);
|
|
395
|
-
console.log(chalk_1.default.green('
|
|
395
|
+
console.log(chalk_1.default.green('[OK] Wallet deleted'));
|
|
396
396
|
}
|
|
397
397
|
async function configureRPC(rl) {
|
|
398
398
|
const config = loadConfig();
|
|
399
|
-
console.log(chalk_1.default.cyan('\n
|
|
399
|
+
console.log(chalk_1.default.cyan('\n[CONFIG] RPC Configuration:'));
|
|
400
400
|
console.log(`Current RPC URL: ${chalk_1.default.green(RPC_URL)}`);
|
|
401
401
|
const newUrl = await question(rl, 'Enter new RPC URL (or press Enter to keep current): ');
|
|
402
402
|
if (newUrl.trim()) {
|
|
403
403
|
RPC_URL = newUrl.trim();
|
|
404
404
|
saveConfig({ rpcUrl: RPC_URL });
|
|
405
|
-
console.log(chalk_1.default.green('
|
|
405
|
+
console.log(chalk_1.default.green('[OK] RPC URL updated!'));
|
|
406
406
|
console.log(`New URL: ${chalk_1.default.green(RPC_URL)}`);
|
|
407
407
|
}
|
|
408
408
|
else {
|
|
@@ -423,9 +423,18 @@ async function main() {
|
|
|
423
423
|
output: process.stdout
|
|
424
424
|
});
|
|
425
425
|
console.clear();
|
|
426
|
-
console.log(chalk_1.default.
|
|
427
|
-
|
|
428
|
-
|
|
426
|
+
console.log(chalk_1.default.cyan.bold(`
|
|
427
|
+
TTTTTTTTT EEEEEEEE TTTTTTTT SSSSSSS UUUU UUUU OOOOOOO
|
|
428
|
+
TTT EEEE TTT SSSS UUUU UUUU OOOOOOO
|
|
429
|
+
TTT EEEEE TTT SSSSS UUUU UUUU OOOOO
|
|
430
|
+
TTT EEEE TTT SSS UUUU UUUU OOOOOOO
|
|
431
|
+
TTT EEEEEEEE TTT SSSSSSS UUUUUUUU OOOOOOO
|
|
432
|
+
|
|
433
|
+
WALLET : SECURE BLOCKCHAIN TRANSACTIONS
|
|
434
|
+
`));
|
|
435
|
+
console.log(chalk_1.default.cyan.bold('═══════════════════════════════'));
|
|
436
|
+
console.log(chalk_1.default.cyan.bold(' TETSUO BLOCKCHAIN WALLET'));
|
|
437
|
+
console.log(chalk_1.default.cyan.bold('═══════════════════════════════\n'));
|
|
429
438
|
let running = true;
|
|
430
439
|
while (running) {
|
|
431
440
|
const store = loadWallets();
|
|
@@ -483,10 +492,10 @@ async function main() {
|
|
|
483
492
|
break;
|
|
484
493
|
case '/exit':
|
|
485
494
|
running = false;
|
|
486
|
-
console.log(chalk_1.default.green('\nGoodbye!
|
|
495
|
+
console.log(chalk_1.default.green('\nGoodbye! [BYE]\n'));
|
|
487
496
|
break;
|
|
488
497
|
default:
|
|
489
|
-
console.log(chalk_1.default.red('
|
|
498
|
+
console.log(chalk_1.default.red('[ERROR] Unknown command'));
|
|
490
499
|
}
|
|
491
500
|
}
|
|
492
501
|
rl.close();
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -92,18 +92,18 @@ function saveWallets(store: WalletStore) {
|
|
|
92
92
|
async function createWallet(rl: readline.Interface): Promise<void> {
|
|
93
93
|
const name = await question(rl, 'Wallet name: ');
|
|
94
94
|
if (!name.trim()) {
|
|
95
|
-
console.log(chalk.red('
|
|
95
|
+
console.log(chalk.red('[ERROR] Wallet name cannot be empty'));
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
try {
|
|
100
|
-
console.log(chalk.yellow('
|
|
100
|
+
console.log(chalk.yellow('[...] Generating wallet...'));
|
|
101
101
|
const wallet = await generateWallet();
|
|
102
102
|
|
|
103
103
|
const store = loadWallets();
|
|
104
104
|
const exists = store.wallets.some(w => w.name === name);
|
|
105
105
|
if (exists) {
|
|
106
|
-
console.log(chalk.red('
|
|
106
|
+
console.log(chalk.red('[ERROR] Wallet with this name already exists'));
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -122,13 +122,13 @@ async function createWallet(rl: readline.Interface): Promise<void> {
|
|
|
122
122
|
|
|
123
123
|
saveWallets(store);
|
|
124
124
|
|
|
125
|
-
console.log(chalk.green('
|
|
126
|
-
console.log(chalk.cyan('\n
|
|
125
|
+
console.log(chalk.green('[OK] Wallet created successfully!'));
|
|
126
|
+
console.log(chalk.cyan('\n[NOTE] Mnemonic (BACKUP THIS):'));
|
|
127
127
|
console.log(chalk.yellow(wallet.mnemonic));
|
|
128
|
-
console.log(chalk.cyan('\n
|
|
128
|
+
console.log(chalk.cyan('\n[ADDR] Address:'));
|
|
129
129
|
console.log(chalk.yellow(wallet.address));
|
|
130
130
|
} catch (error: any) {
|
|
131
|
-
console.log(chalk.red(
|
|
131
|
+
console.log(chalk.red(`[ERROR] Error: ${error.message}`));
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
|
|
@@ -137,7 +137,7 @@ async function importWallet(rl: readline.Interface): Promise<void> {
|
|
|
137
137
|
const type = await question(rl, 'Import from (mnemonic/privatekey): ');
|
|
138
138
|
|
|
139
139
|
if (!name.trim()) {
|
|
140
|
-
console.log(chalk.red('
|
|
140
|
+
console.log(chalk.red('[ERROR] Wallet name cannot be empty'));
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -147,24 +147,24 @@ async function importWallet(rl: readline.Interface): Promise<void> {
|
|
|
147
147
|
if (type.toLowerCase() === 'mnemonic') {
|
|
148
148
|
const mnemonic = await question(rl, 'Enter mnemonic (12 words): ');
|
|
149
149
|
if (!isValidMnemonic(mnemonic)) {
|
|
150
|
-
console.log(chalk.red('
|
|
150
|
+
console.log(chalk.red('[ERROR] Invalid mnemonic'));
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
|
-
console.log(chalk.yellow('
|
|
153
|
+
console.log(chalk.yellow('[...] Importing wallet...'));
|
|
154
154
|
wallet = await importFromMnemonic(mnemonic);
|
|
155
155
|
} else if (type.toLowerCase() === 'privatekey') {
|
|
156
156
|
const privateKey = await question(rl, 'Enter private key (hex): ');
|
|
157
|
-
console.log(chalk.yellow('
|
|
157
|
+
console.log(chalk.yellow('[...] Importing wallet...'));
|
|
158
158
|
wallet = importFromPrivateKey(privateKey);
|
|
159
159
|
} else {
|
|
160
|
-
console.log(chalk.red('
|
|
160
|
+
console.log(chalk.red('[ERROR] Invalid import type'));
|
|
161
161
|
return;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
const store = loadWallets();
|
|
165
165
|
const exists = store.wallets.some(w => w.name === name);
|
|
166
166
|
if (exists) {
|
|
167
|
-
console.log(chalk.red('
|
|
167
|
+
console.log(chalk.red('[ERROR] Wallet with this name already exists'));
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
170
|
|
|
@@ -182,11 +182,11 @@ async function importWallet(rl: readline.Interface): Promise<void> {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
saveWallets(store);
|
|
185
|
-
console.log(chalk.green('
|
|
186
|
-
console.log(chalk.cyan('
|
|
185
|
+
console.log(chalk.green('[OK] Wallet imported successfully!'));
|
|
186
|
+
console.log(chalk.cyan('[ADDR] Address:'));
|
|
187
187
|
console.log(chalk.yellow(wallet.address));
|
|
188
188
|
} catch (error: any) {
|
|
189
|
-
console.log(chalk.red(
|
|
189
|
+
console.log(chalk.red(`[ERROR] Error: ${error.message}`));
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
|
|
@@ -198,11 +198,11 @@ async function listWallets(): Promise<void> {
|
|
|
198
198
|
return;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
console.log(chalk.cyan('\n
|
|
201
|
+
console.log(chalk.cyan('\n[INFO] Your Wallets:'));
|
|
202
202
|
console.log('─'.repeat(80));
|
|
203
203
|
|
|
204
204
|
store.wallets.forEach((wallet, index) => {
|
|
205
|
-
const selected = store.selectedWallet === wallet.name ? '
|
|
205
|
+
const selected = store.selectedWallet === wallet.name ? ' [SELECTED]' : '';
|
|
206
206
|
const created = new Date(wallet.createdAt).toLocaleDateString();
|
|
207
207
|
console.log(
|
|
208
208
|
`${index + 1}. ${chalk.bold(wallet.name)}${selected}`
|
|
@@ -230,9 +230,9 @@ async function selectWallet(rl: readline.Interface): Promise<void> {
|
|
|
230
230
|
if (index >= 0 && index < store.wallets.length) {
|
|
231
231
|
store.selectedWallet = store.wallets[index].name;
|
|
232
232
|
saveWallets(store);
|
|
233
|
-
console.log(chalk.green(
|
|
233
|
+
console.log(chalk.green(`[OK] Selected: ${store.wallets[index].name}`));
|
|
234
234
|
} else {
|
|
235
|
-
console.log(chalk.red('
|
|
235
|
+
console.log(chalk.red('[ERROR] Invalid selection'));
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
|
|
@@ -241,23 +241,23 @@ async function getBalance(): Promise<void> {
|
|
|
241
241
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
242
242
|
|
|
243
243
|
if (!wallet) {
|
|
244
|
-
console.log(chalk.red('
|
|
244
|
+
console.log(chalk.red('[ERROR] No wallet selected'));
|
|
245
245
|
return;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
try {
|
|
249
|
-
console.log(chalk.yellow('
|
|
249
|
+
console.log(chalk.yellow('[...] Fetching balance...'));
|
|
250
250
|
const rpc = createRPCClient(RPC_URL);
|
|
251
251
|
const balance = await rpc.getBalance(wallet.address);
|
|
252
252
|
|
|
253
|
-
console.log(chalk.cyan('\n
|
|
253
|
+
console.log(chalk.cyan('\n[BALANCE] Balance Information:'));
|
|
254
254
|
console.log('─'.repeat(50));
|
|
255
255
|
console.log(chalk.yellow(' Wallet: ') + chalk.white(wallet.name));
|
|
256
256
|
console.log(chalk.yellow(' Address: ') + chalk.white(wallet.address));
|
|
257
257
|
console.log(chalk.yellow(' Balance: ') + chalk.green(`${balance.toFixed(8)} TETSUO`));
|
|
258
258
|
console.log('─'.repeat(50));
|
|
259
259
|
} catch (error: any) {
|
|
260
|
-
console.log(chalk.red(
|
|
260
|
+
console.log(chalk.red(`[ERROR] Error: ${error.message}`));
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
@@ -266,23 +266,23 @@ async function getTransactions(): Promise<void> {
|
|
|
266
266
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
267
267
|
|
|
268
268
|
if (!wallet) {
|
|
269
|
-
console.log(chalk.red('
|
|
269
|
+
console.log(chalk.red('[ERROR] No wallet selected'));
|
|
270
270
|
return;
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
try {
|
|
274
|
-
console.log(chalk.yellow('
|
|
274
|
+
console.log(chalk.yellow('[...] Fetching transactions...'));
|
|
275
275
|
const rpc = createRPCClient(RPC_URL);
|
|
276
276
|
const transactions = await rpc.getTransactionHistory(wallet.address);
|
|
277
277
|
|
|
278
278
|
if (transactions.length === 0) {
|
|
279
|
-
console.log(chalk.cyan('\n
|
|
279
|
+
console.log(chalk.cyan('\n[HISTORY] Transaction History:'));
|
|
280
280
|
console.log(chalk.yellow(' Wallet: ') + wallet.name);
|
|
281
281
|
console.log(chalk.yellow('No transactions found'));
|
|
282
282
|
return;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
console.log(chalk.cyan('\n
|
|
285
|
+
console.log(chalk.cyan('\n[HISTORY] Transaction History:'));
|
|
286
286
|
console.log(chalk.yellow(' Wallet: ') + wallet.name);
|
|
287
287
|
console.log('─'.repeat(80));
|
|
288
288
|
|
|
@@ -294,7 +294,7 @@ async function getTransactions(): Promise<void> {
|
|
|
294
294
|
});
|
|
295
295
|
console.log('─'.repeat(80));
|
|
296
296
|
} catch (error: any) {
|
|
297
|
-
console.log(chalk.red(
|
|
297
|
+
console.log(chalk.red(`[ERROR] Error: ${error.message}`));
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
|
|
@@ -303,11 +303,11 @@ async function receiveTokens(): Promise<void> {
|
|
|
303
303
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
304
304
|
|
|
305
305
|
if (!wallet) {
|
|
306
|
-
console.log(chalk.red('
|
|
306
|
+
console.log(chalk.red('[ERROR] No wallet selected'));
|
|
307
307
|
return;
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
-
console.log(chalk.cyan('\n
|
|
310
|
+
console.log(chalk.cyan('\n[ADDR] Receive Address:'));
|
|
311
311
|
console.log(chalk.green(wallet.address));
|
|
312
312
|
console.log(chalk.yellow('\nShare this address to receive TETSUO'));
|
|
313
313
|
}
|
|
@@ -317,25 +317,25 @@ async function sendTokens(rl: readline.Interface): Promise<void> {
|
|
|
317
317
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
318
318
|
|
|
319
319
|
if (!wallet) {
|
|
320
|
-
console.log(chalk.red('
|
|
320
|
+
console.log(chalk.red('[ERROR] No wallet selected'));
|
|
321
321
|
return;
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
const toAddress = await question(rl, 'Recipient address: ');
|
|
325
325
|
if (!isValidAddress(toAddress)) {
|
|
326
|
-
console.log(chalk.red('
|
|
326
|
+
console.log(chalk.red('[ERROR] Invalid recipient address'));
|
|
327
327
|
return;
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
const amount = await question(rl, 'Amount (TETSUO): ');
|
|
331
331
|
const numAmount = parseFloat(amount);
|
|
332
332
|
if (isNaN(numAmount) || numAmount <= 0) {
|
|
333
|
-
console.log(chalk.red('
|
|
333
|
+
console.log(chalk.red('[ERROR] Invalid amount'));
|
|
334
334
|
return;
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
try {
|
|
338
|
-
console.log(chalk.yellow('\n
|
|
338
|
+
console.log(chalk.yellow('\n[...] Preparing transaction...'));
|
|
339
339
|
const rpc = createRPCClient(RPC_URL);
|
|
340
340
|
|
|
341
341
|
// Get UTXOs
|
|
@@ -343,7 +343,7 @@ async function sendTokens(rl: readline.Interface): Promise<void> {
|
|
|
343
343
|
const utxos = await rpc.getUTXOs(wallet.address);
|
|
344
344
|
|
|
345
345
|
if (utxos.length === 0) {
|
|
346
|
-
console.log(chalk.red('
|
|
346
|
+
console.log(chalk.red('[ERROR] No UTXOs available to spend'));
|
|
347
347
|
return;
|
|
348
348
|
}
|
|
349
349
|
|
|
@@ -351,7 +351,7 @@ async function sendTokens(rl: readline.Interface): Promise<void> {
|
|
|
351
351
|
const txData = buildTransaction(wallet.address, toAddress, numAmount, utxos, wallet.address);
|
|
352
352
|
|
|
353
353
|
// Show transaction details
|
|
354
|
-
console.log(chalk.cyan('\n
|
|
354
|
+
console.log(chalk.cyan('\n[HISTORY] Transaction Details:'));
|
|
355
355
|
console.log('─'.repeat(60));
|
|
356
356
|
console.log(chalk.yellow(' From: ') + wallet.address);
|
|
357
357
|
console.log(chalk.yellow(' To: ') + toAddress);
|
|
@@ -363,12 +363,12 @@ async function sendTokens(rl: readline.Interface): Promise<void> {
|
|
|
363
363
|
// Ask for confirmation
|
|
364
364
|
const confirm = await question(rl, chalk.cyan('\nConfirm transaction? (yes/no): '));
|
|
365
365
|
if (confirm.toLowerCase() !== 'yes' && confirm.toLowerCase() !== 'y') {
|
|
366
|
-
console.log(chalk.yellow('
|
|
366
|
+
console.log(chalk.yellow('[CANCEL] Transaction cancelled'));
|
|
367
367
|
return;
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
// Create and sign transaction
|
|
371
|
-
console.log(chalk.yellow('\n
|
|
371
|
+
console.log(chalk.yellow('\n[...] Signing transaction...'));
|
|
372
372
|
const txHex = createTransactionHex(txData.inputs, txData.outputs);
|
|
373
373
|
const signedTxHex = signTransaction(txHex, wallet.privateKey, txData.inputs, utxos);
|
|
374
374
|
|
|
@@ -384,8 +384,8 @@ async function sendTokens(rl: readline.Interface): Promise<void> {
|
|
|
384
384
|
txid = await rpc.signAndBroadcast(txHex, wallet.privateKey);
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
-
console.log(chalk.green('\n
|
|
388
|
-
console.log(chalk.cyan('\n
|
|
387
|
+
console.log(chalk.green('\n[OK] Transaction sent successfully!'));
|
|
388
|
+
console.log(chalk.cyan('\n[INFO] Transaction Info:'));
|
|
389
389
|
console.log('─'.repeat(60));
|
|
390
390
|
console.log(chalk.yellow(' TXID: ') + chalk.green(txid));
|
|
391
391
|
console.log(chalk.yellow(' Amount: ') + chalk.green(numAmount.toFixed(8) + ' TETSUO'));
|
|
@@ -393,7 +393,7 @@ async function sendTokens(rl: readline.Interface): Promise<void> {
|
|
|
393
393
|
console.log('─'.repeat(60));
|
|
394
394
|
console.log(chalk.cyan('\nCheck transaction status at: https://tetsuoarena.com/tx/' + txid));
|
|
395
395
|
} catch (error: any) {
|
|
396
|
-
console.log(chalk.red('\n
|
|
396
|
+
console.log(chalk.red('\n[ERROR] Error: ' + error.message));
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
|
|
@@ -402,11 +402,11 @@ async function walletData(): Promise<void> {
|
|
|
402
402
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
403
403
|
|
|
404
404
|
if (!wallet) {
|
|
405
|
-
console.log(chalk.red('
|
|
405
|
+
console.log(chalk.red('[ERROR] No wallet selected'));
|
|
406
406
|
return;
|
|
407
407
|
}
|
|
408
408
|
|
|
409
|
-
console.log(chalk.cyan('\n
|
|
409
|
+
console.log(chalk.cyan('\n[INFO] Wallet Data:'));
|
|
410
410
|
console.log('─'.repeat(80));
|
|
411
411
|
console.log(`Name: ${chalk.yellow(wallet.name)}`);
|
|
412
412
|
console.log(`Address: ${chalk.green(wallet.address)}`);
|
|
@@ -424,7 +424,7 @@ async function deleteWallet(rl: readline.Interface): Promise<void> {
|
|
|
424
424
|
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
425
425
|
|
|
426
426
|
if (!wallet) {
|
|
427
|
-
console.log(chalk.red('
|
|
427
|
+
console.log(chalk.red('[ERROR] No wallet selected'));
|
|
428
428
|
return;
|
|
429
429
|
}
|
|
430
430
|
|
|
@@ -440,13 +440,13 @@ async function deleteWallet(rl: readline.Interface): Promise<void> {
|
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
saveWallets(store);
|
|
443
|
-
console.log(chalk.green('
|
|
443
|
+
console.log(chalk.green('[OK] Wallet deleted'));
|
|
444
444
|
}
|
|
445
445
|
|
|
446
446
|
async function configureRPC(rl: readline.Interface): Promise<void> {
|
|
447
447
|
const config = loadConfig();
|
|
448
448
|
|
|
449
|
-
console.log(chalk.cyan('\n
|
|
449
|
+
console.log(chalk.cyan('\n[CONFIG] RPC Configuration:'));
|
|
450
450
|
console.log(`Current RPC URL: ${chalk.green(RPC_URL)}`);
|
|
451
451
|
|
|
452
452
|
const newUrl = await question(rl, 'Enter new RPC URL (or press Enter to keep current): ');
|
|
@@ -454,7 +454,7 @@ async function configureRPC(rl: readline.Interface): Promise<void> {
|
|
|
454
454
|
if (newUrl.trim()) {
|
|
455
455
|
RPC_URL = newUrl.trim();
|
|
456
456
|
saveConfig({ rpcUrl: RPC_URL });
|
|
457
|
-
console.log(chalk.green('
|
|
457
|
+
console.log(chalk.green('[OK] RPC URL updated!'));
|
|
458
458
|
console.log(`New URL: ${chalk.green(RPC_URL)}`);
|
|
459
459
|
} else {
|
|
460
460
|
console.log(chalk.yellow('No changes made'));
|
|
@@ -478,9 +478,18 @@ async function main() {
|
|
|
478
478
|
});
|
|
479
479
|
|
|
480
480
|
console.clear();
|
|
481
|
-
console.log(chalk.
|
|
482
|
-
|
|
483
|
-
|
|
481
|
+
console.log(chalk.cyan.bold(`
|
|
482
|
+
TTTTTTTTT EEEEEEEE TTTTTTTT SSSSSSS UUUU UUUU OOOOOOO
|
|
483
|
+
TTT EEEE TTT SSSS UUUU UUUU OOOOOOO
|
|
484
|
+
TTT EEEEE TTT SSSSS UUUU UUUU OOOOO
|
|
485
|
+
TTT EEEE TTT SSS UUUU UUUU OOOOOOO
|
|
486
|
+
TTT EEEEEEEE TTT SSSSSSS UUUUUUUU OOOOOOO
|
|
487
|
+
|
|
488
|
+
WALLET : SECURE BLOCKCHAIN TRANSACTIONS
|
|
489
|
+
`));
|
|
490
|
+
console.log(chalk.cyan.bold('═══════════════════════════════'));
|
|
491
|
+
console.log(chalk.cyan.bold(' TETSUO BLOCKCHAIN WALLET'));
|
|
492
|
+
console.log(chalk.cyan.bold('═══════════════════════════════\n'));
|
|
484
493
|
|
|
485
494
|
let running = true;
|
|
486
495
|
|
|
@@ -543,10 +552,10 @@ async function main() {
|
|
|
543
552
|
break;
|
|
544
553
|
case '/exit':
|
|
545
554
|
running = false;
|
|
546
|
-
console.log(chalk.green('\nGoodbye!
|
|
555
|
+
console.log(chalk.green('\nGoodbye! [BYE]\n'));
|
|
547
556
|
break;
|
|
548
557
|
default:
|
|
549
|
-
console.log(chalk.red('
|
|
558
|
+
console.log(chalk.red('[ERROR] Unknown command'));
|
|
550
559
|
}
|
|
551
560
|
}
|
|
552
561
|
|
package/src/cli.ts.bak
ADDED
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as readline from 'readline';
|
|
6
|
+
import {
|
|
7
|
+
generateWallet,
|
|
8
|
+
importFromMnemonic,
|
|
9
|
+
importFromPrivateKey,
|
|
10
|
+
isValidAddress,
|
|
11
|
+
createRPCClient,
|
|
12
|
+
isValidMnemonic,
|
|
13
|
+
buildTransaction,
|
|
14
|
+
createTransactionHex,
|
|
15
|
+
signTransaction
|
|
16
|
+
} from './index';
|
|
17
|
+
import chalk from 'chalk';
|
|
18
|
+
|
|
19
|
+
// Types
|
|
20
|
+
interface StoredWallet {
|
|
21
|
+
name: string;
|
|
22
|
+
address: string;
|
|
23
|
+
privateKey: string;
|
|
24
|
+
publicKey: string;
|
|
25
|
+
mnemonic?: string;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface WalletStore {
|
|
30
|
+
wallets: StoredWallet[];
|
|
31
|
+
selectedWallet?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface Config {
|
|
35
|
+
rpcUrl: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Constants
|
|
39
|
+
const WALLET_DIR = path.join(process.env.HOME || '~', '.tetsuo');
|
|
40
|
+
const WALLET_FILE = path.join(WALLET_DIR, 'wallets.json');
|
|
41
|
+
const CONFIG_FILE = path.join(WALLET_DIR, 'config.json');
|
|
42
|
+
let RPC_URL = process.env.TETSUO_RPC_URL || 'https://tetsuoarena.com';
|
|
43
|
+
|
|
44
|
+
// Load config from storage
|
|
45
|
+
function loadConfig(): Config {
|
|
46
|
+
try {
|
|
47
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
48
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
49
|
+
return JSON.parse(data);
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
// Fall back to defaults
|
|
53
|
+
}
|
|
54
|
+
return { rpcUrl: RPC_URL };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Save config to storage
|
|
58
|
+
function saveConfig(config: Config) {
|
|
59
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Ensure wallet directory exists
|
|
63
|
+
function initWalletStorage() {
|
|
64
|
+
if (!fs.existsSync(WALLET_DIR)) {
|
|
65
|
+
fs.mkdirSync(WALLET_DIR, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
if (!fs.existsSync(WALLET_FILE)) {
|
|
68
|
+
fs.writeFileSync(WALLET_FILE, JSON.stringify({ wallets: [] }, null, 2));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Load config and update RPC_URL
|
|
72
|
+
const config = loadConfig();
|
|
73
|
+
RPC_URL = config.rpcUrl;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Load wallets from storage
|
|
77
|
+
function loadWallets(): WalletStore {
|
|
78
|
+
try {
|
|
79
|
+
const data = fs.readFileSync(WALLET_FILE, 'utf-8');
|
|
80
|
+
return JSON.parse(data);
|
|
81
|
+
} catch {
|
|
82
|
+
return { wallets: [] };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Save wallets to storage
|
|
87
|
+
function saveWallets(store: WalletStore) {
|
|
88
|
+
fs.writeFileSync(WALLET_FILE, JSON.stringify(store, null, 2));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// CLI Commands
|
|
92
|
+
async function createWallet(rl: readline.Interface): Promise<void> {
|
|
93
|
+
const name = await question(rl, 'Wallet name: ');
|
|
94
|
+
if (!name.trim()) {
|
|
95
|
+
console.log(chalk.red('✗ Wallet name cannot be empty'));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
console.log(chalk.yellow('⏳ Generating wallet...'));
|
|
101
|
+
const wallet = await generateWallet();
|
|
102
|
+
|
|
103
|
+
const store = loadWallets();
|
|
104
|
+
const exists = store.wallets.some(w => w.name === name);
|
|
105
|
+
if (exists) {
|
|
106
|
+
console.log(chalk.red('✗ Wallet with this name already exists'));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
store.wallets.push({
|
|
111
|
+
name,
|
|
112
|
+
address: wallet.address,
|
|
113
|
+
privateKey: wallet.privateKey,
|
|
114
|
+
publicKey: wallet.publicKey,
|
|
115
|
+
mnemonic: wallet.mnemonic,
|
|
116
|
+
createdAt: new Date().toISOString()
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (!store.selectedWallet) {
|
|
120
|
+
store.selectedWallet = name;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
saveWallets(store);
|
|
124
|
+
|
|
125
|
+
console.log(chalk.green('✓ Wallet created successfully!'));
|
|
126
|
+
console.log(chalk.cyan('\n📝 Mnemonic (BACKUP THIS):'));
|
|
127
|
+
console.log(chalk.yellow(wallet.mnemonic));
|
|
128
|
+
console.log(chalk.cyan('\n📍 Address:'));
|
|
129
|
+
console.log(chalk.yellow(wallet.address));
|
|
130
|
+
} catch (error: any) {
|
|
131
|
+
console.log(chalk.red(`✗ Error: ${error.message}`));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function importWallet(rl: readline.Interface): Promise<void> {
|
|
136
|
+
const name = await question(rl, 'Wallet name: ');
|
|
137
|
+
const type = await question(rl, 'Import from (mnemonic/privatekey): ');
|
|
138
|
+
|
|
139
|
+
if (!name.trim()) {
|
|
140
|
+
console.log(chalk.red('✗ Wallet name cannot be empty'));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
let wallet;
|
|
146
|
+
|
|
147
|
+
if (type.toLowerCase() === 'mnemonic') {
|
|
148
|
+
const mnemonic = await question(rl, 'Enter mnemonic (12 words): ');
|
|
149
|
+
if (!isValidMnemonic(mnemonic)) {
|
|
150
|
+
console.log(chalk.red('✗ Invalid mnemonic'));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
console.log(chalk.yellow('⏳ Importing wallet...'));
|
|
154
|
+
wallet = await importFromMnemonic(mnemonic);
|
|
155
|
+
} else if (type.toLowerCase() === 'privatekey') {
|
|
156
|
+
const privateKey = await question(rl, 'Enter private key (hex): ');
|
|
157
|
+
console.log(chalk.yellow('⏳ Importing wallet...'));
|
|
158
|
+
wallet = importFromPrivateKey(privateKey);
|
|
159
|
+
} else {
|
|
160
|
+
console.log(chalk.red('✗ Invalid import type'));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const store = loadWallets();
|
|
165
|
+
const exists = store.wallets.some(w => w.name === name);
|
|
166
|
+
if (exists) {
|
|
167
|
+
console.log(chalk.red('✗ Wallet with this name already exists'));
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
store.wallets.push({
|
|
172
|
+
name,
|
|
173
|
+
address: wallet.address,
|
|
174
|
+
privateKey: wallet.privateKey,
|
|
175
|
+
publicKey: wallet.publicKey,
|
|
176
|
+
mnemonic: (wallet as any).mnemonic,
|
|
177
|
+
createdAt: new Date().toISOString()
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (!store.selectedWallet) {
|
|
181
|
+
store.selectedWallet = name;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
saveWallets(store);
|
|
185
|
+
console.log(chalk.green('✓ Wallet imported successfully!'));
|
|
186
|
+
console.log(chalk.cyan('📍 Address:'));
|
|
187
|
+
console.log(chalk.yellow(wallet.address));
|
|
188
|
+
} catch (error: any) {
|
|
189
|
+
console.log(chalk.red(`✗ Error: ${error.message}`));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function listWallets(): Promise<void> {
|
|
194
|
+
const store = loadWallets();
|
|
195
|
+
|
|
196
|
+
if (store.wallets.length === 0) {
|
|
197
|
+
console.log(chalk.yellow('No wallets found. Create one first!'));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
console.log(chalk.cyan('\n📊 Your Wallets:'));
|
|
202
|
+
console.log('─'.repeat(80));
|
|
203
|
+
|
|
204
|
+
store.wallets.forEach((wallet, index) => {
|
|
205
|
+
const selected = store.selectedWallet === wallet.name ? ' ✓' : '';
|
|
206
|
+
const created = new Date(wallet.createdAt).toLocaleDateString();
|
|
207
|
+
console.log(
|
|
208
|
+
`${index + 1}. ${chalk.bold(wallet.name)}${selected}`
|
|
209
|
+
);
|
|
210
|
+
console.log(` Address: ${chalk.green(wallet.address)}`);
|
|
211
|
+
console.log(` Created: ${created}`);
|
|
212
|
+
});
|
|
213
|
+
console.log('─'.repeat(80));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async function selectWallet(rl: readline.Interface): Promise<void> {
|
|
217
|
+
const store = loadWallets();
|
|
218
|
+
|
|
219
|
+
if (store.wallets.length === 0) {
|
|
220
|
+
console.log(chalk.yellow('No wallets found'));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
console.log(chalk.cyan('\nAvailable wallets:'));
|
|
225
|
+
store.wallets.forEach((w, i) => console.log(`${i + 1}. ${w.name}`));
|
|
226
|
+
|
|
227
|
+
const choice = await question(rl, 'Select wallet (number): ');
|
|
228
|
+
const index = parseInt(choice) - 1;
|
|
229
|
+
|
|
230
|
+
if (index >= 0 && index < store.wallets.length) {
|
|
231
|
+
store.selectedWallet = store.wallets[index].name;
|
|
232
|
+
saveWallets(store);
|
|
233
|
+
console.log(chalk.green(`✓ Selected: ${store.wallets[index].name}`));
|
|
234
|
+
} else {
|
|
235
|
+
console.log(chalk.red('✗ Invalid selection'));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function getBalance(): Promise<void> {
|
|
240
|
+
const store = loadWallets();
|
|
241
|
+
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
242
|
+
|
|
243
|
+
if (!wallet) {
|
|
244
|
+
console.log(chalk.red('✗ No wallet selected'));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
console.log(chalk.yellow('⏳ Fetching balance...'));
|
|
250
|
+
const rpc = createRPCClient(RPC_URL);
|
|
251
|
+
const balance = await rpc.getBalance(wallet.address);
|
|
252
|
+
|
|
253
|
+
console.log(chalk.cyan('\n💰 Balance Information:'));
|
|
254
|
+
console.log('─'.repeat(50));
|
|
255
|
+
console.log(chalk.yellow(' Wallet: ') + chalk.white(wallet.name));
|
|
256
|
+
console.log(chalk.yellow(' Address: ') + chalk.white(wallet.address));
|
|
257
|
+
console.log(chalk.yellow(' Balance: ') + chalk.green(`${balance.toFixed(8)} TETSUO`));
|
|
258
|
+
console.log('─'.repeat(50));
|
|
259
|
+
} catch (error: any) {
|
|
260
|
+
console.log(chalk.red(`✗ Error: ${error.message}`));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async function getTransactions(): Promise<void> {
|
|
265
|
+
const store = loadWallets();
|
|
266
|
+
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
267
|
+
|
|
268
|
+
if (!wallet) {
|
|
269
|
+
console.log(chalk.red('✗ No wallet selected'));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
console.log(chalk.yellow('⏳ Fetching transactions...'));
|
|
275
|
+
const rpc = createRPCClient(RPC_URL);
|
|
276
|
+
const transactions = await rpc.getTransactionHistory(wallet.address);
|
|
277
|
+
|
|
278
|
+
if (transactions.length === 0) {
|
|
279
|
+
console.log(chalk.cyan('\n📋 Transaction History:'));
|
|
280
|
+
console.log(chalk.yellow(' Wallet: ') + wallet.name);
|
|
281
|
+
console.log(chalk.yellow('No transactions found'));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
console.log(chalk.cyan('\n📋 Transaction History:'));
|
|
286
|
+
console.log(chalk.yellow(' Wallet: ') + wallet.name);
|
|
287
|
+
console.log('─'.repeat(80));
|
|
288
|
+
|
|
289
|
+
transactions.forEach((tx: any) => {
|
|
290
|
+
const type = tx.isIncoming ? chalk.green('↓ RECEIVE') : chalk.yellow('↑ SEND');
|
|
291
|
+
const date = new Date(tx.timestamp).toLocaleDateString();
|
|
292
|
+
const feeStr = tx.fee ? ` | Fee: ${tx.fee}` : '';
|
|
293
|
+
console.log(`${type} | ${tx.amount.toFixed(8)} TETSUO | Confirmations: ${tx.confirmations}${feeStr} | ${date}`);
|
|
294
|
+
});
|
|
295
|
+
console.log('─'.repeat(80));
|
|
296
|
+
} catch (error: any) {
|
|
297
|
+
console.log(chalk.red(`✗ Error: ${error.message}`));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async function receiveTokens(): Promise<void> {
|
|
302
|
+
const store = loadWallets();
|
|
303
|
+
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
304
|
+
|
|
305
|
+
if (!wallet) {
|
|
306
|
+
console.log(chalk.red('✗ No wallet selected'));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
console.log(chalk.cyan('\n📍 Receive Address:'));
|
|
311
|
+
console.log(chalk.green(wallet.address));
|
|
312
|
+
console.log(chalk.yellow('\nShare this address to receive TETSUO'));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async function sendTokens(rl: readline.Interface): Promise<void> {
|
|
316
|
+
const store = loadWallets();
|
|
317
|
+
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
318
|
+
|
|
319
|
+
if (!wallet) {
|
|
320
|
+
console.log(chalk.red('✗ No wallet selected'));
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const toAddress = await question(rl, 'Recipient address: ');
|
|
325
|
+
if (!isValidAddress(toAddress)) {
|
|
326
|
+
console.log(chalk.red('✗ Invalid recipient address'));
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const amount = await question(rl, 'Amount (TETSUO): ');
|
|
331
|
+
const numAmount = parseFloat(amount);
|
|
332
|
+
if (isNaN(numAmount) || numAmount <= 0) {
|
|
333
|
+
console.log(chalk.red('✗ Invalid amount'));
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
console.log(chalk.yellow('\n⏳ Preparing transaction...'));
|
|
339
|
+
const rpc = createRPCClient(RPC_URL);
|
|
340
|
+
|
|
341
|
+
// Get UTXOs
|
|
342
|
+
console.log(chalk.yellow(' Fetching UTXOs...'));
|
|
343
|
+
const utxos = await rpc.getUTXOs(wallet.address);
|
|
344
|
+
|
|
345
|
+
if (utxos.length === 0) {
|
|
346
|
+
console.log(chalk.red('✗ No UTXOs available to spend'));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Build transaction
|
|
351
|
+
const txData = buildTransaction(wallet.address, toAddress, numAmount, utxos, wallet.address);
|
|
352
|
+
|
|
353
|
+
// Show transaction details
|
|
354
|
+
console.log(chalk.cyan('\n📋 Transaction Details:'));
|
|
355
|
+
console.log('─'.repeat(60));
|
|
356
|
+
console.log(chalk.yellow(' From: ') + wallet.address);
|
|
357
|
+
console.log(chalk.yellow(' To: ') + toAddress);
|
|
358
|
+
console.log(chalk.yellow(' Amount: ') + chalk.green(numAmount.toFixed(8) + ' TETSUO'));
|
|
359
|
+
console.log(chalk.yellow(' Fee: ') + chalk.yellow((txData.fee / 100_000_000).toFixed(8) + ' TETSUO'));
|
|
360
|
+
console.log(chalk.yellow(' Total: ') + chalk.cyan((numAmount + txData.fee / 100_000_000).toFixed(8) + ' TETSUO'));
|
|
361
|
+
console.log('─'.repeat(60));
|
|
362
|
+
|
|
363
|
+
// Ask for confirmation
|
|
364
|
+
const confirm = await question(rl, chalk.cyan('\nConfirm transaction? (yes/no): '));
|
|
365
|
+
if (confirm.toLowerCase() !== 'yes' && confirm.toLowerCase() !== 'y') {
|
|
366
|
+
console.log(chalk.yellow('❌ Transaction cancelled'));
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Create and sign transaction
|
|
371
|
+
console.log(chalk.yellow('\n⏳ Signing transaction...'));
|
|
372
|
+
const txHex = createTransactionHex(txData.inputs, txData.outputs);
|
|
373
|
+
const signedTxHex = signTransaction(txHex, wallet.privateKey, txData.inputs, utxos);
|
|
374
|
+
|
|
375
|
+
// Broadcast or use server fallback
|
|
376
|
+
console.log(chalk.yellow(' Broadcasting...'));
|
|
377
|
+
let txid: string;
|
|
378
|
+
try {
|
|
379
|
+
// Try broadcasting signed transaction
|
|
380
|
+
txid = await rpc.broadcastTransaction(signedTxHex);
|
|
381
|
+
} catch (broadcastError: any) {
|
|
382
|
+
console.log(chalk.yellow(' Client signing verification failed, using server signature...'));
|
|
383
|
+
// Fallback: Use server to sign and broadcast
|
|
384
|
+
txid = await rpc.signAndBroadcast(txHex, wallet.privateKey);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
console.log(chalk.green('\n✅ Transaction sent successfully!'));
|
|
388
|
+
console.log(chalk.cyan('\n📊 Transaction Info:'));
|
|
389
|
+
console.log('─'.repeat(60));
|
|
390
|
+
console.log(chalk.yellow(' TXID: ') + chalk.green(txid));
|
|
391
|
+
console.log(chalk.yellow(' Amount: ') + chalk.green(numAmount.toFixed(8) + ' TETSUO'));
|
|
392
|
+
console.log(chalk.yellow(' Fee: ') + chalk.yellow((txData.fee / 100_000_000).toFixed(8) + ' TETSUO'));
|
|
393
|
+
console.log('─'.repeat(60));
|
|
394
|
+
console.log(chalk.cyan('\nCheck transaction status at: https://tetsuoarena.com/tx/' + txid));
|
|
395
|
+
} catch (error: any) {
|
|
396
|
+
console.log(chalk.red('\n✗ Error: ' + error.message));
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
async function walletData(): Promise<void> {
|
|
401
|
+
const store = loadWallets();
|
|
402
|
+
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
403
|
+
|
|
404
|
+
if (!wallet) {
|
|
405
|
+
console.log(chalk.red('✗ No wallet selected'));
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
console.log(chalk.cyan('\n📊 Wallet Data:'));
|
|
410
|
+
console.log('─'.repeat(80));
|
|
411
|
+
console.log(`Name: ${chalk.yellow(wallet.name)}`);
|
|
412
|
+
console.log(`Address: ${chalk.green(wallet.address)}`);
|
|
413
|
+
console.log(`Public Key: ${chalk.blue(wallet.publicKey)}`);
|
|
414
|
+
console.log(`Created: ${new Date(wallet.createdAt).toLocaleString()}`);
|
|
415
|
+
if (wallet.mnemonic) {
|
|
416
|
+
console.log(chalk.yellow('\nMnemonic (keep safe):'));
|
|
417
|
+
console.log(chalk.red(wallet.mnemonic));
|
|
418
|
+
}
|
|
419
|
+
console.log('─'.repeat(80));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
async function deleteWallet(rl: readline.Interface): Promise<void> {
|
|
423
|
+
const store = loadWallets();
|
|
424
|
+
const wallet = store.wallets.find(w => w.name === store.selectedWallet);
|
|
425
|
+
|
|
426
|
+
if (!wallet) {
|
|
427
|
+
console.log(chalk.red('✗ No wallet selected'));
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const confirm = await question(rl, `Delete ${wallet.name}? (yes/no): `);
|
|
432
|
+
if (confirm.toLowerCase() !== 'yes') {
|
|
433
|
+
console.log(chalk.yellow('Cancelled'));
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
store.wallets = store.wallets.filter(w => w.name !== wallet.name);
|
|
438
|
+
if (store.selectedWallet === wallet.name) {
|
|
439
|
+
store.selectedWallet = store.wallets[0]?.name;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
saveWallets(store);
|
|
443
|
+
console.log(chalk.green('✓ Wallet deleted'));
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async function configureRPC(rl: readline.Interface): Promise<void> {
|
|
447
|
+
const config = loadConfig();
|
|
448
|
+
|
|
449
|
+
console.log(chalk.cyan('\n⚙️ RPC Configuration:'));
|
|
450
|
+
console.log(`Current RPC URL: ${chalk.green(RPC_URL)}`);
|
|
451
|
+
|
|
452
|
+
const newUrl = await question(rl, 'Enter new RPC URL (or press Enter to keep current): ');
|
|
453
|
+
|
|
454
|
+
if (newUrl.trim()) {
|
|
455
|
+
RPC_URL = newUrl.trim();
|
|
456
|
+
saveConfig({ rpcUrl: RPC_URL });
|
|
457
|
+
console.log(chalk.green('✓ RPC URL updated!'));
|
|
458
|
+
console.log(`New URL: ${chalk.green(RPC_URL)}`);
|
|
459
|
+
} else {
|
|
460
|
+
console.log(chalk.yellow('No changes made'));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Helper to get user input
|
|
465
|
+
function question(rl: readline.Interface, prompt: string): Promise<string> {
|
|
466
|
+
return new Promise(resolve => {
|
|
467
|
+
rl.question(chalk.cyan(prompt), resolve);
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Main CLI Loop
|
|
472
|
+
async function main() {
|
|
473
|
+
initWalletStorage();
|
|
474
|
+
|
|
475
|
+
const rl = readline.createInterface({
|
|
476
|
+
input: process.stdin,
|
|
477
|
+
output: process.stdout
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
console.clear();
|
|
481
|
+
console.log(chalk.cyan.bold(`
|
|
482
|
+
TTTTTTTTT EEEEEEEE TTTTTTTT SSSSSSS UUUU UUUU OOOOOOO
|
|
483
|
+
TTT EEEE TTT SSSS UUUU UUUU OOOOOOO
|
|
484
|
+
TTT EEEEE TTT SSSSS UUUU UUUU OOOOO
|
|
485
|
+
TTT EEEE TTT SSS UUUU UUUU OOOOOOO
|
|
486
|
+
TTT EEEEEEEE TTT SSSSSSS UUUUUUUU OOOOOOO
|
|
487
|
+
|
|
488
|
+
WALLET : SECURE BLOCKCHAIN TRANSACTIONS
|
|
489
|
+
`));
|
|
490
|
+
console.log(chalk.cyan.bold('═══════════════════════════════'));
|
|
491
|
+
console.log(chalk.cyan.bold(' TETSUO BLOCKCHAIN WALLET'));
|
|
492
|
+
console.log(chalk.cyan.bold('═══════════════════════════════\n'));
|
|
493
|
+
|
|
494
|
+
let running = true;
|
|
495
|
+
|
|
496
|
+
while (running) {
|
|
497
|
+
const store = loadWallets();
|
|
498
|
+
const selected = store.selectedWallet
|
|
499
|
+
? chalk.green(`[${store.selectedWallet}]`)
|
|
500
|
+
: chalk.red('[No Wallet Selected]');
|
|
501
|
+
|
|
502
|
+
console.log(`\n${selected} Commands:`);
|
|
503
|
+
console.log('/create-wallet - Create new wallet');
|
|
504
|
+
console.log('/import-wallet - Import from mnemonic or private key');
|
|
505
|
+
console.log('/list-wallets - Show all wallets');
|
|
506
|
+
console.log('/select-wallet - Select active wallet');
|
|
507
|
+
console.log('/balance - Check balance');
|
|
508
|
+
console.log('/transactions - View transaction history');
|
|
509
|
+
console.log('/receive - Show receive address');
|
|
510
|
+
console.log('/send - Send tokens');
|
|
511
|
+
console.log('/wallet-data - View wallet details');
|
|
512
|
+
console.log('/delete-wallet - Delete wallet');
|
|
513
|
+
console.log('/config - Configure RPC URL');
|
|
514
|
+
console.log('/exit - Exit CLI\n');
|
|
515
|
+
|
|
516
|
+
const input = await question(rl, 'Command: ');
|
|
517
|
+
const command = input.toLowerCase().trim();
|
|
518
|
+
|
|
519
|
+
switch (command) {
|
|
520
|
+
case '/create-wallet':
|
|
521
|
+
await createWallet(rl);
|
|
522
|
+
break;
|
|
523
|
+
case '/import-wallet':
|
|
524
|
+
await importWallet(rl);
|
|
525
|
+
break;
|
|
526
|
+
case '/list-wallets':
|
|
527
|
+
await listWallets();
|
|
528
|
+
break;
|
|
529
|
+
case '/select-wallet':
|
|
530
|
+
await selectWallet(rl);
|
|
531
|
+
break;
|
|
532
|
+
case '/balance':
|
|
533
|
+
await getBalance();
|
|
534
|
+
break;
|
|
535
|
+
case '/transactions':
|
|
536
|
+
await getTransactions();
|
|
537
|
+
break;
|
|
538
|
+
case '/receive':
|
|
539
|
+
await receiveTokens();
|
|
540
|
+
break;
|
|
541
|
+
case '/send':
|
|
542
|
+
await sendTokens(rl);
|
|
543
|
+
break;
|
|
544
|
+
case '/wallet-data':
|
|
545
|
+
await walletData();
|
|
546
|
+
break;
|
|
547
|
+
case '/delete-wallet':
|
|
548
|
+
await deleteWallet(rl);
|
|
549
|
+
break;
|
|
550
|
+
case '/config':
|
|
551
|
+
await configureRPC(rl);
|
|
552
|
+
break;
|
|
553
|
+
case '/exit':
|
|
554
|
+
running = false;
|
|
555
|
+
console.log(chalk.green('\nGoodbye! 👋\n'));
|
|
556
|
+
break;
|
|
557
|
+
default:
|
|
558
|
+
console.log(chalk.red('✗ Unknown command'));
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
rl.close();
|
|
563
|
+
process.exit(0);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
main().catch(error => {
|
|
567
|
+
console.error(chalk.red('Fatal error:'), error);
|
|
568
|
+
process.exit(1);
|
|
569
|
+
});
|