@clawdvault/cli 0.1.2 → 0.1.3

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 (3) hide show
  1. package/README.md +48 -0
  2. package/dist/index.js +362 -4
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -160,6 +160,54 @@ Examples:
160
160
  clawdvault trade quote -m TOKEN_MINT -t buy -a 0.1
161
161
  ```
162
162
 
163
+ ### `clawdvault stream`
164
+
165
+ Real-time data streaming (live trades, prices, chat).
166
+
167
+ ```bash
168
+ # Stream live trades
169
+ clawdvault stream trades [options]
170
+ -m, --mint <address> Token mint address (required)
171
+ --json Output as JSON (one object per line)
172
+ --append Append mode (simple log format)
173
+
174
+ # Stream token price updates
175
+ clawdvault stream token [options]
176
+ -m, --mint <address> Token mint address (required)
177
+ --json Output as JSON
178
+
179
+ # Stream chat messages
180
+ clawdvault stream chat [options]
181
+ -m, --mint <address> Token mint address (required)
182
+ --json Output as JSON
183
+
184
+ Examples:
185
+ # Watch trades in real-time (table mode)
186
+ clawdvault stream trades -m TOKEN_MINT
187
+
188
+ # Watch trades for scripting (JSON output)
189
+ clawdvault stream trades -m TOKEN_MINT --json
190
+
191
+ # Log trades to file
192
+ clawdvault stream trades -m TOKEN_MINT --append >> trades.log
193
+
194
+ # Monitor price changes
195
+ clawdvault stream token -m TOKEN_MINT
196
+
197
+ # Watch chat
198
+ clawdvault stream chat -m TOKEN_MINT
199
+
200
+ # Pipe to jq for filtering
201
+ clawdvault stream trades -m TOKEN_MINT --json | jq 'select(.type == "buy")'
202
+ ```
203
+
204
+ **Features:**
205
+ - Auto-reconnect on connection loss
206
+ - Graceful shutdown with Ctrl+C
207
+ - Multiple output modes: table (default), append, JSON
208
+ - Table mode clears and updates in-place
209
+ - JSON mode outputs one object per line (great for piping)
210
+
163
211
  ### `clawdvault wallet`
164
212
 
165
213
  Wallet management and info.
package/dist/index.js CHANGED
@@ -24,8 +24,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_commander5 = require("commander");
28
- var import_chalk6 = __toESM(require("chalk"));
27
+ var import_commander6 = require("commander");
28
+ var import_chalk7 = __toESM(require("chalk"));
29
29
 
30
30
  // src/commands/tokens.ts
31
31
  var import_commander = require("commander");
@@ -223,6 +223,7 @@ var import_commander2 = require("commander");
223
223
  var import_chalk3 = __toESM(require("chalk"));
224
224
  var import_cli_table32 = __toESM(require("cli-table3"));
225
225
  var fs2 = __toESM(require("fs"));
226
+ var import_sdk3 = require("@clawdvault/sdk");
226
227
  var tokenCommand = new import_commander2.Command("token").description("Token operations");
227
228
  tokenCommand.command("get <mint>").description("Get token details").option("--json", "Output as JSON").action(async (mint, options) => {
228
229
  const spin = spinner("Fetching token...").start();
@@ -411,11 +412,86 @@ tokenCommand.command("holders <mint>").description("Get top token holders").opti
411
412
  handleError(err);
412
413
  }
413
414
  });
415
+ tokenCommand.command("watch <mint>").description("Watch token price in real-time").option("--json", "Output as JSON").action(async (mint, options) => {
416
+ const baseUrl = process.env.CLAWDVAULT_API_URL || "https://clawdvault.com/api";
417
+ console.log(import_chalk3.default.bold(`
418
+ \u{1F4C8} Watching ${shortenAddress(mint)}
419
+ `));
420
+ info(`Connecting to ${baseUrl}...`);
421
+ console.log(import_chalk3.default.dim("Press Ctrl+C to stop\n"));
422
+ const streaming = (0, import_sdk3.createStreaming)(baseUrl);
423
+ const conn = streaming.streamToken(mint);
424
+ const client = createReadOnlyClient();
425
+ let solPrice = 0;
426
+ try {
427
+ const { price } = await client.getSolPrice();
428
+ solPrice = price;
429
+ } catch {
430
+ }
431
+ let tokenInfo = {};
432
+ let lastUpdate = null;
433
+ const displayUpdate = (update) => {
434
+ if (options.json) {
435
+ console.log(JSON.stringify({ ...update, ...tokenInfo }));
436
+ return;
437
+ }
438
+ console.clear();
439
+ console.log(import_chalk3.default.bold(`
440
+ \u{1F4C8} ${tokenInfo.name || "Token"} (${tokenInfo.symbol || shortenAddress(mint)})
441
+ `));
442
+ const table = new import_cli_table32.default({
443
+ style: { head: [], border: [] }
444
+ });
445
+ const priceUsd = solPrice > 0 ? formatUsd(update.price_sol * solPrice) : "-";
446
+ const mcapUsd = solPrice > 0 ? formatUsd(update.market_cap_sol * solPrice) : "-";
447
+ table.push(
448
+ { [import_chalk3.default.cyan("Price (SOL)")]: formatSol(update.price_sol) },
449
+ { [import_chalk3.default.cyan("Price (USD)")]: priceUsd },
450
+ { [import_chalk3.default.cyan("Market Cap (SOL)")]: formatSol(update.market_cap_sol) },
451
+ { [import_chalk3.default.cyan("Market Cap (USD)")]: mcapUsd },
452
+ { [import_chalk3.default.cyan("Bonding Curve SOL")]: formatSol(update.real_sol_reserves) },
453
+ { [import_chalk3.default.cyan("Status")]: update.graduated ? import_chalk3.default.green("\u2713 Graduated") : import_chalk3.default.yellow("Bonding Curve") }
454
+ );
455
+ console.log(table.toString());
456
+ if (lastUpdate && lastUpdate.price_sol !== update.price_sol) {
457
+ const change = (update.price_sol - lastUpdate.price_sol) / lastUpdate.price_sol * 100;
458
+ const changeStr = change >= 0 ? import_chalk3.default.green(`+${change.toFixed(2)}%`) : import_chalk3.default.red(`${change.toFixed(2)}%`);
459
+ console.log(`
460
+ ${import_chalk3.default.dim("Last change:")} ${changeStr}`);
461
+ }
462
+ console.log(import_chalk3.default.dim("\nLast update: " + new Date(update.timestamp).toLocaleTimeString()));
463
+ console.log(import_chalk3.default.dim("Press Ctrl+C to stop"));
464
+ lastUpdate = update;
465
+ };
466
+ conn.onConnect(() => success("Connected to stream"));
467
+ conn.onDisconnect(() => warn("Disconnected - reconnecting..."));
468
+ conn.on("connected", (data) => {
469
+ tokenInfo = { name: data.name, symbol: data.symbol };
470
+ displayUpdate(data);
471
+ });
472
+ conn.on("update", displayUpdate);
473
+ conn.on("trade", (trade) => {
474
+ if (lastUpdate) {
475
+ lastUpdate.price_sol = trade.price_sol;
476
+ displayUpdate(lastUpdate);
477
+ }
478
+ });
479
+ conn.connect();
480
+ process.on("SIGINT", () => {
481
+ console.log("\n");
482
+ info("Disconnecting...");
483
+ streaming.disconnectAll();
484
+ process.exit(0);
485
+ });
486
+ await new Promise(() => {
487
+ });
488
+ });
414
489
 
415
490
  // src/commands/trade.ts
416
491
  var import_commander3 = require("commander");
417
492
  var import_chalk4 = __toESM(require("chalk"));
418
493
  var import_cli_table33 = __toESM(require("cli-table3"));
494
+ var import_sdk4 = require("@clawdvault/sdk");
419
495
  var tradeCommand = new import_commander3.Command("trade").description("Trading operations");
420
496
  tradeCommand.command("buy").description("Buy tokens").requiredOption("-m, --mint <address>", "Token mint address").requiredOption("-a, --sol <amount>", "Amount of SOL to spend").option("-s, --slippage <percent>", "Slippage tolerance (default: 1%)", "1").option("-w, --wallet <path>", "Wallet file path").option("--simulate", "Only simulate, don't execute").action(async (options) => {
421
497
  const { client, signer, walletAddress } = createClientWithWallet(options.wallet);
@@ -630,6 +706,78 @@ tradeCommand.command("history").description("Get trade history for a token").req
630
706
  handleError(err);
631
707
  }
632
708
  });
709
+ tradeCommand.command("stream").description("Stream trades in real-time").requiredOption("-m, --mint <address>", "Token mint address").option("--json", "Output as JSON (one object per line)").option("--append", "Append mode (simple log format)").action(async (options) => {
710
+ const baseUrl = process.env.CLAWDVAULT_API_URL || "https://clawdvault.com/api";
711
+ console.log(import_chalk4.default.bold(`
712
+ \u{1F4E1} Streaming trades for ${shortenAddress(options.mint)}
713
+ `));
714
+ info(`Connecting to ${baseUrl}...`);
715
+ console.log(import_chalk4.default.dim("Press Ctrl+C to stop\n"));
716
+ const streaming = (0, import_sdk4.createStreaming)(baseUrl);
717
+ const conn = streaming.streamTrades(options.mint);
718
+ const trades = [];
719
+ const MAX_DISPLAY = 20;
720
+ conn.onConnect(() => {
721
+ success("Connected to stream");
722
+ console.log();
723
+ });
724
+ conn.onDisconnect(() => warn("Disconnected - reconnecting..."));
725
+ conn.on("trade", (trade) => {
726
+ if (options.json) {
727
+ console.log(JSON.stringify(trade));
728
+ return;
729
+ }
730
+ if (options.append) {
731
+ const typeStr = trade.type === "buy" ? import_chalk4.default.green("BUY ") : import_chalk4.default.red("SELL");
732
+ const time = new Date(trade.created_at).toLocaleTimeString();
733
+ console.log(
734
+ `${import_chalk4.default.dim(time)} ${typeStr} ${formatSol(trade.sol_amount).padEnd(15)} ${formatTokens(trade.token_amount).padEnd(12)} @ ${formatSol(trade.price_sol).padEnd(18)} ${import_chalk4.default.dim(shortenAddress(trade.trader))}`
735
+ );
736
+ return;
737
+ }
738
+ trades.unshift(trade);
739
+ if (trades.length > MAX_DISPLAY) {
740
+ trades.pop();
741
+ }
742
+ console.clear();
743
+ console.log(import_chalk4.default.bold(`
744
+ \u{1F4E1} Live Trades - ${shortenAddress(options.mint)}
745
+ `));
746
+ const table = new import_cli_table33.default({
747
+ head: [
748
+ import_chalk4.default.cyan("Type"),
749
+ import_chalk4.default.cyan("SOL"),
750
+ import_chalk4.default.cyan("Tokens"),
751
+ import_chalk4.default.cyan("Price"),
752
+ import_chalk4.default.cyan("Trader"),
753
+ import_chalk4.default.cyan("Time")
754
+ ],
755
+ style: { head: [], border: [] }
756
+ });
757
+ for (const t of trades) {
758
+ const typeStr = t.type === "buy" ? import_chalk4.default.green("BUY") : import_chalk4.default.red("SELL");
759
+ table.push([
760
+ typeStr,
761
+ formatSol(t.sol_amount),
762
+ formatTokens(t.token_amount),
763
+ formatSol(t.price_sol),
764
+ shortenAddress(t.trader),
765
+ new Date(t.created_at).toLocaleTimeString()
766
+ ]);
767
+ }
768
+ console.log(table.toString());
769
+ console.log(import_chalk4.default.dim("\nPress Ctrl+C to stop"));
770
+ });
771
+ conn.connect();
772
+ process.on("SIGINT", () => {
773
+ console.log("\n");
774
+ info("Disconnecting...");
775
+ streaming.disconnectAll();
776
+ process.exit(0);
777
+ });
778
+ await new Promise(() => {
779
+ });
780
+ });
633
781
 
634
782
  // src/commands/wallet.ts
635
783
  var import_commander4 = require("commander");
@@ -1007,18 +1155,228 @@ walletCommand.command("airdrop").description("Request SOL from devnet faucet (de
1007
1155
  }
1008
1156
  });
1009
1157
 
1158
+ // src/commands/stream.ts
1159
+ var import_commander5 = require("commander");
1160
+ var import_chalk6 = __toESM(require("chalk"));
1161
+ var import_cli_table35 = __toESM(require("cli-table3"));
1162
+ var import_sdk5 = require("@clawdvault/sdk");
1163
+ function getBaseUrl2() {
1164
+ return process.env.CLAWDVAULT_API_URL || "https://clawdvault.com/api";
1165
+ }
1166
+ var streamCommand = new import_commander5.Command("stream").description("Real-time streaming commands");
1167
+ streamCommand.command("trades").description("Stream real-time trades for a token").requiredOption("-m, --mint <address>", "Token mint address").option("--json", "Output as JSON (one object per line)").option("--append", "Append mode instead of table (good for logging)").action(async (options) => {
1168
+ const baseUrl = getBaseUrl2();
1169
+ console.log(import_chalk6.default.bold(`
1170
+ \u{1F4E1} Streaming trades for ${shortenAddress(options.mint)}
1171
+ `));
1172
+ info(`Connecting to ${baseUrl}...`);
1173
+ console.log(import_chalk6.default.dim("Press Ctrl+C to stop\n"));
1174
+ const streaming = (0, import_sdk5.createStreaming)(baseUrl, {
1175
+ autoReconnect: true,
1176
+ reconnectDelay: 3e3
1177
+ });
1178
+ const conn = streaming.streamTrades(options.mint);
1179
+ const trades = [];
1180
+ const MAX_DISPLAY = 20;
1181
+ conn.onConnect(() => {
1182
+ success("Connected to stream");
1183
+ console.log();
1184
+ });
1185
+ conn.onDisconnect(() => {
1186
+ warn("Disconnected - reconnecting...");
1187
+ });
1188
+ conn.onError((err) => {
1189
+ if (!err.message.includes("Max reconnect")) {
1190
+ } else {
1191
+ console.error(import_chalk6.default.red(`Error: ${err.message}`));
1192
+ process.exit(1);
1193
+ }
1194
+ });
1195
+ conn.on("trade", (trade) => {
1196
+ if (options.json) {
1197
+ console.log(JSON.stringify(trade));
1198
+ return;
1199
+ }
1200
+ if (options.append) {
1201
+ const typeStr = trade.type === "buy" ? import_chalk6.default.green("BUY ") : import_chalk6.default.red("SELL");
1202
+ const time = new Date(trade.created_at).toLocaleTimeString();
1203
+ console.log(
1204
+ `${import_chalk6.default.dim(time)} ${typeStr} ${formatSol(trade.sol_amount).padEnd(15)} ${formatTokens(trade.token_amount).padEnd(12)} @ ${formatSol(trade.price_sol).padEnd(18)} ${import_chalk6.default.dim(shortenAddress(trade.trader))}`
1205
+ );
1206
+ return;
1207
+ }
1208
+ trades.unshift(trade);
1209
+ if (trades.length > MAX_DISPLAY) {
1210
+ trades.pop();
1211
+ }
1212
+ console.clear();
1213
+ console.log(import_chalk6.default.bold(`
1214
+ \u{1F4E1} Live Trades - ${shortenAddress(options.mint)}
1215
+ `));
1216
+ const table = new import_cli_table35.default({
1217
+ head: [
1218
+ import_chalk6.default.cyan("Type"),
1219
+ import_chalk6.default.cyan("SOL"),
1220
+ import_chalk6.default.cyan("Tokens"),
1221
+ import_chalk6.default.cyan("Price"),
1222
+ import_chalk6.default.cyan("Trader"),
1223
+ import_chalk6.default.cyan("Time")
1224
+ ],
1225
+ style: { head: [], border: [] }
1226
+ });
1227
+ for (const t of trades) {
1228
+ const typeStr = t.type === "buy" ? import_chalk6.default.green("BUY") : import_chalk6.default.red("SELL");
1229
+ table.push([
1230
+ typeStr,
1231
+ formatSol(t.sol_amount),
1232
+ formatTokens(t.token_amount),
1233
+ formatSol(t.price_sol),
1234
+ shortenAddress(t.trader),
1235
+ new Date(t.created_at).toLocaleTimeString()
1236
+ ]);
1237
+ }
1238
+ console.log(table.toString());
1239
+ console.log(import_chalk6.default.dim("\nPress Ctrl+C to stop"));
1240
+ });
1241
+ conn.connect();
1242
+ process.on("SIGINT", () => {
1243
+ console.log("\n");
1244
+ info("Disconnecting...");
1245
+ streaming.disconnectAll();
1246
+ process.exit(0);
1247
+ });
1248
+ await new Promise(() => {
1249
+ });
1250
+ });
1251
+ streamCommand.command("token").description("Stream real-time token updates (price, market cap)").requiredOption("-m, --mint <address>", "Token mint address").option("--json", "Output as JSON (one object per line)").action(async (options) => {
1252
+ const baseUrl = getBaseUrl2();
1253
+ console.log(import_chalk6.default.bold(`
1254
+ \u{1F4C8} Watching token ${shortenAddress(options.mint)}
1255
+ `));
1256
+ info(`Connecting to ${baseUrl}...`);
1257
+ console.log(import_chalk6.default.dim("Press Ctrl+C to stop\n"));
1258
+ const streaming = (0, import_sdk5.createStreaming)(baseUrl);
1259
+ const conn = streaming.streamToken(options.mint);
1260
+ const client = createReadOnlyClient();
1261
+ let solPrice = 0;
1262
+ try {
1263
+ const { price } = await client.getSolPrice();
1264
+ solPrice = price;
1265
+ } catch {
1266
+ }
1267
+ let tokenInfo = {};
1268
+ let lastUpdate = null;
1269
+ const displayUpdate = (update) => {
1270
+ if (options.json) {
1271
+ console.log(JSON.stringify({ ...update, ...tokenInfo }));
1272
+ return;
1273
+ }
1274
+ console.clear();
1275
+ console.log(import_chalk6.default.bold(`
1276
+ \u{1F4C8} ${tokenInfo.name || "Token"} (${tokenInfo.symbol || shortenAddress(options.mint)})
1277
+ `));
1278
+ const table = new import_cli_table35.default({
1279
+ style: { head: [], border: [] }
1280
+ });
1281
+ const priceUsd = solPrice > 0 ? formatUsd(update.price_sol * solPrice) : "-";
1282
+ const mcapUsd = solPrice > 0 ? formatUsd(update.market_cap_sol * solPrice) : "-";
1283
+ table.push(
1284
+ { [import_chalk6.default.cyan("Price (SOL)")]: formatSol(update.price_sol) },
1285
+ { [import_chalk6.default.cyan("Price (USD)")]: priceUsd },
1286
+ { [import_chalk6.default.cyan("Market Cap (SOL)")]: formatSol(update.market_cap_sol) },
1287
+ { [import_chalk6.default.cyan("Market Cap (USD)")]: mcapUsd },
1288
+ { [import_chalk6.default.cyan("Bonding Curve SOL")]: formatSol(update.real_sol_reserves) },
1289
+ { [import_chalk6.default.cyan("Status")]: update.graduated ? import_chalk6.default.green("\u2713 Graduated") : import_chalk6.default.yellow("Bonding Curve") }
1290
+ );
1291
+ console.log(table.toString());
1292
+ if (lastUpdate && lastUpdate.price_sol !== update.price_sol) {
1293
+ const change = (update.price_sol - lastUpdate.price_sol) / lastUpdate.price_sol * 100;
1294
+ const changeStr = change >= 0 ? import_chalk6.default.green(`+${change.toFixed(2)}%`) : import_chalk6.default.red(`${change.toFixed(2)}%`);
1295
+ console.log(`
1296
+ ${import_chalk6.default.dim("Last change:")} ${changeStr}`);
1297
+ }
1298
+ console.log(import_chalk6.default.dim("\nLast update: " + new Date(update.timestamp).toLocaleTimeString()));
1299
+ console.log(import_chalk6.default.dim("Press Ctrl+C to stop"));
1300
+ lastUpdate = update;
1301
+ };
1302
+ conn.onConnect(() => {
1303
+ success("Connected to stream");
1304
+ });
1305
+ conn.onDisconnect(() => {
1306
+ warn("Disconnected - reconnecting...");
1307
+ });
1308
+ conn.on("connected", (data) => {
1309
+ tokenInfo = { name: data.name, symbol: data.symbol };
1310
+ displayUpdate(data);
1311
+ });
1312
+ conn.on("update", displayUpdate);
1313
+ conn.on("trade", (trade) => {
1314
+ if (lastUpdate) {
1315
+ lastUpdate.price_sol = trade.price_sol;
1316
+ displayUpdate(lastUpdate);
1317
+ }
1318
+ });
1319
+ conn.connect();
1320
+ process.on("SIGINT", () => {
1321
+ console.log("\n");
1322
+ info("Disconnecting...");
1323
+ streaming.disconnectAll();
1324
+ process.exit(0);
1325
+ });
1326
+ await new Promise(() => {
1327
+ });
1328
+ });
1329
+ streamCommand.command("chat").description("Stream real-time chat messages for a token").requiredOption("-m, --mint <address>", "Token mint address").option("--json", "Output as JSON (one object per line)").action(async (options) => {
1330
+ const baseUrl = getBaseUrl2();
1331
+ console.log(import_chalk6.default.bold(`
1332
+ \u{1F4AC} Streaming chat for ${shortenAddress(options.mint)}
1333
+ `));
1334
+ info(`Connecting to ${baseUrl}...`);
1335
+ console.log(import_chalk6.default.dim("Press Ctrl+C to stop\n"));
1336
+ const streaming = (0, import_sdk5.createStreaming)(baseUrl);
1337
+ const conn = streaming.streamChat(options.mint);
1338
+ conn.onConnect(() => {
1339
+ success("Connected to stream");
1340
+ console.log();
1341
+ });
1342
+ conn.onDisconnect(() => {
1343
+ warn("Disconnected - reconnecting...");
1344
+ });
1345
+ conn.on("message", (msg) => {
1346
+ if (options.json) {
1347
+ console.log(JSON.stringify(msg));
1348
+ return;
1349
+ }
1350
+ const time = new Date(msg.created_at).toLocaleTimeString();
1351
+ const sender = msg.username || shortenAddress(msg.wallet);
1352
+ console.log(
1353
+ `${import_chalk6.default.dim(time)} ${import_chalk6.default.cyan(sender)}: ${msg.message}`
1354
+ );
1355
+ });
1356
+ conn.connect();
1357
+ process.on("SIGINT", () => {
1358
+ console.log("\n");
1359
+ info("Disconnecting...");
1360
+ streaming.disconnectAll();
1361
+ process.exit(0);
1362
+ });
1363
+ await new Promise(() => {
1364
+ });
1365
+ });
1366
+
1010
1367
  // src/index.ts
1011
- var program = new import_commander5.Command();
1368
+ var program = new import_commander6.Command();
1012
1369
  program.name("clawdvault").description("CLI for ClawdVault - Solana token launchpad").version("0.1.0");
1013
1370
  program.addCommand(tokensCommand);
1014
1371
  program.addCommand(tokenCommand);
1015
1372
  program.addCommand(tradeCommand);
1016
1373
  program.addCommand(walletCommand);
1374
+ program.addCommand(streamCommand);
1017
1375
  program.hook("preAction", () => {
1018
1376
  });
1019
1377
  program.configureOutput({
1020
1378
  outputError: (str, write) => {
1021
- write(import_chalk6.default.red(str));
1379
+ write(import_chalk7.default.red(str));
1022
1380
  }
1023
1381
  });
1024
1382
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdvault/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "CLI for ClawdVault - Solana token launchpad",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -15,7 +15,7 @@
15
15
  "clean": "rm -rf dist"
16
16
  },
17
17
  "dependencies": {
18
- "@clawdvault/sdk": "^0.1.2",
18
+ "@clawdvault/sdk": "^0.1.3",
19
19
  "@solana/spl-token": "^0.4.0",
20
20
  "@solana/web3.js": "^1.91.0",
21
21
  "bs58": "^5.0.0",