@feardread/fear 1.0.1

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.
Files changed (99) hide show
  1. package/FEAR.js +459 -0
  2. package/FEARServer.js +280 -0
  3. package/controllers/agent.js +438 -0
  4. package/controllers/auth/index.js +345 -0
  5. package/controllers/auth/token.js +50 -0
  6. package/controllers/blog.js +105 -0
  7. package/controllers/brand.js +10 -0
  8. package/controllers/cart.js +425 -0
  9. package/controllers/category.js +9 -0
  10. package/controllers/coupon.js +63 -0
  11. package/controllers/crud/crud.js +508 -0
  12. package/controllers/crud/index.js +36 -0
  13. package/controllers/email.js +34 -0
  14. package/controllers/enquiry.js +65 -0
  15. package/controllers/events.js +9 -0
  16. package/controllers/order.js +125 -0
  17. package/controllers/payment.js +31 -0
  18. package/controllers/product.js +147 -0
  19. package/controllers/review.js +247 -0
  20. package/controllers/tag.js +10 -0
  21. package/controllers/task.js +10 -0
  22. package/controllers/upload.js +41 -0
  23. package/controllers/user.js +401 -0
  24. package/index.js +7 -0
  25. package/libs/agent/index.js +561 -0
  26. package/libs/agent/modules/ai/ai.js +285 -0
  27. package/libs/agent/modules/ai/chat.js +518 -0
  28. package/libs/agent/modules/ai/config.js +688 -0
  29. package/libs/agent/modules/ai/operations.js +787 -0
  30. package/libs/agent/modules/analyze/api.js +546 -0
  31. package/libs/agent/modules/analyze/dorks.js +395 -0
  32. package/libs/agent/modules/ccard/README.md +454 -0
  33. package/libs/agent/modules/ccard/audit.js +479 -0
  34. package/libs/agent/modules/ccard/checker.js +674 -0
  35. package/libs/agent/modules/ccard/payment-processors.json +16 -0
  36. package/libs/agent/modules/ccard/validator.js +629 -0
  37. package/libs/agent/modules/code/analyzer.js +303 -0
  38. package/libs/agent/modules/code/jquery.js +1093 -0
  39. package/libs/agent/modules/code/react.js +1536 -0
  40. package/libs/agent/modules/code/refactor.js +499 -0
  41. package/libs/agent/modules/crypto/exchange.js +564 -0
  42. package/libs/agent/modules/net/proxy.js +409 -0
  43. package/libs/agent/modules/security/cve.js +442 -0
  44. package/libs/agent/modules/security/monitor.js +360 -0
  45. package/libs/agent/modules/security/scanner.js +300 -0
  46. package/libs/agent/modules/security/vulnerability.js +506 -0
  47. package/libs/agent/modules/security/web.js +465 -0
  48. package/libs/agent/modules/utils/browser.js +492 -0
  49. package/libs/agent/modules/utils/colorizer.js +285 -0
  50. package/libs/agent/modules/utils/manager.js +478 -0
  51. package/libs/cloud/index.js +228 -0
  52. package/libs/config/db.js +21 -0
  53. package/libs/config/validator.js +82 -0
  54. package/libs/db/index.js +318 -0
  55. package/libs/emailer/imap.js +126 -0
  56. package/libs/emailer/info.js +41 -0
  57. package/libs/emailer/smtp.js +77 -0
  58. package/libs/handler/async.js +3 -0
  59. package/libs/handler/error.js +66 -0
  60. package/libs/handler/index.js +161 -0
  61. package/libs/logger/index.js +49 -0
  62. package/libs/logger/morgan.js +24 -0
  63. package/libs/passport/passport.js +109 -0
  64. package/libs/search/api.js +384 -0
  65. package/libs/search/features.js +219 -0
  66. package/libs/search/service.js +64 -0
  67. package/libs/swagger/config.js +18 -0
  68. package/libs/swagger/index.js +35 -0
  69. package/libs/validator/index.js +254 -0
  70. package/models/blog.js +31 -0
  71. package/models/brand.js +12 -0
  72. package/models/cart.js +14 -0
  73. package/models/category.js +11 -0
  74. package/models/coupon.js +9 -0
  75. package/models/customer.js +0 -0
  76. package/models/enquiry.js +29 -0
  77. package/models/events.js +13 -0
  78. package/models/order.js +94 -0
  79. package/models/product.js +32 -0
  80. package/models/review.js +14 -0
  81. package/models/tag.js +10 -0
  82. package/models/task.js +11 -0
  83. package/models/user.js +68 -0
  84. package/package.json +12 -0
  85. package/routes/agent.js +615 -0
  86. package/routes/auth.js +13 -0
  87. package/routes/blog.js +19 -0
  88. package/routes/brand.js +15 -0
  89. package/routes/cart.js +105 -0
  90. package/routes/category.js +16 -0
  91. package/routes/coupon.js +15 -0
  92. package/routes/enquiry.js +14 -0
  93. package/routes/events.js +16 -0
  94. package/routes/mail.js +170 -0
  95. package/routes/order.js +19 -0
  96. package/routes/product.js +22 -0
  97. package/routes/review.js +11 -0
  98. package/routes/task.js +12 -0
  99. package/routes/user.js +17 -0
@@ -0,0 +1,564 @@
1
+ const https = require('https');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const colorizer = require('../utils/colorizer');
5
+
6
+ /**
7
+ * Crypto Exchange Rate Checker
8
+ * Fetches and compares cryptocurrency exchange rates across multiple platforms
9
+ */
10
+ class CryptoExchangeChecker {
11
+ constructor() {
12
+ this.name = 'Crypto Exchange Checker';
13
+ this.cache = {
14
+ rates: {},
15
+ timestamp: null,
16
+ ttl: 60000 // Cache for 1 minute
17
+ };
18
+
19
+ // Major cryptocurrency exchanges APIs
20
+ this.exchanges = {
21
+ coinbase: {
22
+ name: 'Coinbase',
23
+ apiUrl: 'api.coinbase.com',
24
+ path: '/v2/exchange-rates?currency=',
25
+ parseRate: (data, targetCurrency) => {
26
+ if (data.data && data.data.rates && data.data.rates[targetCurrency]) {
27
+ return parseFloat(data.data.rates[targetCurrency]);
28
+ }
29
+ return null;
30
+ }
31
+ },
32
+ kraken: {
33
+ name: 'Kraken',
34
+ apiUrl: 'api.kraken.com',
35
+ path: '/0/public/Ticker?pair=',
36
+ pairFormat: (base, quote) => `${base}${quote}`,
37
+ parseRate: (data) => {
38
+ if (data.result) {
39
+ const pair = Object.keys(data.result)[0];
40
+ if (pair && data.result[pair] && data.result[pair].c) {
41
+ return parseFloat(data.result[pair].c[0]);
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+ },
47
+ binance: {
48
+ name: 'Binance',
49
+ apiUrl: 'api.binance.com',
50
+ path: '/api/v3/ticker/price?symbol=',
51
+ pairFormat: (base, quote) => `${base}${quote}`,
52
+ parseRate: (data) => {
53
+ if (data.price) {
54
+ return parseFloat(data.price);
55
+ }
56
+ return null;
57
+ }
58
+ }
59
+ };
60
+
61
+ // Popular cryptocurrencies
62
+ this.cryptos = {
63
+ BTC: { name: 'Bitcoin', symbol: 'BTC' },
64
+ ETH: { name: 'Ethereum', symbol: 'ETH' },
65
+ USDT: { name: 'Tether', symbol: 'USDT' },
66
+ BNB: { name: 'Binance Coin', symbol: 'BNB' },
67
+ XRP: { name: 'Ripple', symbol: 'XRP' },
68
+ ADA: { name: 'Cardano', symbol: 'ADA' },
69
+ DOGE: { name: 'Dogecoin', symbol: 'DOGE' },
70
+ SOL: { name: 'Solana', symbol: 'SOL' },
71
+ DOT: { name: 'Polkadot', symbol: 'DOT' },
72
+ MATIC: { name: 'Polygon', symbol: 'MATIC' }
73
+ };
74
+
75
+ // Fiat currencies
76
+ this.fiatCurrencies = ['USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD'];
77
+ }
78
+
79
+ /**
80
+ * Make HTTPS request
81
+ */
82
+ httpsRequest(hostname, path) {
83
+ return new Promise((resolve, reject) => {
84
+ const options = {
85
+ hostname: hostname,
86
+ path: path,
87
+ method: 'GET',
88
+ headers: {
89
+ 'User-Agent': 'SecurityAgent/2.3',
90
+ 'Accept': 'application/json'
91
+ }
92
+ };
93
+
94
+ const req = https.request(options, (res) => {
95
+ let data = '';
96
+
97
+ res.on('data', (chunk) => {
98
+ data += chunk;
99
+ });
100
+
101
+ res.on('end', () => {
102
+ try {
103
+ resolve(JSON.parse(data));
104
+ } catch (err) {
105
+ reject(new Error('Failed to parse JSON response'));
106
+ }
107
+ });
108
+ });
109
+
110
+ req.on('error', (err) => {
111
+ reject(err);
112
+ });
113
+
114
+ req.setTimeout(10000, () => {
115
+ req.destroy();
116
+ reject(new Error('Request timeout'));
117
+ });
118
+
119
+ req.end();
120
+ });
121
+ }
122
+
123
+ /**
124
+ * Fetch rate from Coinbase
125
+ */
126
+ async fetchCoinbaseRate(baseCurrency, targetCurrency) {
127
+ try {
128
+ const exchange = this.exchanges.coinbase;
129
+ const path = exchange.path + baseCurrency;
130
+ const data = await this.httpsRequest(exchange.apiUrl, path);
131
+ return exchange.parseRate(data, targetCurrency);
132
+ } catch (err) {
133
+ return null;
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Fetch rate from Kraken
139
+ */
140
+ async fetchKrakenRate(baseCurrency, targetCurrency) {
141
+ try {
142
+ const exchange = this.exchanges.kraken;
143
+ const pair = exchange.pairFormat(baseCurrency, targetCurrency);
144
+ const path = exchange.path + pair;
145
+ const data = await this.httpsRequest(exchange.apiUrl, path);
146
+ return exchange.parseRate(data);
147
+ } catch (err) {
148
+ return null;
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Fetch rate from Binance
154
+ */
155
+ async fetchBinanceRate(baseCurrency, targetCurrency) {
156
+ try {
157
+ const exchange = this.exchanges.binance;
158
+ const pair = exchange.pairFormat(baseCurrency, targetCurrency);
159
+ const path = exchange.path + pair;
160
+ const data = await this.httpsRequest(exchange.apiUrl, path);
161
+ return exchange.parseRate(data);
162
+ } catch (err) {
163
+ return null;
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Check if cache is valid
169
+ */
170
+ isCacheValid() {
171
+ if (!this.cache.timestamp) return false;
172
+ return (Date.now() - this.cache.timestamp) < this.cache.ttl;
173
+ }
174
+
175
+ /**
176
+ * Compare rates across exchanges
177
+ */
178
+ async compareRates(args) {
179
+ if (args.length < 2) {
180
+ console.log(colorizer.error('Usage: compare-rates <crypto> <fiat>'));
181
+ console.log(colorizer.info('Example: compare-rates BTC USD'));
182
+ console.log(colorizer.dim('Supported cryptos: ' + Object.keys(this.cryptos).join(', ')));
183
+ console.log(colorizer.dim('Supported fiat: ' + this.fiatCurrencies.join(', ')));
184
+ return Promise.resolve();
185
+ }
186
+
187
+ const crypto = args[0].toUpperCase();
188
+ const fiat = args[1].toUpperCase();
189
+
190
+ if (!this.cryptos[crypto]) {
191
+ console.log(colorizer.error('Unsupported cryptocurrency: ' + crypto));
192
+ console.log(colorizer.info('Supported: ' + Object.keys(this.cryptos).join(', ')));
193
+ return Promise.resolve();
194
+ }
195
+
196
+ if (!this.fiatCurrencies.includes(fiat)) {
197
+ console.log(colorizer.error('Unsupported fiat currency: ' + fiat));
198
+ console.log(colorizer.info('Supported: ' + this.fiatCurrencies.join(', ')));
199
+ return Promise.resolve();
200
+ }
201
+
202
+ console.log(colorizer.section(`Comparing ${crypto}/${fiat} Exchange Rates`));
203
+ console.log(colorizer.dim('Fetching rates from multiple exchanges...'));
204
+ console.log();
205
+
206
+ const rates = {};
207
+
208
+ // Fetch from Coinbase
209
+ process.stdout.write(colorizer.dim(' Coinbase... '));
210
+ rates.coinbase = await this.fetchCoinbaseRate(crypto, fiat);
211
+ console.log(rates.coinbase ? colorizer.green('✓') : colorizer.red('✗'));
212
+
213
+ // Fetch from Kraken
214
+ process.stdout.write(colorizer.dim(' Kraken... '));
215
+ rates.kraken = await this.fetchKrakenRate(crypto, fiat);
216
+ console.log(rates.kraken ? colorizer.green('✓') : colorizer.red('✗'));
217
+
218
+ // Fetch from Binance
219
+ process.stdout.write(colorizer.dim(' Binance... '));
220
+ rates.binance = await this.fetchBinanceRate(crypto, fiat);
221
+ console.log(rates.binance ? colorizer.green('✓') : colorizer.red('✗'));
222
+
223
+ console.log();
224
+
225
+ // Display results
226
+ const validRates = Object.entries(rates)
227
+ .filter(([_, rate]) => rate !== null)
228
+ .sort(([_, a], [__, b]) => a - b); // Sort by rate (best to worst for selling)
229
+
230
+ if (validRates.length === 0) {
231
+ console.log(colorizer.error('Failed to fetch rates from any exchange'));
232
+ console.log(colorizer.dim('This may be due to API rate limits or unsupported pair'));
233
+ return Promise.resolve();
234
+ }
235
+
236
+ console.log(colorizer.cyan('Exchange Rates:'));
237
+ validRates.forEach(([exchange, rate], index) => {
238
+ const exchangeName = this.exchanges[exchange].name;
239
+ const badge = index === 0 ? colorizer.green(' [BEST BUY]') :
240
+ index === validRates.length - 1 ? colorizer.yellow(' [BEST SELL]') : '';
241
+
242
+ console.log(colorizer.bullet(
243
+ exchangeName.padEnd(15) +
244
+ colorizer.bright(this.formatPrice(rate, fiat)) +
245
+ badge
246
+ ));
247
+ });
248
+
249
+ // Calculate spread
250
+ if (validRates.length > 1) {
251
+ const lowest = validRates[0][1];
252
+ const highest = validRates[validRates.length - 1][1];
253
+ const spread = highest - lowest;
254
+ const spreadPercent = ((spread / lowest) * 100).toFixed(2);
255
+
256
+ console.log();
257
+ console.log(colorizer.cyan('Arbitrage Opportunity:'));
258
+ console.log(colorizer.bullet('Spread: ' + this.formatPrice(spread, fiat) +
259
+ ' (' + spreadPercent + '%)'));
260
+
261
+ if (spreadPercent > 1) {
262
+ console.log(colorizer.yellow(' ⚠ Significant price difference detected!'));
263
+ }
264
+ }
265
+
266
+ // Calculate average
267
+ const average = validRates.reduce((sum, [_, rate]) => sum + rate, 0) / validRates.length;
268
+ console.log();
269
+ console.log(colorizer.cyan('Average Rate: ') + colorizer.bright(this.formatPrice(average, fiat)));
270
+ console.log();
271
+ console.log(colorizer.dim('Note: Rates are indicative and may not reflect actual trading fees'));
272
+ console.log();
273
+
274
+ return Promise.resolve();
275
+ }
276
+
277
+ /**
278
+ * Get current price for a cryptocurrency
279
+ */
280
+ async getPrice(args) {
281
+ if (args.length === 0) {
282
+ console.log(colorizer.error('Usage: crypto-price <symbol> [fiat]'));
283
+ console.log(colorizer.info('Example: crypto-price BTC USD'));
284
+ console.log(colorizer.dim('Supported cryptos: ' + Object.keys(this.cryptos).join(', ')));
285
+ return Promise.resolve();
286
+ }
287
+
288
+ const crypto = args[0].toUpperCase();
289
+ const fiat = (args[1] || 'USD').toUpperCase();
290
+
291
+ if (!this.cryptos[crypto]) {
292
+ console.log(colorizer.error('Unsupported cryptocurrency: ' + crypto));
293
+ return Promise.resolve();
294
+ }
295
+
296
+ console.log(colorizer.section(`${this.cryptos[crypto].name} (${crypto}) Price`));
297
+ console.log(colorizer.dim('Fetching current price...'));
298
+ console.log();
299
+
300
+ const rate = await this.fetchCoinbaseRate(crypto, fiat);
301
+
302
+ if (rate) {
303
+ console.log(colorizer.cyan('Current Price: ') +
304
+ colorizer.bright(colorizer.green(this.formatPrice(rate, fiat))));
305
+ console.log(colorizer.dim('Source: Coinbase'));
306
+ } else {
307
+ console.log(colorizer.error('Failed to fetch price'));
308
+ }
309
+
310
+ console.log();
311
+ return Promise.resolve();
312
+ }
313
+
314
+ /**
315
+ * Track multiple cryptocurrencies
316
+ */
317
+ async trackPortfolio(args) {
318
+ const cryptoList = args.length > 0 ?
319
+ args.map(c => c.toUpperCase()) :
320
+ ['BTC', 'ETH', 'BNB', 'XRP', 'ADA'];
321
+
322
+ console.log(colorizer.section('Cryptocurrency Portfolio Tracker'));
323
+ console.log(colorizer.dim('Tracking: ' + cryptoList.join(', ')));
324
+ console.log();
325
+
326
+ const results = [];
327
+
328
+ for (const crypto of cryptoList) {
329
+ if (!this.cryptos[crypto]) {
330
+ console.log(colorizer.warning(`Skipping unsupported: ${crypto}`));
331
+ continue;
332
+ }
333
+
334
+ process.stdout.write(colorizer.dim(` Fetching ${crypto}... `));
335
+ const rate = await this.fetchCoinbaseRate(crypto, 'USD');
336
+
337
+ if (rate) {
338
+ results.push({ crypto, rate });
339
+ console.log(colorizer.green('✓'));
340
+ } else {
341
+ console.log(colorizer.red('✗'));
342
+ }
343
+ }
344
+
345
+ console.log();
346
+ console.log(colorizer.cyan('Current Prices (USD):'));
347
+
348
+ results.forEach(({ crypto, rate }) => {
349
+ const name = this.cryptos[crypto].name;
350
+ console.log(colorizer.bullet(
351
+ crypto.padEnd(8) +
352
+ name.padEnd(20) +
353
+ colorizer.bright(this.formatPrice(rate, 'USD'))
354
+ ));
355
+ });
356
+
357
+ console.log();
358
+ return Promise.resolve();
359
+ }
360
+
361
+ /**
362
+ * Calculate conversion between cryptocurrencies
363
+ */
364
+ async convert(args) {
365
+ if (args.length < 3) {
366
+ console.log(colorizer.error('Usage: crypto-convert <amount> <from> <to>'));
367
+ console.log(colorizer.info('Example: crypto-convert 1 BTC ETH'));
368
+ return Promise.resolve();
369
+ }
370
+
371
+ const amount = parseFloat(args[0]);
372
+ const fromCrypto = args[1].toUpperCase();
373
+ const toCrypto = args[2].toUpperCase();
374
+
375
+ if (isNaN(amount) || amount <= 0) {
376
+ console.log(colorizer.error('Invalid amount'));
377
+ return Promise.resolve();
378
+ }
379
+
380
+ if (!this.cryptos[fromCrypto] || !this.cryptos[toCrypto]) {
381
+ console.log(colorizer.error('Unsupported cryptocurrency'));
382
+ return Promise.resolve();
383
+ }
384
+
385
+ console.log(colorizer.section('Crypto Conversion'));
386
+ console.log(colorizer.dim('Calculating conversion rate...'));
387
+ console.log();
388
+
389
+ // Convert through USD as intermediate
390
+ const fromRate = await this.fetchCoinbaseRate(fromCrypto, 'USD');
391
+ const toRate = await this.fetchCoinbaseRate(toCrypto, 'USD');
392
+
393
+ if (!fromRate || !toRate) {
394
+ console.log(colorizer.error('Failed to fetch conversion rates'));
395
+ return Promise.resolve();
396
+ }
397
+
398
+ const usdValue = amount * fromRate;
399
+ const convertedAmount = usdValue / toRate;
400
+
401
+ console.log(colorizer.cyan('Conversion:'));
402
+ console.log(colorizer.bullet(
403
+ colorizer.bright(amount.toFixed(8)) + ' ' + fromCrypto +
404
+ ' → ' +
405
+ colorizer.bright(convertedAmount.toFixed(8)) + ' ' + toCrypto
406
+ ));
407
+ console.log();
408
+ console.log(colorizer.dim('USD Equivalent: ' + this.formatPrice(usdValue, 'USD')));
409
+ console.log(colorizer.dim('Source: Coinbase'));
410
+ console.log();
411
+
412
+ return Promise.resolve();
413
+ }
414
+
415
+ /**
416
+ * Show market summary
417
+ */
418
+ async marketSummary(args) {
419
+ console.log(colorizer.section('Cryptocurrency Market Summary'));
420
+ console.log(colorizer.dim('Top cryptocurrencies by market cap'));
421
+ console.log();
422
+
423
+ const topCryptos = ['BTC', 'ETH', 'USDT', 'BNB', 'XRP', 'ADA', 'DOGE', 'SOL'];
424
+ const rates = [];
425
+
426
+ for (const crypto of topCryptos) {
427
+ const rate = await this.fetchCoinbaseRate(crypto, 'USD');
428
+ if (rate) {
429
+ rates.push({ crypto, rate });
430
+ }
431
+ }
432
+
433
+ console.log(colorizer.cyan('Current Prices (USD):'));
434
+ console.log(colorizer.dim('─'.repeat(60)));
435
+ console.log(colorizer.dim(
436
+ 'Symbol'.padEnd(10) +
437
+ 'Name'.padEnd(20) +
438
+ 'Price'.padEnd(20)
439
+ ));
440
+ console.log(colorizer.dim('─'.repeat(60)));
441
+
442
+ rates.forEach(({ crypto, rate }) => {
443
+ const name = this.cryptos[crypto].name;
444
+ console.log(
445
+ colorizer.bright(crypto.padEnd(10)) +
446
+ name.padEnd(20) +
447
+ colorizer.green(this.formatPrice(rate, 'USD').padEnd(20))
448
+ );
449
+ });
450
+
451
+ console.log(colorizer.dim('─'.repeat(60)));
452
+ console.log();
453
+ console.log(colorizer.dim('Data source: Coinbase'));
454
+ console.log();
455
+
456
+ return Promise.resolve();
457
+ }
458
+
459
+ /**
460
+ * Export rates to file
461
+ */
462
+ async exportRates(args) {
463
+ const outputFile = args[0] || 'crypto-rates.json';
464
+
465
+ console.log(colorizer.section('Exporting Cryptocurrency Rates'));
466
+ console.log(colorizer.dim('Fetching rates...'));
467
+ console.log();
468
+
469
+ const data = {
470
+ timestamp: new Date().toISOString(),
471
+ rates: {}
472
+ };
473
+
474
+ for (const crypto of Object.keys(this.cryptos)) {
475
+ const rate = await this.fetchCoinbaseRate(crypto, 'USD');
476
+ if (rate) {
477
+ data.rates[crypto] = {
478
+ name: this.cryptos[crypto].name,
479
+ usd: rate
480
+ };
481
+ }
482
+ }
483
+
484
+ fs.writeFileSync(outputFile, JSON.stringify(data, null, 2));
485
+
486
+ console.log(colorizer.green('✓ Rates exported to: ' + outputFile));
487
+ console.log(colorizer.dim(' Cryptocurrencies: ' + Object.keys(data.rates).length));
488
+ console.log(colorizer.dim(' Timestamp: ' + data.timestamp));
489
+ console.log();
490
+
491
+ return Promise.resolve();
492
+ }
493
+
494
+ /**
495
+ * Show help for crypto commands
496
+ */
497
+ showHelp(args) {
498
+ console.log(colorizer.section('Crypto Exchange Checker - Help'));
499
+ console.log();
500
+
501
+ const commands = [
502
+ { cmd: 'compare-rates', desc: 'Compare rates across exchanges', example: 'compare-rates BTC USD' },
503
+ { cmd: 'crypto-price', desc: 'Get current price for a crypto', example: 'crypto-price ETH' },
504
+ { cmd: 'track-portfolio', desc: 'Track multiple cryptocurrencies', example: 'track-portfolio BTC ETH XRP' },
505
+ { cmd: 'crypto-convert', desc: 'Convert between cryptocurrencies', example: 'crypto-convert 1 BTC ETH' },
506
+ { cmd: 'market-summary', desc: 'Show market summary', example: 'market-summary' },
507
+ { cmd: 'export-rates', desc: 'Export rates to JSON file', example: 'export-rates rates.json' }
508
+ ];
509
+
510
+ console.log(colorizer.cyan('Available Commands:'));
511
+ commands.forEach(({ cmd, desc, example }) => {
512
+ console.log(colorizer.bullet(colorizer.bright(cmd)));
513
+ console.log(colorizer.dim(' ' + desc));
514
+ console.log(colorizer.dim(' Example: ' + example));
515
+ console.log();
516
+ });
517
+
518
+ console.log(colorizer.cyan('Supported Cryptocurrencies:'));
519
+ Object.entries(this.cryptos).forEach(([symbol, info]) => {
520
+ console.log(colorizer.dim(' ' + symbol + ' - ' + info.name));
521
+ });
522
+
523
+ console.log();
524
+ console.log(colorizer.cyan('Supported Exchanges:'));
525
+ Object.entries(this.exchanges).forEach(([key, exchange]) => {
526
+ console.log(colorizer.dim(' ' + exchange.name));
527
+ });
528
+
529
+ console.log();
530
+ console.log(colorizer.warning('Note: Rates are indicative and exclude trading fees'));
531
+ console.log(colorizer.dim('Always verify rates on the actual exchange before trading'));
532
+ console.log();
533
+
534
+ return Promise.resolve();
535
+ }
536
+
537
+ /**
538
+ * Helper: Format price with currency symbol
539
+ */
540
+ formatPrice(price, currency) {
541
+ const symbols = {
542
+ USD: '$',
543
+ EUR: '€',
544
+ GBP: '£',
545
+ JPY: '¥',
546
+ CAD: 'C$',
547
+ AUD: 'A$'
548
+ };
549
+
550
+ const symbol = symbols[currency] || currency + ' ';
551
+
552
+ if (price >= 1000) {
553
+ return symbol + price.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
554
+ } else if (price >= 1) {
555
+ return symbol + price.toFixed(2);
556
+ } else if (price >= 0.01) {
557
+ return symbol + price.toFixed(4);
558
+ } else {
559
+ return symbol + price.toFixed(8);
560
+ }
561
+ }
562
+ }
563
+
564
+ module.exports = CryptoExchangeChecker;