httpcat-cli 0.0.19 → 0.0.21

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.
@@ -23,7 +23,8 @@
23
23
  "Bash(gh pr list:*)",
24
24
  "Bash(gh pr view:*)",
25
25
  "Bash(gh pr diff:*)",
26
- "Bash(gh pr merge:*)"
26
+ "Bash(gh pr merge:*)",
27
+ "Bash(cat:*)"
27
28
  ],
28
29
  "deny": [],
29
30
  "ask": []
package/README.md CHANGED
@@ -129,6 +129,7 @@ Available Commands:
129
129
  sell <id|name|symbol> <amount|all> Sell tokens
130
130
  info <id|name|symbol> Get token information
131
131
  list [--sort mcap|created] List all tokens
132
+ positions Get all your positions with comprehensive info
132
133
  chat [token] Start streaming chat (optional: token symbol/name/address)
133
134
  balance Check wallet balance (ETH and USDC)
134
135
  health Check agent health
@@ -322,6 +323,42 @@ httpcat list --page 3 --sort name
322
323
 
323
324
  **Cost:** $0.0001 USDC
324
325
 
326
+ ### Positions
327
+
328
+ Get all your positions with comprehensive information including current value, profit/loss, ROI, transaction history, and portfolio summary.
329
+
330
+ **Interactive:**
331
+
332
+ ```bash
333
+ httpcat> positions
334
+ ```
335
+
336
+ **CLI:**
337
+
338
+ ```bash
339
+ httpcat positions
340
+ httpcat --json positions
341
+ httpcat --private-key 0x... positions
342
+ ```
343
+
344
+ **Output:**
345
+
346
+ For each position:
347
+ - Token information (name, symbol, address, status, price, market cap, graduation progress)
348
+ - Position details (tokens owned, USDC invested, current value, average cost per token)
349
+ - Performance metrics (profit/loss in USDC and percentage ROI)
350
+ - Position age (days, hours, minutes, seconds since first purchase)
351
+ - Transaction history (total transaction count, last transaction date)
352
+ - Timestamps (position created and updated dates)
353
+
354
+ Portfolio summary:
355
+ - Total positions count
356
+ - Total portfolio value
357
+ - Total amount invested
358
+ - Total profit/loss and overall ROI percentage
359
+
360
+ **Cost:** $0.01 USDC
361
+
325
362
  ### Check Balance
326
363
 
327
364
  Check your wallet's ETH and USDC balances.
@@ -623,6 +660,51 @@ All commands with `--json` flag return structured JSON responses. The output fol
623
660
  }
624
661
  ```
625
662
 
663
+ **Positions (`positions`)**
664
+
665
+ ```json
666
+ {
667
+ "positions": [
668
+ {
669
+ "tokenId": "uuid-string",
670
+ "tokensOwned": "50000",
671
+ "usdcInvested": "5000000",
672
+ "currentValue": "10000000",
673
+ "pnl": "5000000",
674
+ "pnlPercentage": 100.0,
675
+ "averageCostPerToken": "0.0001",
676
+ "positionAge": {
677
+ "days": 2,
678
+ "hours": 5,
679
+ "minutes": 30,
680
+ "seconds": 15
681
+ },
682
+ "createdAt": "2025-11-22T10:30:00.000Z",
683
+ "updatedAt": "2025-11-24T15:30:00.000Z",
684
+ "lastTransactionDate": "2025-11-24T15:30:00.000Z",
685
+ "transactionCount": 3,
686
+ "token": {
687
+ "name": "Token Name",
688
+ "symbol": "SYMBOL",
689
+ "address": "0x...",
690
+ "status": "active",
691
+ "price": "0.0002",
692
+ "mcap": "200000",
693
+ "graduationProgress": 0.15
694
+ }
695
+ }
696
+ ],
697
+ "total": 1,
698
+ "summary": {
699
+ "totalPositions": 1,
700
+ "totalValue": "10000000",
701
+ "totalInvested": "5000000",
702
+ "totalPnl": "5000000",
703
+ "totalPnlPercentage": 100.0
704
+ }
705
+ }
706
+ ```
707
+
626
708
  **Health Check (`health`)**
627
709
 
628
710
  ```json
@@ -857,6 +939,23 @@ List all tokens with pagination and sorting.
857
939
 
858
940
  **Cost:** $0.0001 USDC
859
941
 
942
+ #### `positions`
943
+
944
+ Get all your positions with comprehensive information including current value, profit/loss, ROI, transaction history, and portfolio summary.
945
+
946
+ **Parameters:**
947
+
948
+ - `privateKey` (string, optional) - Private key (overrides config/env)
949
+
950
+ **Returns:** All positions for the requesting address with:
951
+ - Position details (tokens owned, USDC invested, current value, average cost)
952
+ - Performance metrics (profit/loss, ROI percentage)
953
+ - Position age and transaction history
954
+ - Token information for each position
955
+ - Portfolio summary (total value, total invested, total P/L, overall ROI)
956
+
957
+ **Cost:** $0.01 USDC
958
+
860
959
  #### `check_balance`
861
960
 
862
961
  Check wallet balance (ETH and USDC).
@@ -1262,6 +1361,9 @@ httpcat buy <tokenId> 5
1262
1361
  # Check your position
1263
1362
  httpcat info <tokenId>
1264
1363
 
1364
+ # Get all your positions with comprehensive info
1365
+ httpcat positions
1366
+
1265
1367
  # Sell half when profitable
1266
1368
  httpcat sell <tokenId> 50%
1267
1369
 
@@ -1 +1 @@
1
- {"version":3,"file":"buy.d.ts","sourceRoot":"","sources":["../../src/commands/buy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAM7C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAKD,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,EAAE,mCAAmC;AACvD,MAAM,EAAE,MAAM,EACd,UAAU,UAAO,EACjB,MAAM,UAAQ,GACb,OAAO,CAAC,cAAc,CAAC,CAuBzB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAkB7D"}
1
+ {"version":3,"file":"buy.d.ts","sourceRoot":"","sources":["../../src/commands/buy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAM7C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,eAAO,MAAM,YAAY,UAA2B,CAAC;AACrD,eAAO,MAAM,YAAY,UAAuB,CAAC;AAEjD,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,EAAE,mCAAmC;AACvD,MAAM,EAAE,MAAM,EACd,UAAU,UAAO,EACjB,MAAM,UAAQ,GACb,OAAO,CAAC,cAAc,CAAC,CAuBzB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAkB7D"}
@@ -2,8 +2,8 @@ import { validateTokenId, validateAmount } from '../utils/validation.js';
2
2
  import { printBox, formatTokenAmount, formatCurrency } from '../utils/formatting.js';
3
3
  import { printSuccess, printGraduationProgress } from '../interactive/art.js';
4
4
  import { resolveTokenId } from '../utils/token-resolver.js';
5
- const TEST_AMOUNTS = ['0.05', '0.10', '0.20'];
6
- const PROD_AMOUNTS = ['50', '100', '200'];
5
+ export const TEST_AMOUNTS = ['0.05', '0.10', '0.20'];
6
+ export const PROD_AMOUNTS = ['50', '100', '200'];
7
7
  export async function buyToken(client, identifier, // Can be token ID, name, or symbol
8
8
  amount, isTestMode = true, silent = false // Suppress resolver output for quiet/JSON mode
9
9
  ) {
@@ -12,12 +12,12 @@ amount, isTestMode = true, silent = false // Suppress resolver output for quiet/
12
12
  // Validate input
13
13
  validateTokenId(tokenId);
14
14
  const validAmounts = isTestMode ? TEST_AMOUNTS : PROD_AMOUNTS;
15
- validateAmount(amount, validAmounts);
16
- const input = { tokenId, amount };
15
+ const normalizedAmount = validateAmount(amount, validAmounts, isTestMode);
16
+ const input = { tokenId, amount: normalizedAmount };
17
17
  // Route to correct entrypoint based on test mode and amount
18
18
  // Test mode: token_buy_0_05, token_buy_0_10, token_buy_0_20
19
19
  // Production mode: token_buy (single entrypoint)
20
- const entrypoint = isTestMode ? `token_buy_${amount.replace('.', '_')}` : 'token_buy';
20
+ const entrypoint = isTestMode ? `token_buy_${normalizedAmount.replace('.', '_')}` : 'token_buy';
21
21
  // Make request
22
22
  const { data } = await client.invoke(entrypoint, input);
23
23
  return data;
@@ -1 +1 @@
1
- {"version":3,"file":"buy.js","sourceRoot":"","sources":["../../src/commands/buy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAkB5D,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAC9C,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAqB,EACrB,UAAkB,EAAE,mCAAmC;AACvD,MAAc,EACd,UAAU,GAAG,IAAI,EACjB,MAAM,GAAG,KAAK,CAAC,+CAA+C;;IAE9D,iCAAiC;IACjC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjE,iBAAiB;IACjB,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC;IAC9D,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAErC,MAAM,KAAK,GAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAEjD,4DAA4D;IAC5D,4DAA4D;IAC5D,iDAAiD;IACjD,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,aAAa,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IAEtF,eAAe;IACf,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAClC,UAAU,EACV,KAAK,CACN,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,YAAY,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAC;IAExD,MAAM,gBAAgB,GAAG,MAAM,CAAC,iBAAiB;QAC/C,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAE/C,QAAQ,CAAC,qBAAqB,EAAE;QAC9B,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,CAAC,cAAc,CAAC;QAC3D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,WAAW,CAAC;QAClD,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC;QACtC,WAAW,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC5C,gBAAgB,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC;QAChD,YAAY,EAAE,gBAAgB;KAC/B,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,uBAAuB,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"buy.js","sourceRoot":"","sources":["../../src/commands/buy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAkB5D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACrD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAqB,EACrB,UAAkB,EAAE,mCAAmC;AACvD,MAAc,EACd,UAAU,GAAG,IAAI,EACjB,MAAM,GAAG,KAAK,CAAC,+CAA+C;;IAE9D,iCAAiC;IACjC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjE,iBAAiB;IACjB,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC;IAC9D,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IAE1E,MAAM,KAAK,GAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAEnE,4DAA4D;IAC5D,4DAA4D;IAC5D,iDAAiD;IACjD,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,aAAa,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IAEhG,eAAe;IACf,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAClC,UAAU,EACV,KAAK,CACN,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,YAAY,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAC;IAExD,MAAM,gBAAgB,GAAG,MAAM,CAAC,iBAAiB;QAC/C,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAE/C,QAAQ,CAAC,qBAAqB,EAAE;QAC9B,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,CAAC,cAAc,CAAC;QAC3D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,WAAW,CAAC;QAClD,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC;QACtC,WAAW,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC5C,gBAAgB,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC;QAChD,YAAY,EAAE,gBAAgB;KAC/B,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,uBAAuB,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positions.d.ts","sourceRoot":"","sources":["../../src/commands/positions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,MAAM,WAAW,cAAc;CAE9B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE;QACR,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;CACH;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,eAAe,CAAC,CAU1B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAwJ9D"}
@@ -0,0 +1,136 @@
1
+ import { createTable, formatAddress, formatCurrency, formatTokenAmount } from '../utils/formatting.js';
2
+ import chalk from 'chalk';
3
+ export async function getPositions(client) {
4
+ const input = {};
5
+ // Make request
6
+ const { data } = await client.invoke('positions', input);
7
+ return data;
8
+ }
9
+ export function displayPositions(result) {
10
+ console.log();
11
+ console.log(chalk.cyan.bold(`💼 Your Positions (${result.total} total)`));
12
+ console.log();
13
+ if (result.positions.length === 0) {
14
+ console.log(chalk.yellow('No positions found.'));
15
+ console.log();
16
+ console.log(chalk.dim('💡 Try buying some tokens:'));
17
+ console.log(chalk.dim(' httpcat buy <tokenId> <amount>'));
18
+ console.log(chalk.dim(' httpcat list'));
19
+ console.log();
20
+ return;
21
+ }
22
+ // Display each position
23
+ for (let i = 0; i < result.positions.length; i++) {
24
+ const position = result.positions[i];
25
+ // Position header
26
+ const graduationIcon = position.token.status === 'graduated'
27
+ ? '🎓'
28
+ : position.token.graduationProgress >= 90
29
+ ? '🔥'
30
+ : position.token.graduationProgress >= 50
31
+ ? '📈'
32
+ : '🌱';
33
+ console.log(chalk.bold(`${i + 1}. ${position.token.name} (${position.token.symbol}) ${graduationIcon}`));
34
+ console.log(chalk.dim(` Token ID: ${position.tokenId}`));
35
+ console.log(chalk.dim(` Address: ${formatAddress(position.token.address, 12)}`));
36
+ console.log(chalk.dim(` Status: ${position.token.status}`));
37
+ console.log();
38
+ // Position details table
39
+ const detailsTable = createTable(['Metric', 'Value']);
40
+ detailsTable.push(['Price', formatCurrency(position.token.price)], ['Market Cap', formatCurrency(position.token.mcap)], ['Graduation', `${position.token.graduationProgress.toFixed(2)}%`], ['Tokens Owned', formatTokenAmount(position.tokensOwned)], ['USDC Invested', formatCurrency(position.usdcInvested)]);
41
+ // Add enhanced fields if available
42
+ if (position.currentValue !== undefined) {
43
+ detailsTable.push(['Current Value', formatCurrency(position.currentValue)]);
44
+ }
45
+ if (position.averageCostPerToken !== undefined) {
46
+ detailsTable.push(['Avg Cost/Token', formatCurrency(position.averageCostPerToken)]);
47
+ }
48
+ console.log(detailsTable.toString());
49
+ console.log();
50
+ // Performance section (if available)
51
+ if (position.pnl !== undefined && position.pnlPercentage !== undefined) {
52
+ const pnl = parseFloat(position.pnl) / 1e6;
53
+ const pnlColor = pnl >= 0 ? chalk.green : chalk.red;
54
+ const pnlSign = pnl >= 0 ? '+' : '';
55
+ const pnlIcon = pnl >= 0 ? '🟢' : '🔴';
56
+ console.log(chalk.bold('📈 Performance:'));
57
+ console.log(` ${pnlIcon} P/L: ${pnlColor(`${pnlSign}${formatCurrency(position.pnl)}`)} (${pnlColor(`${pnlSign}${position.pnlPercentage.toFixed(2)}%`)})`);
58
+ console.log();
59
+ }
60
+ // Position age (if available)
61
+ if (position.positionAge) {
62
+ const age = position.positionAge;
63
+ let ageStr = '';
64
+ if (age.days > 0) {
65
+ ageStr = `${age.days} day${age.days !== 1 ? 's' : ''}, ${age.hours} hour${age.hours !== 1 ? 's' : ''}, ${age.minutes} minute${age.minutes !== 1 ? 's' : ''}`;
66
+ }
67
+ else if (age.hours > 0) {
68
+ ageStr = `${age.hours} hour${age.hours !== 1 ? 's' : ''}, ${age.minutes} minute${age.minutes !== 1 ? 's' : ''}, ${age.seconds} second${age.seconds !== 1 ? 's' : ''}`;
69
+ }
70
+ else if (age.minutes > 0) {
71
+ ageStr = `${age.minutes} minute${age.minutes !== 1 ? 's' : ''}, ${age.seconds} second${age.seconds !== 1 ? 's' : ''}`;
72
+ }
73
+ else {
74
+ ageStr = `${age.seconds} second${age.seconds !== 1 ? 's' : ''}`;
75
+ }
76
+ console.log(chalk.bold('⏱️ Position Age:'));
77
+ console.log(` ${ageStr}`);
78
+ console.log();
79
+ }
80
+ // Transaction history (if available)
81
+ if (position.transactionCount !== undefined) {
82
+ console.log(chalk.bold('📝 Transaction History:'));
83
+ console.log(` Total Transactions: ${position.transactionCount}`);
84
+ if (position.lastTransactionDate) {
85
+ const lastTxDate = new Date(position.lastTransactionDate);
86
+ console.log(` Last Transaction: ${lastTxDate.toLocaleString()}`);
87
+ }
88
+ else {
89
+ console.log(` Last Transaction: N/A`);
90
+ }
91
+ console.log();
92
+ }
93
+ // Timestamps
94
+ console.log(chalk.bold('📅 Timestamps:'));
95
+ console.log(` Created: ${new Date(position.createdAt).toLocaleString()}`);
96
+ console.log(` Updated: ${new Date(position.updatedAt).toLocaleString()}`);
97
+ console.log();
98
+ }
99
+ // Display summary if available
100
+ if (result.summary) {
101
+ console.log(chalk.cyan('='.repeat(80)));
102
+ console.log(chalk.cyan.bold('📊 Portfolio Summary'));
103
+ console.log(chalk.cyan('='.repeat(80)));
104
+ console.log();
105
+ const summaryTable = createTable(['Metric', 'Value']);
106
+ summaryTable.push(['Total Positions', result.summary.totalPositions.toString()]);
107
+ if (result.summary.totalInvested !== undefined) {
108
+ summaryTable.push(['Total Invested', formatCurrency(result.summary.totalInvested)]);
109
+ }
110
+ if (result.summary.totalValue !== undefined) {
111
+ summaryTable.push(['Total Value', formatCurrency(result.summary.totalValue)]);
112
+ }
113
+ if (result.summary.totalPnl !== undefined && result.summary.totalPnlPercentage !== undefined) {
114
+ const totalPnl = parseFloat(result.summary.totalPnl) / 1e6;
115
+ const totalPnlColor = totalPnl >= 0 ? chalk.green : chalk.red;
116
+ const totalPnlSign = totalPnl >= 0 ? '+' : '';
117
+ const totalPnlIcon = totalPnl >= 0 ? '🟢' : '🔴';
118
+ summaryTable.push([
119
+ 'Total P/L',
120
+ `${totalPnlIcon} ${totalPnlColor(`${totalPnlSign}${formatCurrency(result.summary.totalPnl)}`)} (${totalPnlColor(`${totalPnlSign}${result.summary.totalPnlPercentage.toFixed(2)}%`)})`
121
+ ]);
122
+ }
123
+ console.log(summaryTable.toString());
124
+ console.log();
125
+ }
126
+ // Show example commands
127
+ if (result.positions.length > 0) {
128
+ const firstPosition = result.positions[0];
129
+ console.log(chalk.dim('💡 Example commands:'));
130
+ console.log(chalk.dim(` httpcat info ${firstPosition.token.symbol}`));
131
+ console.log(chalk.dim(` httpcat sell ${firstPosition.token.symbol} 50%`));
132
+ console.log(chalk.dim(` httpcat buy ${firstPosition.token.symbol} 0.10`));
133
+ console.log();
134
+ }
135
+ }
136
+ //# sourceMappingURL=positions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positions.js","sourceRoot":"","sources":["../../src/commands/positions.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,18 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
3
  import chalk from "chalk";
4
+ import { privateKeyToAccount } from "viem/accounts";
4
5
  import { config } from "./config.js";
5
6
  import { HttpcatClient } from "./client.js";
6
7
  import { handleError, getExitCode } from "./utils/errors.js";
7
8
  import { startInteractiveShell } from "./interactive/shell.js";
8
9
  import { outputJson, outputError } from "./headless/json-output.js";
9
10
  import { promptForPrivateKey } from "./utils/privateKeyPrompt.js";
11
+ import { withLoading } from "./utils/loading.js";
10
12
  // Import commands
11
13
  import { createToken, displayCreateResult } from "./commands/create.js";
12
14
  import { buyToken, displayBuyResult } from "./commands/buy.js";
13
15
  import { sellToken, displaySellResult, parseTokenAmount, } from "./commands/sell.js";
14
16
  import { getTokenInfo, displayTokenInfo } from "./commands/info.js";
15
17
  import { listTokens, displayTokenList } from "./commands/list.js";
18
+ import { getPositions, displayPositions } from "./commands/positions.js";
16
19
  import { checkHealth, displayHealthStatus } from "./commands/health.js";
17
20
  import { checkBalance, displayBalance } from "./commands/balance.js";
18
21
  import { startChatStream } from "./commands/chat.js";
@@ -23,7 +26,7 @@ if (args.includes("--version") || args.includes("-V")) {
23
26
  if (args.includes("--json")) {
24
27
  console.log(JSON.stringify({
25
28
  name: "httpcat-cli",
26
- version: "0.0.19",
29
+ version: "0.0.20",
27
30
  }, null, 2));
28
31
  process.exit(0);
29
32
  }
@@ -32,7 +35,7 @@ const program = new Command();
32
35
  program
33
36
  .name("httpcat")
34
37
  .description("CLI tool for interacting with httpcat agent")
35
- .version("0.0.19")
38
+ .version("0.0.20")
36
39
  .option("--json", "Output in JSON format")
37
40
  .option("--quiet", "Minimal output (exit codes only)")
38
41
  .option("--verbose", "Verbose error messages")
@@ -81,6 +84,7 @@ envCommand
81
84
  if (current) {
82
85
  console.log(chalk.dim(`Current environment: ${chalk.green(current)}`));
83
86
  }
87
+ process.exit(0);
84
88
  }
85
89
  catch (error) {
86
90
  handleError(error, false);
@@ -98,6 +102,7 @@ envCommand
98
102
  console.log(chalk.green(`✅ Switched to environment: ${name}`));
99
103
  console.log(chalk.dim(` Agent URL: ${env?.agentUrl}`));
100
104
  console.log(chalk.dim(` Network: ${env?.network}`));
105
+ process.exit(0);
101
106
  }
102
107
  catch (error) {
103
108
  handleError(error, false);
@@ -112,11 +117,13 @@ envCommand
112
117
  const current = config.getCurrentEnvironment();
113
118
  if (!current) {
114
119
  console.log(chalk.yellow("No environment selected"));
120
+ process.exit(0);
115
121
  return;
116
122
  }
117
123
  const env = config.getEnvironmentConfig(current);
118
124
  if (!env) {
119
125
  console.log(chalk.yellow(`Environment "${current}" not found`));
126
+ process.exit(0);
120
127
  return;
121
128
  }
122
129
  console.log();
@@ -125,6 +132,7 @@ envCommand
125
132
  console.log(chalk.dim(`Agent URL: ${env.agentUrl}`));
126
133
  console.log(chalk.dim(`Network: ${env.network}`));
127
134
  console.log();
135
+ process.exit(0);
128
136
  }
129
137
  catch (error) {
130
138
  handleError(error, false);
@@ -145,6 +153,7 @@ envCommand
145
153
  console.log(chalk.dim(` Network: ${options.network}`));
146
154
  console.log();
147
155
  console.log(chalk.dim(`Switch to it with: httpcat env use ${name}`));
156
+ process.exit(0);
148
157
  }
149
158
  catch (error) {
150
159
  handleError(error, false);
@@ -163,6 +172,7 @@ envCommand
163
172
  console.log(chalk.green(`✅ Updated environment: ${name}`));
164
173
  console.log(chalk.dim(` Agent URL: ${agentUrl}`));
165
174
  console.log(chalk.dim(` Network: ${options.network}`));
175
+ process.exit(0);
166
176
  }
167
177
  catch (error) {
168
178
  handleError(error, false);
@@ -235,12 +245,17 @@ Examples:
235
245
  privateKey = await promptForPrivateKey();
236
246
  }
237
247
  const client = await HttpcatClient.create(privateKey);
238
- const result = await createToken(client, {
248
+ const result = await withLoading(() => createToken(client, {
239
249
  name,
240
250
  symbol,
241
251
  photoUrl: options.photo,
242
252
  bannerUrl: options.banner,
243
253
  websiteUrl: options.website,
254
+ }), {
255
+ message: "Creating token...",
256
+ json: globalOpts.json,
257
+ quiet: globalOpts.quiet,
258
+ spinner: "cat",
244
259
  });
245
260
  if (globalOpts.json) {
246
261
  outputJson("create_token", result);
@@ -291,7 +306,12 @@ Examples:
291
306
  const client = await HttpcatClient.create(privateKey);
292
307
  const isTestMode = client.getNetwork().includes("sepolia");
293
308
  const silent = globalOpts.json || globalOpts.quiet;
294
- const result = await buyToken(client, tokenId, amount, isTestMode, silent);
309
+ const result = await withLoading(() => buyToken(client, tokenId, amount, isTestMode, silent), {
310
+ message: "Buying tokens...",
311
+ json: globalOpts.json,
312
+ quiet: globalOpts.quiet,
313
+ spinner: "cat",
314
+ });
295
315
  if (globalOpts.json) {
296
316
  outputJson("token_buy", result);
297
317
  }
@@ -339,13 +359,26 @@ Examples:
339
359
  }
340
360
  const client = await HttpcatClient.create(privateKey);
341
361
  const silent = globalOpts.json || globalOpts.quiet;
362
+ // Derive user address from private key
363
+ const account = privateKeyToAccount(privateKey);
364
+ const userAddress = account.address;
342
365
  // Get current holdings
343
- const info = await getTokenInfo(client, tokenId, undefined, silent);
366
+ const info = await withLoading(() => getTokenInfo(client, tokenId, userAddress, silent), {
367
+ message: "Checking token info...",
368
+ json: globalOpts.json,
369
+ quiet: globalOpts.quiet,
370
+ spinner: "cat",
371
+ });
344
372
  if (!info.userPosition || info.userPosition.tokensOwned === "0") {
345
373
  throw new Error("You do not own any of this token");
346
374
  }
347
375
  const tokenAmount = parseTokenAmount(amountInput, info.userPosition.tokensOwned);
348
- const result = await sellToken(client, tokenId, tokenAmount, silent);
376
+ const result = await withLoading(() => sellToken(client, tokenId, tokenAmount, silent), {
377
+ message: "Selling tokens...",
378
+ json: globalOpts.json,
379
+ quiet: globalOpts.quiet,
380
+ spinner: "cat",
381
+ });
349
382
  if (globalOpts.json) {
350
383
  outputJson("token_sell", result);
351
384
  }
@@ -392,7 +425,12 @@ Examples:
392
425
  }
393
426
  const client = await HttpcatClient.create(privateKey);
394
427
  const silent = globalOpts.json || globalOpts.quiet;
395
- const result = await getTokenInfo(client, tokenId, undefined, silent);
428
+ const result = await withLoading(() => getTokenInfo(client, tokenId, undefined, silent), {
429
+ message: "Fetching token info...",
430
+ json: globalOpts.json,
431
+ quiet: globalOpts.quiet,
432
+ spinner: "cat",
433
+ });
396
434
  if (globalOpts.json) {
397
435
  outputJson("token_info", result);
398
436
  }
@@ -440,7 +478,12 @@ Examples:
440
478
  privateKey = await promptForPrivateKey();
441
479
  }
442
480
  const client = await HttpcatClient.create(privateKey);
443
- const result = await listTokens(client, parseInt(options.page), parseInt(options.limit), options.sort);
481
+ const result = await withLoading(() => listTokens(client, parseInt(options.page), parseInt(options.limit), options.sort), {
482
+ message: "Fetching token list...",
483
+ json: globalOpts.json,
484
+ quiet: globalOpts.quiet,
485
+ spinner: "cat",
486
+ });
444
487
  if (globalOpts.json) {
445
488
  outputJson("list_tokens", result);
446
489
  }
@@ -460,6 +503,55 @@ Examples:
460
503
  process.exit(getExitCode(error));
461
504
  }
462
505
  });
506
+ // Positions command
507
+ program
508
+ .command("positions")
509
+ .description("Get all your positions with comprehensive information")
510
+ .addHelpText("after", `
511
+ Examples:
512
+ httpcat positions
513
+ httpcat --json positions
514
+ httpcat --private-key 0x... positions
515
+ `)
516
+ .action(async (command) => {
517
+ try {
518
+ const globalOpts = command.parent?.opts() || {};
519
+ let privateKey = getPrivateKey(globalOpts.privateKey);
520
+ // If not configured and not in JSON mode, prompt interactively
521
+ if (!isConfigured(globalOpts.privateKey)) {
522
+ if (globalOpts.json) {
523
+ console.error('❌ Not configured. Run "httpcat config" first or use --private-key flag.');
524
+ process.exit(2);
525
+ }
526
+ // Interactive prompt for private key
527
+ privateKey = await promptForPrivateKey();
528
+ }
529
+ const client = await HttpcatClient.create(privateKey);
530
+ const result = await withLoading(() => getPositions(client), {
531
+ message: "Fetching positions...",
532
+ json: globalOpts.json,
533
+ quiet: globalOpts.quiet,
534
+ spinner: "cat",
535
+ });
536
+ if (globalOpts.json) {
537
+ outputJson("positions", result);
538
+ }
539
+ else if (!globalOpts.quiet) {
540
+ displayPositions(result);
541
+ }
542
+ process.exit(0);
543
+ }
544
+ catch (error) {
545
+ const globalOpts = command.parent?.opts() || {};
546
+ if (globalOpts.json) {
547
+ outputError("positions", error, getExitCode(error));
548
+ }
549
+ else {
550
+ handleError(error, globalOpts.verbose);
551
+ }
552
+ process.exit(getExitCode(error));
553
+ }
554
+ });
463
555
  // Health command
464
556
  program
465
557
  .command("health")
@@ -479,7 +571,12 @@ Examples:
479
571
  process.exit(2);
480
572
  }
481
573
  const client = await HttpcatClient.create(privateKey);
482
- const result = await checkHealth(client);
574
+ const result = await withLoading(() => checkHealth(client), {
575
+ message: "Checking health...",
576
+ json: globalOpts.json,
577
+ quiet: globalOpts.quiet,
578
+ spinner: "cat",
579
+ });
483
580
  if (globalOpts.json) {
484
581
  outputJson("health", result);
485
582
  }
@@ -522,7 +619,12 @@ Examples:
522
619
  // Interactive prompt for private key (handled inside checkBalance)
523
620
  privateKey = undefined;
524
621
  }
525
- const result = await checkBalance(privateKey);
622
+ const result = await withLoading(() => checkBalance(privateKey), {
623
+ message: "Checking balance...",
624
+ json: globalOpts.json,
625
+ quiet: globalOpts.quiet,
626
+ spinner: "cat",
627
+ });
526
628
  if (globalOpts.json) {
527
629
  outputJson("balance", result);
528
630
  }