nansen-cli 1.11.0 → 1.11.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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.11.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#194](https://github.com/nansen-ai/nansen-cli/pull/194) [`89225f5`](https://github.com/nansen-ai/nansen-cli/commit/89225f5d5b566f7eda77b1876c77545c2feb6a1c) Thanks [@TimNooren](https://github.com/TimNooren)! - fix: --help on trade subcommands and wallet subcommands now shows full help identical to the no-args case
8
+
9
+ - [#199](https://github.com/nansen-ai/nansen-cli/pull/199) [`9ae981e`](https://github.com/nansen-ai/nansen-cli/commit/9ae981e6dcf7fa663e47a3608afab7f12e0a9463) Thanks [@TimNooren](https://github.com/TimNooren)! - fix: replace misleading `walletconnect connect` command reference in x402 payment error with actionable guidance mentioning both local wallet (`nansen wallet create`) and external WalletConnect CLI options
10
+
3
11
  ## 1.11.0
4
12
 
5
13
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nansen-cli",
3
- "version": "1.11.0",
3
+ "version": "1.11.1",
4
4
  "description": "Command-line interface for Nansen API - designed for AI agents",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/api.js CHANGED
@@ -578,9 +578,20 @@ export class NansenAPI {
578
578
  return await paidResponse.json();
579
579
  }
580
580
  } catch (x402Err) {
581
- message = `x402 auto-payment failed: ${x402Err.message}`;
581
+ if (!this.apiKey) {
582
+ // No API key and no payment wallet — guide the user to login rather than
583
+ // showing a confusing x402 payment dump they can't act on.
584
+ // TODO: full fix would skip x402 entirely when no apiKey is set — see PR #<this PR number>
585
+ message = 'No API key configured. Run: nansen login --api-key <key>. Get your key at https://app.nansen.ai/api';
586
+ } else {
587
+ message = `x402 auto-payment failed: ${x402Err.message}`;
588
+ }
589
+ }
590
+ // Only include raw payment requirements in the error details when the user
591
+ // has an API key — for unauthenticated users they add noise, not signal.
592
+ if (this.apiKey) {
593
+ data.paymentRequirements = paymentRequirements;
582
594
  }
583
- data.paymentRequirements = paymentRequirements;
584
595
  }
585
596
  }
586
597
  }
package/src/cli.js CHANGED
@@ -642,9 +642,10 @@ EXAMPLES:
642
642
  nansen research smart-money netflow --chain solana
643
643
  nansen research token screener --chain solana --timeframe 24h
644
644
  nansen research profiler balance --address 0x... --chain ethereum
645
- nansen trade quote --chain ethereum --from ETH --to USDC --amount 1
645
+ nansen trade quote --chain base --from ETH --to USDC --amount 1
646
646
 
647
- Chains: ethereum, solana, base, bnb, arbitrum, polygon, optimism, avalanche, linea, scroll, mantle, ronin, sei, plasma, sonic, monad, hyperevm, iotaevm
647
+ Research chains: ethereum, solana, base, bnb, arbitrum, polygon, optimism, avalanche, linea, scroll, mantle, ronin, sei, plasma, sonic, monad, hyperevm, iotaevm
648
+ Trade chains: solana, base
648
649
  Labels: Fund, Smart Trader, 30D/90D/180D Smart Trader, Smart HL Perps Trader
649
650
 
650
651
  Docs: https://docs.nansen.ai
@@ -1079,6 +1080,28 @@ export function buildCommands(deps = {}) {
1079
1080
 
1080
1081
  let result = await handlers[subcommand]();
1081
1082
 
1083
+ // Warn when OHLCV price data is null (backend coverage gap)
1084
+ // Volume comes from on-chain DEX data and is always available, but price/market_cap
1085
+ // requires a price oracle — some tokens are not tracked and return all-null price fields.
1086
+ if (subcommand === 'ohlcv') {
1087
+ const candles = Array.isArray(result?.data) ? result.data : [];
1088
+ if (candles.length === 0) {
1089
+ process.stderr.write(`⚠️ No OHLCV data returned for token ${tokenAddress} on ${chain}.\n`);
1090
+ } else {
1091
+ const hasPrice = candles.some(c => c.open !== null || c.close !== null);
1092
+ const hasVolume = candles.some(c => c.volume !== null);
1093
+ if (!hasPrice && hasVolume) {
1094
+ process.stderr.write(
1095
+ `⚠️ Price data unavailable for token ${tokenAddress} on ${chain}.\n` +
1096
+ ` open/high/low/close, volume_usd, and market_cap are null.\n` +
1097
+ ` Volume (raw token units) is available. This token may not be tracked by Nansen's price oracle.\n`
1098
+ );
1099
+ } else if (!hasPrice && !hasVolume) {
1100
+ process.stderr.write(`⚠️ No OHLCV data available for token ${tokenAddress} on ${chain}.\n`);
1101
+ }
1102
+ }
1103
+ }
1104
+
1082
1105
  // Enrich transfers with Nansen labels for from/to addresses
1083
1106
  if (subcommand === 'transfers' && (options.enrich || flags.enrich)) {
1084
1107
  result = await enrichTransfers(result, apiInstance, chain);
@@ -1360,17 +1383,9 @@ export async function runCLI(rawArgs, deps = {}) {
1360
1383
  return { type: 'command-help', command: `research ${category}` };
1361
1384
  }
1362
1385
  }
1363
- // Handle 'trade <sub> --help'
1364
- if (command === 'trade' && subcommand) {
1365
- const tradeSchema = SCHEMA.commands.trade?.subcommands?.[subcommand];
1366
- if (tradeSchema) {
1367
- output(`\ntrade ${subcommand} - ${tradeSchema.description}\n`);
1368
- notify();
1369
- return { type: 'subcommand-help', command: 'trade', subcommand };
1370
- }
1371
- }
1372
1386
  // First try subcommand help
1373
- if (command && subcommand) {
1387
+ // Skip for 'trade' — its handlers show their own rich usage when required args are missing
1388
+ if (command && subcommand && command !== 'trade') {
1374
1389
  const subHelp = generateSubcommandHelp(command, subcommand);
1375
1390
  if (subHelp) {
1376
1391
  output(subHelp);
@@ -1379,7 +1394,8 @@ export async function runCLI(rawArgs, deps = {}) {
1379
1394
  }
1380
1395
  }
1381
1396
  // Then try command-level help (list subcommands)
1382
- const cmdSchemaLookup = SCHEMA.commands[command] || SCHEMA.commands.research.subcommands[command];
1397
+ // Skip for 'trade' let the handler show its own usage
1398
+ const cmdSchemaLookup = command !== 'trade' && (SCHEMA.commands[command] || SCHEMA.commands.research.subcommands[command]);
1383
1399
  if (command && cmdSchemaLookup) {
1384
1400
  const cmdSchema = cmdSchemaLookup;
1385
1401
  const lines = [`${command} — ${cmdSchema.description}`];
package/src/schema.json CHANGED
@@ -157,6 +157,14 @@
157
157
  "page": {
158
158
  "type": "number",
159
159
  "description": "Page number for paginated results (default: 1)"
160
+ },
161
+ "sort": {
162
+ "type": "string",
163
+ "description": "Sort field:direction (e.g., value_usd:desc)"
164
+ },
165
+ "filters": {
166
+ "type": "object",
167
+ "description": "Additional filters as JSON"
160
168
  }
161
169
  },
162
170
  "returns": [
@@ -178,6 +186,14 @@
178
186
  "limit": {
179
187
  "type": "number"
180
188
  },
189
+ "labels": {
190
+ "type": "string|array",
191
+ "description": "Smart Money label filter"
192
+ },
193
+ "sort": {
194
+ "type": "string",
195
+ "description": "Sort field:direction (e.g., deposit_value_usd:desc)"
196
+ },
181
197
  "filters": {
182
198
  "type": "object"
183
199
  },
@@ -224,6 +240,18 @@
224
240
  "page": {
225
241
  "type": "number",
226
242
  "description": "Page number for paginated results (default: 1)"
243
+ },
244
+ "labels": {
245
+ "type": "string|array",
246
+ "description": "Smart Money label filter"
247
+ },
248
+ "sort": {
249
+ "type": "string",
250
+ "description": "Sort field:direction (e.g., value_usd:desc)"
251
+ },
252
+ "filters": {
253
+ "type": "object",
254
+ "description": "Additional filters as JSON"
227
255
  }
228
256
  },
229
257
  "returns": [
package/src/wallet.js CHANGED
@@ -753,6 +753,11 @@ EXAMPLES:
753
753
  return;
754
754
  }
755
755
 
756
+ // --help on any wallet subcommand shows wallet help instead of executing
757
+ if (flags.help || flags.h) {
758
+ return handlers['help']();
759
+ }
760
+
756
761
  return handlers[subcommand]();
757
762
  },
758
763
  };
@@ -142,7 +142,9 @@ export async function handleX402Payment(paymentRequirements) {
142
142
  const wallet = await checkWalletConnection();
143
143
  if (!wallet) {
144
144
  throw new NansenError(
145
- 'x402 payment required but no wallet connected. Run `walletconnect connect` first.',
145
+ 'x402 payment required but no wallet connected. ' +
146
+ 'To pay automatically: create a local wallet with `nansen wallet create` (then set NANSEN_WALLET_PASSWORD), ' +
147
+ 'or connect an external wallet via the `walletconnect` CLI (`walletconnect connect`).',
146
148
  ErrorCode.PAYMENT_REQUIRED,
147
149
  402
148
150
  );