alpha-cli-toolkit 1.2.0 → 1.4.0

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 (2) hide show
  1. package/bin/alpha.js +163 -5
  2. package/package.json +1 -1
package/bin/alpha.js CHANGED
@@ -7,7 +7,7 @@ const Table = require('cli-table3');
7
7
  const { authenticateViaBrowser, getToken, clearToken } = require('../utils/auth');
8
8
 
9
9
  const program = new Command();
10
- const BACKEND_URL = process.env.ALPHA_BACKEND_URL;
10
+ const BACKEND_URL = process.env.ALPHA_BACKEND_URL || 'https://alpha-cli.onrender.com/api';
11
11
 
12
12
  program
13
13
  .name('alpha')
@@ -71,7 +71,7 @@ program
71
71
  }
72
72
 
73
73
  // Backend health
74
- const healthUrl = BACKEND_URL ? `${BACKEND_URL.replace(/\/api$/, '')}/health` : 'http://localhost:4000/health';
74
+ const healthUrl = `${BACKEND_URL.replace(/\/api$/, '')}/health`;
75
75
  try {
76
76
  const { data } = await axios.get(healthUrl, { timeout: 3000 });
77
77
  console.log(chalk.green(' āœ… Backend online') + chalk.grey(` (${data.timestamp})`));
@@ -111,19 +111,21 @@ program
111
111
  .option('-n, --nsd', 'Trending NASDAQ assets via Yahoo Finance')
112
112
  .option('-f, --nft', 'NFT Market Indexes (Nansen)')
113
113
  .option('-m, --macro', 'Smart Money Holdings \u0026 Macro (Nansen)')
114
+ .option('--min-usd <value>', 'Filter Smart Money by minimum USD value', '1000')
115
+ .option('--chains <list>', 'Comma-separated chains (e.g. solana,ethereum)', 'solana')
114
116
  .action(async (options) => {
115
117
  const token = checkAuth();
116
118
  const axios = require('axios');
117
119
 
118
- let url = `${BACKEND_URL}/market/crypto/trending`;
120
+ let url = `${BACKEND_URL}/market/crypto/trending?min_usd=${options.minUsd}&chains=${options.chains}`;
119
121
  let cType = 'CRYPTO';
120
122
 
121
123
  if (options.sp500) { url = `${BACKEND_URL}/market/tradfi/sp500`; cType = 'S&P 500'; }
122
124
  else if (options.nsd) { url = `${BACKEND_URL}/market/tradfi/nsd`; cType = 'NASDAQ'; }
123
125
  else if (options.nft || options.macro) {
124
- console.log(chalk.cyan(`\nšŸ” Fetching Nansen Market Macro Insights...`));
126
+ console.log(chalk.cyan(`\nšŸ” Fetching Nansen Market Macro Insights (Chains: ${options.chains})...`));
125
127
  try {
126
- const { data } = await axios.get(`${BACKEND_URL}/market/macro`, { headers: authHeaders(token) });
128
+ const { data } = await axios.get(`${BACKEND_URL}/market/macro?chains=${options.chains}`, { headers: authHeaders(token) });
127
129
  if (options.nft) {
128
130
  console.log(gradient.atlas(`\n─── Nansen NFT Indexes ──────────────────────────`));
129
131
  console.log(JSON.stringify(data.nftIndexes, null, 2));
@@ -150,6 +152,14 @@ program
150
152
  }
151
153
 
152
154
  buildMarketTable(items, cType);
155
+
156
+ if (data.netflow?.length) {
157
+ console.log(gradient.atlas(`\n─── Whale Netflows (Min: $${options.minUsd}) ─────`));
158
+ data.netflow.slice(0, 5).forEach((flow) => {
159
+ const direction = flow.net_flow_usd >= 0 ? chalk.green('INFLOW') : chalk.red('OUTFLOW');
160
+ console.log(` ${chalk.bold(flow.token_name || flow.symbol)}: ${direction} $${Math.abs(flow.net_flow_usd).toLocaleString()}`);
161
+ });
162
+ }
153
163
  } catch (err) {
154
164
  console.error(chalk.red('Failed to fetch market data:'), err.response?.data?.error || err.message);
155
165
  }
@@ -211,6 +221,154 @@ program
211
221
  }
212
222
  });
213
223
 
224
+ // ─────────────────────────────────────────────────────────────────────────────
225
+ // FLOW COMMAND (Smart Money Netflow Explorer)
226
+ // ─────────────────────────────────────────────────────────────────────────────
227
+ program
228
+ .command('flow')
229
+ .description('Deep-dive into capital rotation via Smart Money Netflows')
230
+ .option('--chains <list>', 'Comma-separated chains (e.g. solana,ethereum)', 'solana')
231
+ .option('--sort <period>', 'Sorting timeframe: 1h, 24h, 7d, 30d', '24h')
232
+ .option('--order <dir>', 'Sort direction: DESC, ASC', 'DESC')
233
+ .option('--sector <name>', 'Filter by token sector (e.g. DeFi, AI, Meme)')
234
+ .option('--labels <list>', 'Smart Money labels to include', 'Fund,Smart Trader')
235
+ .option('--stablecoins', 'Include stablecoins in the analysis', false)
236
+ .action(async (options) => {
237
+ const token = checkAuth();
238
+ const axios = require('axios');
239
+
240
+ console.log(chalk.cyan(`\nšŸ” Exploring Smart Money rotation...`));
241
+ console.log(chalk.grey(` Timeframe: ${options.sort} | Chains: ${options.chains} | Sort: ${options.order}\n`));
242
+
243
+ try {
244
+ const { data } = await axios.get(`${BACKEND_URL}/market/smart-money/netflow`, {
245
+ params: {
246
+ chains: options.chains,
247
+ sort: options.sort,
248
+ direction: options.order,
249
+ sector: options.sector,
250
+ labels: options.labels,
251
+ include_stablecoins: options.stablecoins
252
+ },
253
+ headers: authHeaders(token)
254
+ });
255
+
256
+ const items = data.data || [];
257
+
258
+ if (!items.length) {
259
+ console.log(chalk.yellow(' No flow data found for these filters.\n'));
260
+ return;
261
+ }
262
+
263
+ const table = new Table({
264
+ head: [
265
+ chalk.bold.white('Asset'),
266
+ chalk.bold.white('1H Flow'),
267
+ chalk.bold.white('24H Flow'),
268
+ chalk.bold.white('7D Flow'),
269
+ chalk.bold.white('Sector'),
270
+ ],
271
+ colWidths: [18, 16, 16, 16, 20],
272
+ style: { border: ['grey'] },
273
+ });
274
+
275
+ items.slice(0, 15).forEach((item) => {
276
+ const formatFlow = (val) => {
277
+ if (!val) return chalk.grey('—');
278
+ const colorizer = val >= 0 ? chalk.green : chalk.red;
279
+ const prefix = val >= 0 ? '+' : '';
280
+ return colorizer(`${prefix}$${Math.abs(val / 1e3).toFixed(1)}k`);
281
+ };
282
+
283
+ table.push([
284
+ chalk.bold.cyan(item.token_symbol || '???'),
285
+ formatFlow(item.net_flow_1h_usd),
286
+ formatFlow(item.net_flow_24h_usd),
287
+ formatFlow(item.net_flow_7d_usd),
288
+ chalk.grey(item.token_sectors?.[0] || '—'),
289
+ ]);
290
+ });
291
+
292
+ console.log(gradient.atlas('─── Smart Money Netflow Explorer ────────────────'));
293
+ console.log(table.toString());
294
+ console.log(chalk.grey(`\n * Flows in USD (k = thousands). Positive = Accumulation, Negative = Distribution.`));
295
+ console.log('');
296
+ } catch (err) {
297
+ console.error(chalk.red('Flow exploration failed:'), err.response?.data?.error || err.message);
298
+ }
299
+ });
300
+
301
+ // ─────────────────────────────────────────────────────────────────────────────
302
+ // HISTORY COMMAND (Smart Money Historical Analysis)
303
+ // ─────────────────────────────────────────────────────────────────────────────
304
+ program
305
+ .command('history <symbol>')
306
+ .description('Analyze historical Smart Money conviction for a token')
307
+ .option('--from <date>', 'Start date (YYYY-MM-DD)', '')
308
+ .option('--to <date>', 'End date (YYYY-MM-DD)', '')
309
+ .option('--chains <list>', 'Comma-separated chains', 'solana')
310
+ .action(async (symbol, options) => {
311
+ const token = checkAuth();
312
+ const axios = require('axios');
313
+
314
+ console.log(chalk.cyan(`\nšŸ” Analyzing historical Smart Money conviction for ${chalk.bold(symbol.toUpperCase())}...`));
315
+
316
+ try {
317
+ const { data } = await axios.get(`${BACKEND_URL}/market/smart-money/historical-holdings`, {
318
+ params: {
319
+ symbol,
320
+ from: options.from,
321
+ to: options.to,
322
+ chains: options.chains
323
+ },
324
+ headers: authHeaders(token)
325
+ });
326
+
327
+ const items = data.history || [];
328
+
329
+ if (!items.length) {
330
+ console.log(chalk.yellow(` No historical data found for ${symbol}.\n`));
331
+ return;
332
+ }
333
+
334
+ // Display Conviction Score
335
+ const scoreColor = data.convictionScore === 'HIGH' ? chalk.green : data.convictionScore === 'MEDIUM' ? chalk.yellow : chalk.red;
336
+ console.log(`\n šŸŽÆ Conviction Score: ${scoreColor.bold(data.convictionScore)}`);
337
+ console.log(chalk.grey(` (${data.consecutiveDays} consecutive days of accumulation)\n`));
338
+
339
+ const table = new Table({
340
+ head: [
341
+ chalk.bold.white('Date'),
342
+ chalk.bold.white('SM Balance'),
343
+ chalk.bold.white('24H Change'),
344
+ chalk.bold.white('USD Value'),
345
+ ],
346
+ colWidths: [14, 18, 16, 18],
347
+ style: { border: ['grey'] },
348
+ });
349
+
350
+ items.slice(0, 15).forEach((day) => {
351
+ const change = day.balance_24h_percent_change;
352
+ const changeColor = change >= 0 ? chalk.green : chalk.red;
353
+ const arrow = change >= 0 ? 'ā–²' : 'ā–¼';
354
+
355
+ table.push([
356
+ chalk.white(day.date),
357
+ chalk.cyan(day.balance?.toLocaleString()),
358
+ changeColor(`${arrow} ${(change * 100).toFixed(2)}%`),
359
+ chalk.white(`$${(day.value_usd / 1e3).toFixed(1)}k`),
360
+ ]);
361
+ });
362
+
363
+ console.log(gradient.atlas(`─── Historical Trend: ${symbol.toUpperCase()} ──────────────`));
364
+ console.log(table.toString());
365
+ console.log(chalk.grey(`\n * Showing the latest 15 snapshots. Historical data up to 4 years available.`));
366
+ console.log('');
367
+ } catch (err) {
368
+ console.error(chalk.red('Historical analysis failed:'), err.response?.data?.error || err.message);
369
+ }
370
+ });
371
+
214
372
  // ─────────────────────────────────────────────────────────────────────────────
215
373
  // ENTITY COMMAND
216
374
  // ─────────────────────────────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alpha-cli-toolkit",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Autonomous Agent Toolkit for Crypto & TradFi market data powered by Nansen.",
5
5
  "main": "index.js",
6
6
  "scripts": {