nansen-cli 1.8.0 → 1.9.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,103 @@
1
+ # Changelog
2
+
3
+ ## 1.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#110](https://github.com/nansen-ai/nansen-cli/pull/110) [`82aa780`](https://github.com/nansen-ai/nansen-cli/commit/82aa78022bdcd62987b0949e090f19f563699d9a) Thanks [@TimNooren](https://github.com/TimNooren)! - Fix `nansen changelog` always showing "CHANGELOG.md not found". Added a `files` field to `package.json` to explicitly bundle `CHANGELOG.md` with the published package. Also excludes `src/__tests__/` from the package, reducing package size from ~537 kB to ~269 kB.
8
+
9
+ ## 1.9.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#98](https://github.com/nansen-ai/nansen-cli/pull/98) [`2f3f556`](https://github.com/nansen-ai/nansen-cli/commit/2f3f556d008a1f8ec40d57a8a2822bedbc6b60cb) Thanks [@Codier](https://github.com/Codier)! - Add symbol shortcuts for common tokens (SOL, ETH, USDC, USDT, etc.) that resolve to canonical addresses per chain. Users can now use `--from SOL --to USDC` instead of raw contract addresses.
14
+
15
+ - [#32](https://github.com/nansen-ai/nansen-cli/pull/32) [`08a8d21`](https://github.com/nansen-ai/nansen-cli/commit/08a8d21be6e9196661be737545e790af180aebc3) Thanks [@arein](https://github.com/arein)! - Add WalletConnect support for trading, transfers, and x402 auto-payment (EVM only)
16
+
17
+ ### Patch Changes
18
+
19
+ - [#99](https://github.com/nansen-ai/nansen-cli/pull/99) [`9144cba`](https://github.com/nansen-ai/nansen-cli/commit/9144cba38b06c90d462df97ea6cbcdeaed26fa36) Thanks [@Codier](https://github.com/Codier)! - Show clear error when `--amount` contains a decimal (e.g. `0.005`) instead of base units (lamports, wei). Detected client-side before hitting the API.
20
+
21
+ - [#100](https://github.com/nansen-ai/nansen-cli/pull/100) [`19559bf`](https://github.com/nansen-ai/nansen-cli/commit/19559bfea6c22f6bd6b8c278ed5e6ae6d64866d5) Thanks [@Codier](https://github.com/Codier)! - Fix `nansen trade help` returning blank output. Now prints subcommands, usage, and examples. Also fixes `errorOutput` ReferenceError in `buildCommands` scope (affected `trade` and `changelog` commands).
22
+
23
+ - [#93](https://github.com/nansen-ai/nansen-cli/pull/93) [`342c91f`](https://github.com/nansen-ai/nansen-cli/commit/342c91fdeb6d98d6b5c10a58cb9702eb5afe096f) Thanks [@Codier](https://github.com/Codier)! - Warn when `--from` is a wrapped native token (WETH/WBNB) or native sentinel, so AI agents can correct the token before execution fails
24
+
25
+ ## 1.8.0
26
+
27
+ ### Minor Changes
28
+
29
+ - [#56](https://github.com/nansen-ai/nansen-cli/pull/56) [`d10998a`](https://github.com/nansen-ai/nansen-cli/commit/d10998aa2be19f80e8476d19bfd46029757a7335) Thanks [@askeluv](https://github.com/askeluv)! - Add CHANGELOG.md, `nansen changelog` command, and post-update "what's new" notice
30
+
31
+ - Added CHANGELOG.md following Keep a Changelog format with history back to v1.5.0
32
+ - Added `nansen changelog` command with `--since <version>` filtering
33
+ - Added one-time upgrade notice on first run after version update (prints to stderr)
34
+
35
+ - [#77](https://github.com/nansen-ai/nansen-cli/pull/77) [`46e4660`](https://github.com/nansen-ai/nansen-cli/commit/46e4660034d9681405d09a5184f78525c300b8a5) Thanks [@0xlaveen](https://github.com/0xlaveen)! - Add token-ohlcv endpoint for OHLCV candle data
36
+
37
+ - [#75](https://github.com/nansen-ai/nansen-cli/pull/75) [`287937e`](https://github.com/nansen-ai/nansen-cli/commit/287937e1d307e0b3f25648863d0c5b4a54d215ff) Thanks [@TimNooren](https://github.com/TimNooren)! - Restructure CLI into research/trade/wallet namespaces
38
+
39
+ - Commands reorganized: `smart-money`, `profiler`, `token`, `portfolio` now live under `nansen research`
40
+ - New `nansen trade` namespace for `quote` and `execute`
41
+ - New `nansen wallet` namespace for wallet management
42
+ - Old top-level commands still work with deprecation warnings
43
+
44
+ - [#61](https://github.com/nansen-ai/nansen-cli/pull/61) [`9af0192`](https://github.com/nansen-ai/nansen-cli/commit/9af01921871be1d0537047cb4ad9733e01876646) Thanks [@askeluv](https://github.com/askeluv)! - Add ENS name resolution for profiler commands. Use `.eth` names directly in `--address` flags — resolved automatically via ensideas API with onchain RPC fallback. Works across all profiler subcommands, batch, and trace operations.
45
+
46
+ All notable changes to the Nansen CLI will be documented in this file.
47
+
48
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
49
+ and this project adheres to [Semantic Versioning](https://semver.org/).
50
+
51
+ ## [1.7.0] - 2026-02-24
52
+
53
+ ### Added
54
+
55
+ - **Trading commands** — `quote` and `execute` for DEX swaps (EVM + Solana)
56
+ - **Wallet management** — `wallet create`, `list`, `show`, `export`, `default`, `delete`
57
+ - **Wallet send** — transfer tokens on EVM and Solana (`wallet send`)
58
+ - **x402 auto-payment** — automatic payment via Base USDC or Solana SPL USDC
59
+ - Explorer links in transaction output
60
+ - `--dry-run` flag for `wallet send`
61
+ - x402 low balance warning
62
+ - AI Agent Access setup docs and improved onboarding flow
63
+
64
+ ### Fixed
65
+
66
+ - Solana execute crash with OKX quotes
67
+ - x402 auto-pay retry path (3 reference errors)
68
+ - Gas estimation — use API `quote.gas` as floor
69
+ - Pre-flight simulation moved after approval (industry standard)
70
+ - EVM signing edge cases with pure JS ECDSA
71
+ - Wallet send crashes on amount parsing and silent success
72
+ - Solana confirmation and SPL token transfer account ordering
73
+ - Suppress duplicate JSON output from quote/execute
74
+ - Suppress approval warning for native ETH swaps
75
+
76
+ ### Changed
77
+
78
+ - Pricing clarity — from $0.01/call, min $0.05 balance
79
+ - Consolidated crypto primitives into shared module
80
+
81
+ ## [1.6.0] - 2026-02-14
82
+
83
+ ### Added
84
+
85
+ - `token indicators` endpoint
86
+ - `profiler search` — general entity search command
87
+ - `--x402-payment-signature` flag for pre-signed payment headers
88
+ - `X-Client-Type` and `X-Client-Version` tracking headers on all API requests
89
+
90
+ ### Fixed
91
+
92
+ - Error JSON now outputs to stdout (not stderr) for consistent agent parsing
93
+ - Config loading — environment variables correctly override file config
94
+
95
+ ## [1.5.1] - 2026-02-07
96
+
97
+ ### Added
98
+
99
+ - Allow API requests without API key when using x402 payment flow
100
+
101
+ ## [1.5.0] - 2026-01-31
102
+
103
+ _Baseline version. Changes above are relative to this release._
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/nansen-cli.svg)](https://www.npmjs.com/package/nansen-cli)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![Tests](https://img.shields.io/badge/tests-577%20passing-brightgreen.svg)]()
5
+ [![CI](https://github.com/nansen-ai/nansen-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/nansen-ai/nansen-cli/actions/workflows/ci.yml)
6
6
 
7
7
  > **Built by agents, for agents.** We prioritize the best possible AI agent experience.
8
8
 
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "nansen-cli",
3
- "version": "1.8.0",
3
+ "version": "1.9.1",
4
4
  "description": "Command-line interface for Nansen API - designed for AI agents",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "nansen": "./src/index.js"
9
9
  },
10
+ "files": [
11
+ "src/*.js",
12
+ "CHANGELOG.md"
13
+ ],
10
14
  "scripts": {
11
15
  "start": "node src/index.js",
12
16
  "pretest": "node scripts/check-changeset.js",
package/src/api.js CHANGED
@@ -505,8 +505,11 @@ export class NansenAPI {
505
505
  } else if (code === ErrorCode.CREDITS_EXHAUSTED) {
506
506
  message = message.replace(/\.+$/, '') + '. No retry will help. Check your Nansen dashboard for credit balance.';
507
507
  } else if (code === ErrorCode.PAYMENT_REQUIRED) {
508
- // Try x402 auto-payment with fallback across payment networks
509
- if (!this.defaultHeaders['Payment-Signature']) {
508
+ // Try x402 auto-payment: local wallet (with network fallback), then WalletConnect
509
+ const hasManualSignature = !!(this.defaultHeaders['Payment-Signature'] || options.headers?.['Payment-Signature']);
510
+
511
+ if (!hasManualSignature) {
512
+ // 1. Try local wallet with fallback across payment networks
510
513
  try {
511
514
  const { createPaymentSignatures } = await import('./x402.js');
512
515
  for await (const { signature, network } of createPaymentSignatures(response, url)) {
@@ -537,17 +540,54 @@ export class NansenAPI {
537
540
  }
538
541
  // This payment option was rejected, try next
539
542
  }
540
- } catch { /* x402 auto-pay unavailable, fall through */ }
541
- }
542
- message = 'Payment required. To access this endpoint:\n • Set an API key: nansen login --api-key <key> (get one at https://app.nansen.ai/api)\n • Or pay per call: nansen wallet create, fund with USDC on Base or Solana (from $0.01/call, min $0.05 balance)\n • Docs: https://docs.x402.org';
543
- const paymentHeader = response.headers.get('payment-required');
544
- if (paymentHeader) {
545
- try {
546
- data.paymentRequirements = JSON.parse(atob(paymentHeader));
547
- } catch {
548
- data.paymentRequiredRaw = paymentHeader;
543
+ } catch { /* local wallet unavailable, try WalletConnect */ }
544
+
545
+ // 2. Fall back to WalletConnect (walletconnect-x402.js)
546
+ // (local wallet returns early on success above, so we always reach here if it failed)
547
+ {
548
+ let paymentRequirements;
549
+ const paymentHeader = response.headers.get('payment-required');
550
+ if (paymentHeader) {
551
+ try {
552
+ paymentRequirements = JSON.parse(atob(paymentHeader));
553
+ } catch {
554
+ data.paymentRequiredRaw = paymentHeader;
555
+ }
556
+ }
557
+ if (!paymentRequirements && data.paymentRequirements) {
558
+ paymentRequirements = data.paymentRequirements;
559
+ }
560
+
561
+ if (paymentRequirements) {
562
+ try {
563
+ const { handleX402Payment } = await import('./walletconnect-x402.js');
564
+ const paymentSignature = await handleX402Payment(paymentRequirements);
565
+ const paidResponse = await fetch(url, {
566
+ method: 'POST',
567
+ headers: {
568
+ 'Content-Type': 'application/json',
569
+ 'X-Client-Type': 'nansen-cli',
570
+ 'X-Client-Version': packageVersion,
571
+ 'Payment-Signature': paymentSignature,
572
+ ...this.defaultHeaders,
573
+ ...options.headers,
574
+ },
575
+ body: JSON.stringify(NansenAPI.cleanBody(body)),
576
+ });
577
+ if (paidResponse.ok) {
578
+ return await paidResponse.json();
579
+ }
580
+ } catch (x402Err) {
581
+ message = `x402 auto-payment failed: ${x402Err.message}`;
582
+ }
583
+ data.paymentRequirements = paymentRequirements;
584
+ }
549
585
  }
550
586
  }
587
+
588
+ if (!message || message === data.message) {
589
+ message = 'Payment required (x402). Sign the paymentRequirements below per https://docs.x402.org and pass the result with --x402-payment-signature <value>.';
590
+ }
551
591
  }
552
592
 
553
593
  lastError = new NansenError(message, code, response.status, {
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Canonical EVM chain name → numeric chain ID mapping.
3
+ *
4
+ * Single source of truth — import from here instead of defining inline.
5
+ */
6
+
7
+ export const EVM_CHAIN_IDS = {
8
+ ethereum: 1,
9
+ base: 8453,
10
+ optimism: 10,
11
+ arbitrum: 42161,
12
+ polygon: 137,
13
+ avalanche: 43114,
14
+ bnb: 56,
15
+ linea: 59144,
16
+ scroll: 534352,
17
+ zksync: 324,
18
+ mantle: 5000,
19
+ };
package/src/cli.js CHANGED
@@ -144,14 +144,15 @@ export const SCHEMA = {
144
144
  chain: { type: 'string', default: 'ethereum', description: 'Blockchain' },
145
145
  from: { type: 'string', required: true, description: 'Token to sell (address or symbol)' },
146
146
  to: { type: 'string', required: true, description: 'Token to buy (address or symbol)' },
147
- amount: { type: 'string', required: true, description: 'Amount to swap' }
147
+ amount: { type: 'string', required: true, description: 'Amount to swap' },
148
+ wallet: { type: 'string', description: 'Wallet name, or "walletconnect"/"wc" for WalletConnect (EVM only)' }
148
149
  }
149
150
  },
150
151
  'execute': {
151
152
  description: 'Sign and broadcast a quoted trade',
152
153
  options: {
153
154
  chain: { type: 'string', default: 'ethereum', description: 'Blockchain' },
154
- wallet: { type: 'string', description: 'Wallet name or address' }
155
+ wallet: { type: 'string', description: 'Wallet name, or "walletconnect"/"wc" for WalletConnect (EVM only)' }
155
156
  }
156
157
  }
157
158
  }
@@ -838,6 +839,7 @@ export function buildCommands(deps = {}) {
838
839
  api = null,
839
840
  promptFn = prompt,
840
841
  log = console.log,
842
+ errorOutput = console.error,
841
843
  NansenAPIClass = NansenAPI,
842
844
  saveConfigFn = saveConfig,
843
845
  deleteConfigFn = deleteConfig,
@@ -905,7 +907,7 @@ export function buildCommands(deps = {}) {
905
907
  try {
906
908
  content = fs.readFileSync(changelogPath, 'utf8');
907
909
  } catch {
908
- errorOutput('CHANGELOG.md not found. Visit https://github.com/nansen-ai/nansen-cli/blob/main/CHANGELOG.md');
910
+ log('CHANGELOG.md not found. Visit https://github.com/nansen-ai/nansen-cli/blob/main/CHANGELOG.md');
909
911
  return;
910
912
  }
911
913
  const since = options.since;
@@ -1307,14 +1309,31 @@ export function buildCommands(deps = {}) {
1307
1309
  cmds['trade'] = async (args, apiInstance, flags, options) => {
1308
1310
  const sub = args[0];
1309
1311
  if (!sub || sub === 'help') {
1310
- return {
1311
- commands: ['quote', 'execute'],
1312
- description: 'DEX trading commands',
1313
- example: 'nansen trade quote --chain ethereum --from ETH --to USDC --amount 1'
1314
- };
1312
+ log(`nansen trade — DEX trading commands
1313
+
1314
+ SUBCOMMANDS:
1315
+ quote Get a swap quote (price, route, fees)
1316
+ execute Sign and broadcast a quoted swap
1317
+
1318
+ USAGE:
1319
+ nansen trade quote --chain <chain> --from <token> --to <token> --amount <units>
1320
+ nansen trade execute --quote <quoteId>
1321
+
1322
+ EXAMPLES:
1323
+ nansen trade quote --chain solana --from SOL --to USDC --amount 1000000000
1324
+ nansen trade quote --chain base --from ETH --to USDC --amount 1000000000000000000
1325
+ nansen trade execute --quote 1708900000000-abc123
1326
+
1327
+ SYMBOLS:
1328
+ Common tokens resolve automatically: SOL, ETH, BNB, USDC, USDT, WETH, WBNB
1329
+ Raw addresses are also accepted.`);
1330
+ return;
1315
1331
  }
1316
1332
  if (!tradingCmds[sub]) {
1317
- return { error: `Unknown trade subcommand: ${sub}`, available: ['quote', 'execute'] };
1333
+ log(`Unknown trade subcommand: ${sub}`);
1334
+ log(`Available: quote, execute`);
1335
+ log(`Run 'nansen trade help' for usage.`);
1336
+ return;
1318
1337
  }
1319
1338
  return tradingCmds[sub](args.slice(1), apiInstance, flags, options);
1320
1339
  };