nansen-cli 1.33.0 → 1.34.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.34.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#459](https://github.com/nansen-ai/nansen-cli/pull/459) [`37e6725`](https://github.com/nansen-ai/nansen-cli/commit/37e6725aeeb3b83eb29c4650908b8dbb522ed316) Thanks [@dependabot](https://github.com/apps/dependabot)! - Drop support for Node.js 18 (EOL since April 2025). The minimum supported version is now Node.js 20, matching our test toolchain (vitest 4.x requires Node 20+).
8
+
9
+ - [#460](https://github.com/nansen-ai/nansen-cli/pull/460) [`aac4bbe`](https://github.com/nansen-ai/nansen-cli/commit/aac4bbe18312edb48c91df60ab555f9c1d8334ce) Thanks [@gulshngill](https://github.com/gulshngill)! - Add trader_type, sectors_filter, sm_label_filter, and trader_label_filter filters to `nansen research perp screener` (ECINT-6680).
10
+
11
+ New CLI options:
12
+
13
+ - `--trader-type <type>` — filter by trader type: all, sm, whale, public_figure, high_winrate_hl_perps_trader
14
+ - `--sectors-filter <sectors>` — comma-separated sector:subcategory pairs, e.g. "Crypto:AI,TradFi:Stocks"
15
+ - `--sm-label-filter <labels>` — comma-separated Nansen SM labels (applies when trader-type is all or sm)
16
+ - `--trader-label-filter <labels>` — comma-separated HL perps trader labels (applies when trader-type is all or sm)
17
+
3
18
  ## 1.33.0
4
19
 
5
20
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nansen-cli",
3
- "version": "1.33.0",
3
+ "version": "1.34.0",
4
4
  "description": "AI-agent CLI for Nansen API analytics, DEX swaps, and cross-chain trading",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -59,7 +59,7 @@
59
59
  },
60
60
  "homepage": "https://github.com/nansen-ai/nansen-cli#readme",
61
61
  "engines": {
62
- "node": ">=18.0.0"
62
+ "node": ">=20.0.0"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@changesets/changelog-github": "^0.5.1",
@@ -30,3 +30,62 @@ nansen research perp leaderboard --days 7 --limit 20
30
30
  nansen research smart-money perp-trades --limit 20
31
31
  # → token_symbol, side, action (Open/Close), value_usd, price_usd, trader_address_label
32
32
  ```
33
+
34
+ ## New Filters (ECINT-6680)
35
+
36
+ ### `--trader-type`
37
+ Filter by trader type. Accepted values: `all` (default), `sm`, `whale`, `public_figure`, `high_winrate_hl_perps_trader`.
38
+
39
+ ```bash
40
+ # Show only whale traders
41
+ nansen research perp screener --trader-type whale --limit 10
42
+
43
+ # Show only smart money traders
44
+ nansen research perp screener --trader-type sm --limit 20
45
+
46
+ # Show high win-rate HL perps traders
47
+ nansen research perp screener --trader-type high_winrate_hl_perps_trader --limit 20
48
+ ```
49
+
50
+ ### `--sm-label-filter`
51
+ Comma-separated Nansen SM labels to filter by. Only applies when `--trader-type` is `all` or `sm`.
52
+
53
+ ```bash
54
+ # Filter to a specific SM label
55
+ nansen research perp screener --trader-type sm --sm-label-filter "30D Smart Trader"
56
+
57
+ # Multiple labels
58
+ nansen research perp screener --sm-label-filter "30D Smart Trader,Smart LP"
59
+ ```
60
+
61
+ ### `--trader-label-filter`
62
+ Comma-separated HL perps trader labels to filter by. Only applies when `--trader-type` is `all` or `sm`.
63
+
64
+ ```bash
65
+ # Filter to HL Perps Whale label
66
+ nansen research perp screener --trader-label-filter "HL Perps Whale"
67
+ ```
68
+
69
+ ### `--sectors-filter`
70
+ Comma-separated `category:subcategory` pairs to filter coins by sector.
71
+
72
+ ```bash
73
+ # Filter to AI and DeFi crypto sectors
74
+ nansen research perp screener --sectors-filter "Crypto:AI,Crypto:DeFi" --trader-type whale
75
+
76
+ # Combine with trader type and limit
77
+ nansen research perp screener --sectors-filter "Crypto:AI,Crypto:DeFi" --trader-type whale --limit 10 --sort volume:desc
78
+ ```
79
+
80
+ ## Combined Examples
81
+
82
+ ```bash
83
+ # Whale traders in AI crypto, sorted by volume
84
+ nansen research perp screener --trader-type whale --sectors-filter "Crypto:AI" --sort volume:desc --limit 10
85
+
86
+ # Smart money with specific label, last 7 days
87
+ nansen research perp screener --trader-type sm --sm-label-filter "30D Smart Trader" --days 7 --limit 20
88
+
89
+ # All traders in TradFi stocks sector
90
+ nansen research perp screener --sectors-filter "TradFi:Stocks" --sort open_interest:desc --limit 20
91
+ ```
package/src/api.js CHANGED
@@ -1187,13 +1187,18 @@ export class NansenAPI {
1187
1187
  // ============= Perp Endpoints =============
1188
1188
 
1189
1189
  async perpScreener(params = {}) {
1190
- const { filters = {}, orderBy, pagination, days = 30 } = params;
1191
- return this.request('/api/v1/perp-screener', {
1190
+ const { filters = {}, orderBy, pagination, days = 30, traderType, sectorsFilter, smLabelFilter, traderLabelFilter } = params;
1191
+ const body = {
1192
1192
  date: buildDateRange(days),
1193
1193
  filters,
1194
1194
  order_by: orderBy,
1195
1195
  pagination
1196
- });
1196
+ };
1197
+ if (traderType !== undefined) body.filters.trader_type = traderType;
1198
+ if (sectorsFilter !== undefined) body.filters.sectors_filter = sectorsFilter;
1199
+ if (smLabelFilter !== undefined) body.filters.sm_label_filter = smLabelFilter;
1200
+ if (traderLabelFilter !== undefined) body.filters.trader_label_filter = traderLabelFilter;
1201
+ return this.request('/api/v1/perp-screener', body);
1197
1202
  }
1198
1203
 
1199
1204
  async perpLeaderboard(params = {}) {
package/src/cli.js CHANGED
@@ -1367,7 +1367,19 @@ export function buildCommands(deps = {}) {
1367
1367
  const days = options.days ? parseInt(options.days) : 30;
1368
1368
 
1369
1369
  const handlers = {
1370
- 'screener': () => apiInstance.perpScreener({ filters, orderBy, pagination, days }),
1370
+ 'screener': () => {
1371
+ const traderType = options['trader-type'];
1372
+ const sectorsFilter = options['sectors-filter']
1373
+ ? options['sectors-filter'].split(',').map(s => s.trim()).filter(Boolean)
1374
+ : undefined;
1375
+ const smLabelFilter = options['sm-label-filter']
1376
+ ? options['sm-label-filter'].split(',').map(s => s.trim()).filter(Boolean)
1377
+ : undefined;
1378
+ const traderLabelFilter = options['trader-label-filter']
1379
+ ? options['trader-label-filter'].split(',').map(s => s.trim()).filter(Boolean)
1380
+ : undefined;
1381
+ return apiInstance.perpScreener({ filters, orderBy, pagination, days, traderType, sectorsFilter, smLabelFilter, traderLabelFilter });
1382
+ },
1371
1383
  'leaderboard': () => {
1372
1384
  const withLabels = resolveBooleanOption(options, flags, 'premium-labels');
1373
1385
  return apiInstance.perpLeaderboard({ filters, orderBy, pagination, days, withLabels });
package/src/schema.json CHANGED
@@ -522,7 +522,11 @@
522
522
  "options": {
523
523
  "market-cap": {
524
524
  "description": "Filter by market cap group",
525
- "enum": ["lowcap", "midcap", "largecap"]
525
+ "enum": [
526
+ "lowcap",
527
+ "midcap",
528
+ "largecap"
529
+ ]
526
530
  },
527
531
  "limit": {
528
532
  "default": 25
@@ -555,6 +559,25 @@
555
559
  "options": {
556
560
  "days": {
557
561
  "default": 30
562
+ },
563
+ "trader-type": {
564
+ "description": "Filter by trader type. One of: all, sm, whale, public_figure, high_winrate_hl_perps_trader. Defaults to all.",
565
+ "enum": [
566
+ "all",
567
+ "sm",
568
+ "whale",
569
+ "public_figure",
570
+ "high_winrate_hl_perps_trader"
571
+ ]
572
+ },
573
+ "sectors-filter": {
574
+ "description": "Comma-separated sector:subcategory pairs to filter by, e.g. \"Crypto:AI,TradFi:Stocks\"."
575
+ },
576
+ "sm-label-filter": {
577
+ "description": "Comma-separated Nansen SM labels to filter by, e.g. \"30D Smart Trader\". Only applies when trader-type is all or sm."
578
+ },
579
+ "trader-label-filter": {
580
+ "description": "Comma-separated HL perps trader labels to filter by, e.g. \"HL Perps Whale\". Only applies when trader-type is all or sm."
558
581
  }
559
582
  }
560
583
  },
@@ -616,8 +639,12 @@
616
639
  "endpoint": "/api/v1/prediction-market/market-screener",
617
640
  "description": "Get Prediction Market Screener",
618
641
  "options": {
619
- "query": { "default": "" },
620
- "sort-by": { "description": "Deprecated: use --sort field:dir instead" },
642
+ "query": {
643
+ "default": ""
644
+ },
645
+ "sort-by": {
646
+ "description": "Deprecated: use --sort field:dir instead"
647
+ },
621
648
  "tags": {},
622
649
  "min-liquidity": {},
623
650
  "max-liquidity": {},
@@ -638,8 +665,12 @@
638
665
  "endpoint": "/api/v1/prediction-market/event-screener",
639
666
  "description": "Get Prediction Market Event Screener",
640
667
  "options": {
641
- "query": { "default": "" },
642
- "sort-by": { "description": "Deprecated: use --sort field:dir instead" },
668
+ "query": {
669
+ "default": ""
670
+ },
671
+ "sort-by": {
672
+ "description": "Deprecated: use --sort field:dir instead"
673
+ },
643
674
  "tags": {},
644
675
  "min-liquidity": {},
645
676
  "max-liquidity": {},
@@ -717,104 +748,218 @@
717
748
  "endpoint": "/api/v1beta1/tgm/historical-dex-trades",
718
749
  "description": "Historical DEX trades for a token at a point in time",
719
750
  "options": {
720
- "token-address": { "required": true, "description": "Token address" },
721
- "from-date": { "required": true, "description": "Start of date range (YYYY-MM-DD)" },
722
- "to-date": { "required": true, "description": "End of date range (YYYY-MM-DD)" },
723
- "chain": { "default": "solana", "description": "Chain" }
751
+ "token-address": {
752
+ "required": true,
753
+ "description": "Token address"
754
+ },
755
+ "from-date": {
756
+ "required": true,
757
+ "description": "Start of date range (YYYY-MM-DD)"
758
+ },
759
+ "to-date": {
760
+ "required": true,
761
+ "description": "End of date range (YYYY-MM-DD)"
762
+ },
763
+ "chain": {
764
+ "default": "solana",
765
+ "description": "Chain"
766
+ }
724
767
  }
725
768
  },
726
769
  "historical-pnl-leaderboard": {
727
770
  "endpoint": "/api/v1beta1/tgm/historical-pnl-leaderboard",
728
771
  "description": "Historical PnL leaderboard for a token",
729
772
  "options": {
730
- "token-address": { "required": true, "description": "Token address" },
731
- "from-date": { "required": true, "description": "Start of date range (YYYY-MM-DD)" },
732
- "to-date": { "required": true, "description": "End of date range (YYYY-MM-DD)" },
733
- "chain": { "default": "solana", "description": "Chain" }
773
+ "token-address": {
774
+ "required": true,
775
+ "description": "Token address"
776
+ },
777
+ "from-date": {
778
+ "required": true,
779
+ "description": "Start of date range (YYYY-MM-DD)"
780
+ },
781
+ "to-date": {
782
+ "required": true,
783
+ "description": "End of date range (YYYY-MM-DD)"
784
+ },
785
+ "chain": {
786
+ "default": "solana",
787
+ "description": "Chain"
788
+ }
734
789
  }
735
790
  },
736
791
  "historical-token-flow-summary": {
737
792
  "endpoint": "/api/v1beta1/tgm/historical-token-flow-summary",
738
793
  "description": "Historical token flow summary (no pagination)",
739
794
  "options": {
740
- "token-address": { "required": true, "description": "Token address" },
741
- "from-date": { "required": true, "description": "Start of date range (YYYY-MM-DD)" },
742
- "to-date": { "required": true, "description": "End of date range (YYYY-MM-DD)" },
743
- "chain": { "default": "solana", "description": "Chain" }
795
+ "token-address": {
796
+ "required": true,
797
+ "description": "Token address"
798
+ },
799
+ "from-date": {
800
+ "required": true,
801
+ "description": "Start of date range (YYYY-MM-DD)"
802
+ },
803
+ "to-date": {
804
+ "required": true,
805
+ "description": "End of date range (YYYY-MM-DD)"
806
+ },
807
+ "chain": {
808
+ "default": "solana",
809
+ "description": "Chain"
810
+ }
744
811
  }
745
812
  },
746
813
  "historical-token-quant-scores": {
747
814
  "endpoint": "/api/v1beta1/tgm/historical-token-quant-scores",
748
815
  "description": "Historical token quantitative scores at a snapshot date",
749
816
  "options": {
750
- "token-address": { "required": true, "description": "Token address" },
751
- "as-of-date": { "required": true, "description": "Snapshot date (YYYY-MM-DD)" },
752
- "chain": { "default": "solana", "description": "Chain" }
817
+ "token-address": {
818
+ "required": true,
819
+ "description": "Token address"
820
+ },
821
+ "as-of-date": {
822
+ "required": true,
823
+ "description": "Snapshot date (YYYY-MM-DD)"
824
+ },
825
+ "chain": {
826
+ "default": "solana",
827
+ "description": "Chain"
828
+ }
753
829
  }
754
830
  },
755
831
  "historical-top-holders": {
756
832
  "endpoint": "/api/v1beta1/tgm/historical-top-holders",
757
833
  "description": "Historical top holders of a token at a snapshot date",
758
834
  "options": {
759
- "token-address": { "required": true, "description": "Token address" },
760
- "as-of-date": { "required": true, "description": "Snapshot date (YYYY-MM-DD)" },
761
- "chain": { "default": "solana", "description": "Chain" }
835
+ "token-address": {
836
+ "required": true,
837
+ "description": "Token address"
838
+ },
839
+ "as-of-date": {
840
+ "required": true,
841
+ "description": "Snapshot date (YYYY-MM-DD)"
842
+ },
843
+ "chain": {
844
+ "default": "solana",
845
+ "description": "Chain"
846
+ }
762
847
  }
763
848
  },
764
849
  "historical-who-bought-sold": {
765
850
  "endpoint": "/api/v1beta1/tgm/historical-who-bought-sold",
766
851
  "description": "Historical buyers/sellers of a token",
767
852
  "options": {
768
- "token-address": { "required": true, "description": "Token address" },
769
- "from-date": { "required": true, "description": "Start of date range (YYYY-MM-DD)" },
770
- "to-date": { "required": true, "description": "End of date range (YYYY-MM-DD)" },
771
- "buy-or-sell": { "default": "BUY", "description": "BUY or SELL" },
772
- "chain": { "default": "solana", "description": "Chain" }
853
+ "token-address": {
854
+ "required": true,
855
+ "description": "Token address"
856
+ },
857
+ "from-date": {
858
+ "required": true,
859
+ "description": "Start of date range (YYYY-MM-DD)"
860
+ },
861
+ "to-date": {
862
+ "required": true,
863
+ "description": "End of date range (YYYY-MM-DD)"
864
+ },
865
+ "buy-or-sell": {
866
+ "default": "BUY",
867
+ "description": "BUY or SELL"
868
+ },
869
+ "chain": {
870
+ "default": "solana",
871
+ "description": "Chain"
872
+ }
773
873
  }
774
874
  },
775
875
  "historical-smart-money-balances": {
776
876
  "endpoint": "/api/v1beta1/smart-money/historical-token-balances",
777
877
  "description": "Historical smart money token balances at a snapshot date (no order_by)",
778
878
  "options": {
779
- "as-of-date": { "required": true, "description": "Snapshot date (YYYY-MM-DD)" },
780
- "chains": { "default": "solana", "description": "Comma-separated chains" }
879
+ "as-of-date": {
880
+ "required": true,
881
+ "description": "Snapshot date (YYYY-MM-DD)"
882
+ },
883
+ "chains": {
884
+ "default": "solana",
885
+ "description": "Comma-separated chains"
886
+ }
781
887
  }
782
888
  },
783
889
  "historical-token-screener": {
784
890
  "endpoint": "/api/v1beta1/token-screener/historical",
785
891
  "description": "Historical token screener over a trailing window",
786
892
  "options": {
787
- "timeframe-days": { "required": true, "type": "number", "description": "Trailing window size in days" },
788
- "to-date": { "required": true, "description": "End date for the window (YYYY-MM-DD)" },
789
- "chains": { "default": "solana", "description": "Comma-separated chains" }
893
+ "timeframe-days": {
894
+ "required": true,
895
+ "type": "number",
896
+ "description": "Trailing window size in days"
897
+ },
898
+ "to-date": {
899
+ "required": true,
900
+ "description": "End date for the window (YYYY-MM-DD)"
901
+ },
902
+ "chains": {
903
+ "default": "solana",
904
+ "description": "Comma-separated chains"
905
+ }
790
906
  }
791
907
  },
792
908
  "historical-wallet-balances": {
793
909
  "endpoint": "/api/v1beta1/profiler/address/historical-token-balances",
794
910
  "description": "Historical token balances for a wallet at a snapshot date",
795
911
  "options": {
796
- "address": { "required": true, "description": "Wallet address" },
797
- "as-of-date": { "required": true, "description": "Snapshot date (YYYY-MM-DD)" },
798
- "chain": { "default": "ethereum", "description": "Chain" }
912
+ "address": {
913
+ "required": true,
914
+ "description": "Wallet address"
915
+ },
916
+ "as-of-date": {
917
+ "required": true,
918
+ "description": "Snapshot date (YYYY-MM-DD)"
919
+ },
920
+ "chain": {
921
+ "default": "ethereum",
922
+ "description": "Chain"
923
+ }
799
924
  }
800
925
  },
801
926
  "historical-tx-lookup": {
802
927
  "endpoint": "/api/v1beta1/profiler/historical-transaction-lookup",
803
928
  "description": "Lookup a historical transaction by hash",
804
929
  "options": {
805
- "transaction-hash": { "required": true, "description": "Transaction hash (0x-prefixed, 66 chars)" },
806
- "as-of-date": { "required": true, "description": "Reference date for label and pricing resolution (YYYY-MM-DD)" },
807
- "block-timestamp": { "description": "Block timestamp (YYYY-MM-DD HH:MM:SS) — skips slow hash-resolution step if provided" },
808
- "chain": { "default": "ethereum", "description": "Chain (ethereum, bnb, base)" }
930
+ "transaction-hash": {
931
+ "required": true,
932
+ "description": "Transaction hash (0x-prefixed, 66 chars)"
933
+ },
934
+ "as-of-date": {
935
+ "required": true,
936
+ "description": "Reference date for label and pricing resolution (YYYY-MM-DD)"
937
+ },
938
+ "block-timestamp": {
939
+ "description": "Block timestamp (YYYY-MM-DD HH:MM:SS) \u2014 skips slow hash-resolution step if provided"
940
+ },
941
+ "chain": {
942
+ "default": "ethereum",
943
+ "description": "Chain (ethereum, bnb, base)"
944
+ }
809
945
  }
810
946
  },
811
947
  "historical-wallet-transactions": {
812
948
  "endpoint": "/api/v1beta1/profiler/address/historical-transactions",
813
949
  "description": "Historical transactions for a wallet at a snapshot date",
814
950
  "options": {
815
- "address": { "required": true, "description": "Wallet address" },
816
- "as-of-date": { "required": true, "description": "Snapshot date (YYYY-MM-DD)" },
817
- "chain": { "default": "ethereum", "description": "Chain" }
951
+ "address": {
952
+ "required": true,
953
+ "description": "Wallet address"
954
+ },
955
+ "as-of-date": {
956
+ "required": true,
957
+ "description": "Snapshot date (YYYY-MM-DD)"
958
+ },
959
+ "chain": {
960
+ "default": "ethereum",
961
+ "description": "Chain"
962
+ }
818
963
  }
819
964
  }
820
965
  }
@@ -971,7 +1116,7 @@
971
1116
  },
972
1117
  "to-chain": {
973
1118
  "type": "string",
974
- "description": "Destination blockchain for cross-chain swap (solana or base). Omit for same-chain. At least one side must be USDC or a native token (ETH, SOL). Non-native to non-native is not supported swap to USDC first, then bridge. Bridge providers (Li.Fi or Relay) are selected automatically based on best price. Sub-dollar swaps are supported via Relay."
1119
+ "description": "Destination blockchain for cross-chain swap (solana or base). Omit for same-chain. At least one side must be USDC or a native token (ETH, SOL). Non-native to non-native is not supported \u2014 swap to USDC first, then bridge. Bridge providers (Li.Fi or Relay) are selected automatically based on best price. Sub-dollar swaps are supported via Relay."
975
1120
  },
976
1121
  "from": {
977
1122
  "type": "string",
@@ -1047,7 +1192,7 @@
1047
1192
  },
1048
1193
  "aggregator": {
1049
1194
  "type": "string",
1050
- "description": "lifi or relay. Overrides auto-detection use when polling from a different machine or after the 30-day local record TTL has expired."
1195
+ "description": "lifi or relay. Overrides auto-detection \u2014 use when polling from a different machine or after the 30-day local record TTL has expired."
1051
1196
  }
1052
1197
  }
1053
1198
  },
@@ -1101,7 +1246,9 @@
1101
1246
  "description": "Wallet name (or \"walletconnect\"/\"wc\")"
1102
1247
  }
1103
1248
  },
1104
- "chains": ["solana"],
1249
+ "chains": [
1250
+ "solana"
1251
+ ],
1105
1252
  "prerequisites": [
1106
1253
  "A Solana wallet must be configured. Run: nansen wallet create"
1107
1254
  ]
@@ -1141,7 +1288,9 @@
1141
1288
  "description": "Wallet name (or \"walletconnect\"/\"wc\")"
1142
1289
  }
1143
1290
  },
1144
- "chains": ["solana"]
1291
+ "chains": [
1292
+ "solana"
1293
+ ]
1145
1294
  },
1146
1295
  "cancel": {
1147
1296
  "description": "Cancel an open limit order",
@@ -1156,7 +1305,9 @@
1156
1305
  "description": "Wallet name (or \"walletconnect\"/\"wc\")"
1157
1306
  }
1158
1307
  },
1159
- "chains": ["solana"]
1308
+ "chains": [
1309
+ "solana"
1310
+ ]
1160
1311
  },
1161
1312
  "update": {
1162
1313
  "description": "Update trigger price or slippage on an existing order",
@@ -1179,7 +1330,9 @@
1179
1330
  "description": "Wallet name (or \"walletconnect\"/\"wc\")"
1180
1331
  }
1181
1332
  },
1182
- "chains": ["solana"]
1333
+ "chains": [
1334
+ "solana"
1335
+ ]
1183
1336
  }
1184
1337
  }
1185
1338
  }