nansen-cli 1.12.0 → 1.13.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,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.13.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#225](https://github.com/nansen-ai/nansen-cli/pull/225) [`051e4a3`](https://github.com/nansen-ai/nansen-cli/commit/051e4a353641d000facd2133810c059981b9ac7f) Thanks [@TimNooren](https://github.com/TimNooren)! - Remove "recommended, lower fees" label from Base network in wallet create output
8
+
9
+ ## 1.13.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#107](https://github.com/nansen-ai/nansen-cli/pull/107) [`5877c06`](https://github.com/nansen-ai/nansen-cli/commit/5877c06061c1d32998fa3ce011c16f4352fc22dc) Thanks [@marius-reed](https://github.com/marius-reed)! - Add 11 prediction market (Polymarket) endpoints under `nansen research pm`. Includes OHLCV, orderbook, top holders, trades, screeners, PnL, position detail, and categories. Supports `--market-id`, `--address`, `--sort-by`, `--query`, `--status` flags with pagination, sorting, and table output.
14
+
3
15
  ## 1.12.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -30,7 +30,7 @@ nansen wallet <subcommand> [options]
30
30
  nansen schema [command] [--pretty] # full command reference (no API key needed)
31
31
  ```
32
32
 
33
- **Research categories:** `smart-money` (`sm`), `token` (`tgm`), `profiler` (`prof`), `portfolio` (`port`), `search`, `perp`, `points`
33
+ **Research categories:** `smart-money` (`sm`), `token` (`tgm`), `profiler` (`prof`), `portfolio` (`port`), `prediction-market` (`pm`), `search`, `perp`, `points`
34
34
 
35
35
  **Trade:** `quote`, `execute` — DEX swaps on Solana and Base.
36
36
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nansen-cli",
3
- "version": "1.12.0",
3
+ "version": "1.13.1",
4
4
  "description": "Command-line interface for Nansen API - designed for AI agents",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -24,7 +24,7 @@
24
24
  "lint": "eslint .",
25
25
  "lint:fix": "eslint . --fix",
26
26
  "changeset": "changeset",
27
- "changeset:version": "changeset version",
27
+ "changeset:version": "changeset version && npm install --package-lock-only",
28
28
  "changeset:publish": "changeset publish"
29
29
  },
30
30
  "keywords": [
package/src/api.js CHANGED
@@ -6,6 +6,7 @@
6
6
  import fs from 'fs';
7
7
  import path from 'path';
8
8
  import { fileURLToPath } from 'url';
9
+ import { EVM_CHAINS } from './chain-ids.js';
9
10
 
10
11
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
12
 
@@ -255,12 +256,6 @@ const ADDRESS_PATTERNS = {
255
256
  bitcoin: /^(1|3|bc1)[a-zA-HJ-NP-Z0-9]{25,62}$/,
256
257
  };
257
258
 
258
- const EVM_CHAINS = [
259
- 'ethereum', 'arbitrum', 'base', 'bnb', 'polygon', 'optimism',
260
- 'avalanche', 'linea', 'scroll', 'mantle', 'ronin',
261
- 'sei', 'plasma', 'sonic', 'monad', 'hyperevm', 'iotaevm'
262
- ];
263
-
264
259
  /**
265
260
  * Validate address format for a given chain
266
261
  * @param {string} address - The address to validate
@@ -1103,6 +1098,113 @@ export class NansenAPI {
1103
1098
  });
1104
1099
  }
1105
1100
 
1101
+ // ============= Prediction Market Endpoints =============
1102
+
1103
+ async pmOhlcv(params = {}) {
1104
+ const { marketId, sort, pagination } = params;
1105
+ if (!marketId) throw new NansenError('market_id is required', ErrorCode.MISSING_PARAM);
1106
+ return this.request('/api/v1/prediction-market/ohlcv', {
1107
+ market_id: marketId,
1108
+ sort,
1109
+ pagination
1110
+ });
1111
+ }
1112
+
1113
+ async pmOrderbook(params = {}) {
1114
+ const { marketId, pagination } = params;
1115
+ if (!marketId) throw new NansenError('market_id is required', ErrorCode.MISSING_PARAM);
1116
+ return this.request('/api/v1/prediction-market/orderbook', {
1117
+ market_id: marketId,
1118
+ pagination
1119
+ });
1120
+ }
1121
+
1122
+ async pmTopHolders(params = {}) {
1123
+ const { marketId, sort, pagination } = params;
1124
+ if (!marketId) throw new NansenError('market_id is required', ErrorCode.MISSING_PARAM);
1125
+ return this.request('/api/v1/prediction-market/top-holders', {
1126
+ market_id: marketId,
1127
+ sort,
1128
+ pagination
1129
+ });
1130
+ }
1131
+
1132
+ async pmTradesByMarket(params = {}) {
1133
+ const { marketId, pagination } = params;
1134
+ if (!marketId) throw new NansenError('market_id is required', ErrorCode.MISSING_PARAM);
1135
+ return this.request('/api/v1/prediction-market/trades-by-market', {
1136
+ market_id: marketId,
1137
+ pagination
1138
+ });
1139
+ }
1140
+
1141
+ async pmTradesByAddress(params = {}) {
1142
+ const { address, pagination } = params;
1143
+ // Polymarket runs exclusively on Polygon
1144
+ const validation = validateAddress(address, 'polygon');
1145
+ if (!validation.valid) throw new NansenError(validation.error, validation.code);
1146
+ return this.request('/api/v1/prediction-market/trades-by-address', {
1147
+ address,
1148
+ pagination
1149
+ });
1150
+ }
1151
+
1152
+ async pmMarketScreener(params = {}) {
1153
+ const { sortBy = 'volume_24hr', query = '', status = '', pagination } = params;
1154
+ return this.request('/api/v1/prediction-market/market-screener', {
1155
+ sort_by: sortBy,
1156
+ query,
1157
+ status,
1158
+ pagination
1159
+ });
1160
+ }
1161
+
1162
+ async pmEventScreener(params = {}) {
1163
+ const { sortBy = 'volume_24hr', query = '', status = '', pagination } = params;
1164
+ return this.request('/api/v1/prediction-market/event-screener', {
1165
+ sort_by: sortBy,
1166
+ query,
1167
+ status,
1168
+ pagination
1169
+ });
1170
+ }
1171
+
1172
+ async pmPnlByMarket(params = {}) {
1173
+ const { marketId, pagination } = params;
1174
+ if (!marketId) throw new NansenError('market_id is required', ErrorCode.MISSING_PARAM);
1175
+ return this.request('/api/v1/prediction-market/pnl-by-market', {
1176
+ market_id: marketId,
1177
+ pagination
1178
+ });
1179
+ }
1180
+
1181
+ async pmPnlByAddress(params = {}) {
1182
+ const { address, pagination } = params;
1183
+ // Polymarket runs exclusively on Polygon
1184
+ const validation = validateAddress(address, 'polygon');
1185
+ if (!validation.valid) throw new NansenError(validation.error, validation.code);
1186
+ return this.request('/api/v1/prediction-market/pnl-by-address', {
1187
+ address,
1188
+ pagination
1189
+ });
1190
+ }
1191
+
1192
+ async pmPositionDetail(params = {}) {
1193
+ const { marketId, pagination } = params;
1194
+ if (!marketId) throw new NansenError('market_id is required', ErrorCode.MISSING_PARAM);
1195
+ return this.request('/api/v1/prediction-market/position-detail', {
1196
+ market_id: marketId,
1197
+ pagination
1198
+ });
1199
+ }
1200
+
1201
+ async pmCategories(params = {}) {
1202
+ const { pagination } = params;
1203
+ return this.request('/api/v1/prediction-market/categories', {
1204
+ pagination
1205
+ });
1206
+ }
1207
+
1106
1208
  // ============= Points Endpoints =============
1107
1209
 
1108
1210
  async pointsLeaderboard(params = {}) {
package/src/chain-ids.js CHANGED
@@ -17,3 +17,14 @@ export const EVM_CHAIN_IDS = {
17
17
  zksync: 324,
18
18
  mantle: 5000,
19
19
  };
20
+
21
+ /**
22
+ * All EVM chain names recognised by this CLI.
23
+ * Used for address-format validation (0x...) and ENS resolution gating.
24
+ * Import from here instead of defining an inline list per file.
25
+ */
26
+ export const EVM_CHAINS = [
27
+ 'ethereum', 'arbitrum', 'base', 'bnb', 'polygon', 'optimism',
28
+ 'avalanche', 'linea', 'scroll', 'zksync', 'mantle', 'ronin',
29
+ 'sei', 'plasma', 'sonic', 'unichain', 'monad', 'hyperevm', 'iotaevm',
30
+ ];
package/src/cli.js CHANGED
@@ -55,15 +55,26 @@ export function filterFields(data, fields) {
55
55
  const filtered = {};
56
56
  for (const key of Object.keys(obj)) {
57
57
  if (fieldSet.has(key)) {
58
+ // Explicitly requested — include as-is
58
59
  filtered[key] = obj[key];
59
60
  } else if (typeof obj[key] === 'object' && obj[key] !== null) {
60
- // Recurse into nested objects/arrays
61
- const nested = filterObject(obj[key]);
62
- // Only include if it has content
63
- if (nested !== null && nested !== undefined) {
64
- if (Array.isArray(nested) && nested.length > 0) {
65
- filtered[key] = nested;
66
- } else if (!Array.isArray(nested) && Object.keys(nested).length > 0) {
61
+ if (Array.isArray(obj[key])) {
62
+ // Only recurse into arrays whose elements are plain objects.
63
+ // Primitive arrays (e.g. tags: ["a","b"]) are dropped unless the
64
+ // key was explicitly requested (handled above).
65
+ const hasObjectElements = obj[key].length > 0 &&
66
+ typeof obj[key][0] === 'object' && obj[key][0] !== null;
67
+ if (hasObjectElements) {
68
+ const nested = obj[key].map(item => filterObject(item))
69
+ .filter(item => Object.keys(item).length > 0);
70
+ if (nested.length > 0) {
71
+ filtered[key] = nested;
72
+ }
73
+ }
74
+ } else {
75
+ // Plain object — always recurse in case it wraps requested fields
76
+ const nested = filterObject(obj[key]);
77
+ if (nested !== null && nested !== undefined && Object.keys(nested).length > 0) {
67
78
  filtered[key] = nested;
68
79
  }
69
80
  }
@@ -1217,12 +1228,48 @@ export function buildCommands(deps = {}) {
1217
1228
  return { error: `Unknown subcommand: ${subcommand}`, available: Object.keys(handlers) };
1218
1229
  }
1219
1230
 
1231
+ return handlers[subcommand]();
1232
+ },
1233
+
1234
+ 'prediction-market': async (args, apiInstance, flags, options) => {
1235
+ const subcommand = args[0] || 'help';
1236
+ const marketId = options['market-id'];
1237
+ const address = options.address;
1238
+ const sortBy = options['sort-by'];
1239
+ const query = options.query;
1240
+ const status = options.status;
1241
+ const sort = parseSort(options.sort);
1242
+ const pagination = buildPagination(options);
1243
+
1244
+ const handlers = {
1245
+ 'ohlcv': () => apiInstance.pmOhlcv({ marketId, sort, pagination }),
1246
+ 'orderbook': () => apiInstance.pmOrderbook({ marketId, pagination }),
1247
+ 'top-holders': () => apiInstance.pmTopHolders({ marketId, sort, pagination }),
1248
+ 'trades-by-market': () => apiInstance.pmTradesByMarket({ marketId, pagination }),
1249
+ 'trades-by-address': () => apiInstance.pmTradesByAddress({ address, pagination }),
1250
+ 'market-screener': () => apiInstance.pmMarketScreener({ sortBy, query, status, pagination }),
1251
+ 'event-screener': () => apiInstance.pmEventScreener({ sortBy, query, status, pagination }),
1252
+ 'pnl-by-market': () => apiInstance.pmPnlByMarket({ marketId, pagination }),
1253
+ 'pnl-by-address': () => apiInstance.pmPnlByAddress({ address, pagination }),
1254
+ 'position-detail': () => apiInstance.pmPositionDetail({ marketId, pagination }),
1255
+ 'categories': () => apiInstance.pmCategories({ pagination }),
1256
+ 'help': () => ({
1257
+ commands: ['ohlcv', 'orderbook', 'top-holders', 'trades-by-market', 'trades-by-address', 'market-screener', 'event-screener', 'pnl-by-market', 'pnl-by-address', 'position-detail', 'categories'],
1258
+ description: 'Polymarket prediction market analytics',
1259
+ example: 'nansen research pm market-screener --sort-by volume_24hr --limit 20'
1260
+ })
1261
+ };
1262
+
1263
+ if (!handlers[subcommand]) {
1264
+ throw new NansenError(`Unknown subcommand: ${subcommand}. Available: ${Object.keys(handlers).filter(k => k !== 'help').join(', ')}`, ErrorCode.UNKNOWN);
1265
+ }
1266
+
1220
1267
  return handlers[subcommand]();
1221
1268
  }
1222
1269
  };
1223
1270
 
1224
1271
  // 'research' delegates to the category handlers defined above
1225
- const RESEARCH_CATEGORIES = new Set(['smart-money', 'profiler', 'token', 'search', 'perp', 'portfolio', 'points']);
1272
+ const RESEARCH_CATEGORIES = new Set(['smart-money', 'profiler', 'token', 'search', 'perp', 'portfolio', 'points', 'prediction-market']);
1226
1273
 
1227
1274
  cmds['research'] = async (args, apiInstance, flags, options) => {
1228
1275
  const rawCategory = args[0];
@@ -1298,11 +1345,12 @@ export const RESEARCH_CATEGORY_ALIASES = {
1298
1345
  'tgm': 'token',
1299
1346
  'sm': 'smart-money',
1300
1347
  'prof': 'profiler',
1301
- 'port': 'portfolio'
1348
+ 'port': 'portfolio',
1349
+ 'pm': 'prediction-market'
1302
1350
  };
1303
1351
 
1304
1352
  // Generate help text for a specific subcommand using SCHEMA
1305
- export function generateSubcommandHelp(command, subcommand) {
1353
+ export function generateSubcommandHelp(command, subcommand, prefix = null) {
1306
1354
  const cmdSchema = SCHEMA.commands[command] || SCHEMA.commands.research.subcommands[command];
1307
1355
  if (!cmdSchema) return null;
1308
1356
 
@@ -1329,8 +1377,8 @@ export function generateSubcommandHelp(command, subcommand) {
1329
1377
 
1330
1378
  const exampleValues = { address: '0x...', token: '0x...', query: '"term"', symbol: 'BTC', date: '2024-01-01' };
1331
1379
  const chain = subSchema.options?.chain?.default || 'solana';
1332
- const prefix = DEPRECATED_TO_RESEARCH.has(command) ? `research ${command}` : command;
1333
- let example = `nansen ${prefix} ${subcommand}`;
1380
+ const cmdPrefix = prefix || (DEPRECATED_TO_RESEARCH.has(command) ? `research ${command}` : command);
1381
+ let example = `nansen ${cmdPrefix} ${subcommand}`;
1334
1382
  if (subSchema.options) {
1335
1383
  for (const [name, opt] of Object.entries(subSchema.options)) {
1336
1384
  if (opt.required) example += ` --${name} ${exampleValues[name] || '<val>'}`;
@@ -1398,7 +1446,7 @@ export async function runCLI(rawArgs, deps = {}) {
1398
1446
  const category = RESEARCH_CATEGORY_ALIASES[subcommand] || subcommand;
1399
1447
  const deepSub = subArgs[1];
1400
1448
  if (deepSub) {
1401
- const subHelp = generateSubcommandHelp(category, deepSub);
1449
+ const subHelp = generateSubcommandHelp(category, deepSub, `research ${subcommand}`);
1402
1450
  if (subHelp) {
1403
1451
  output(subHelp);
1404
1452
  notify();
package/src/ens.js CHANGED
@@ -6,15 +6,10 @@
6
6
 
7
7
  import https from 'https';
8
8
  import { keccak256 } from './crypto.js';
9
+ import { EVM_CHAINS } from './chain-ids.js';
9
10
 
10
11
  const ENS_PATTERN = /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.eth$/;
11
12
 
12
- const EVM_CHAINS = [
13
- 'ethereum', 'base', 'optimism', 'arbitrum', 'polygon', 'bnb',
14
- 'avalanche', 'fantom', 'gnosis', 'linea', 'scroll', 'zksync',
15
- 'blast', 'mantle', 'ronin', 'sei', 'plasma', 'sonic', 'unichain', 'monad', 'hyperevm', 'iotaevm'
16
- ];
17
-
18
13
  /**
19
14
  * Check if a string looks like an ENS name
20
15
  */
package/src/schema.json CHANGED
@@ -33,10 +33,6 @@
33
33
  "filters": {
34
34
  "type": "object",
35
35
  "description": "Additional filters as JSON"
36
- },
37
- "page": {
38
- "type": "number",
39
- "description": "Page number for paginated results (default: 1)"
40
36
  }
41
37
  },
42
38
  "returns": [
@@ -74,10 +70,6 @@
74
70
  },
75
71
  "filters": {
76
72
  "type": "object"
77
- },
78
- "page": {
79
- "type": "number",
80
- "description": "Page number for paginated results (default: 1)"
81
73
  }
82
74
  },
83
75
  "returns": [
@@ -118,10 +110,6 @@
118
110
  },
119
111
  "filters": {
120
112
  "type": "object"
121
- },
122
- "page": {
123
- "type": "number",
124
- "description": "Page number for paginated results (default: 1)"
125
113
  }
126
114
  },
127
115
  "returns": [
@@ -153,18 +141,6 @@
153
141
  },
154
142
  "labels": {
155
143
  "type": "string|array"
156
- },
157
- "page": {
158
- "type": "number",
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"
168
144
  }
169
145
  },
170
146
  "returns": [
@@ -186,20 +162,8 @@
186
162
  "limit": {
187
163
  "type": "number"
188
164
  },
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
- },
197
165
  "filters": {
198
166
  "type": "object"
199
- },
200
- "page": {
201
- "type": "number",
202
- "description": "Page number for paginated results (default: 1)"
203
167
  }
204
168
  },
205
169
  "returns": [
@@ -236,22 +200,6 @@
236
200
  },
237
201
  "limit": {
238
202
  "type": "number"
239
- },
240
- "page": {
241
- "type": "number",
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"
255
203
  }
256
204
  },
257
205
  "returns": [
@@ -342,18 +290,6 @@
342
290
  "days": {
343
291
  "type": "number",
344
292
  "default": 30
345
- },
346
- "page": {
347
- "type": "number",
348
- "description": "Page number for paginated results (default: 1)"
349
- },
350
- "sort": {
351
- "type": "string",
352
- "description": "Sort field:direction (e.g., block_timestamp:desc)"
353
- },
354
- "filters": {
355
- "type": "object",
356
- "description": "Additional filters as JSON"
357
293
  }
358
294
  },
359
295
  "returns": [
@@ -388,18 +324,6 @@
388
324
  },
389
325
  "limit": {
390
326
  "type": "number"
391
- },
392
- "page": {
393
- "type": "number",
394
- "description": "Page number for paginated results (default: 1)"
395
- },
396
- "sort": {
397
- "type": "string",
398
- "description": "Sort field:direction (e.g., pnl_usd_realised:desc)"
399
- },
400
- "filters": {
401
- "type": "object",
402
- "description": "Additional filters as JSON"
403
327
  }
404
328
  },
405
329
  "returns": [
@@ -434,10 +358,6 @@
434
358
  },
435
359
  "limit": {
436
360
  "type": "number"
437
- },
438
- "page": {
439
- "type": "number",
440
- "description": "Page number for paginated results (default: 1)"
441
361
  }
442
362
  },
443
363
  "returns": [
@@ -461,18 +381,6 @@
461
381
  },
462
382
  "limit": {
463
383
  "type": "number"
464
- },
465
- "page": {
466
- "type": "number",
467
- "description": "Page number for paginated results (default: 1)"
468
- },
469
- "sort": {
470
- "type": "string",
471
- "description": "Sort field:direction (e.g., value_usd:desc)"
472
- },
473
- "filters": {
474
- "type": "object",
475
- "description": "Additional filters as JSON"
476
384
  }
477
385
  },
478
386
  "returns": [
@@ -497,14 +405,6 @@
497
405
  },
498
406
  "limit": {
499
407
  "type": "number"
500
- },
501
- "page": {
502
- "type": "number",
503
- "description": "Page number for paginated results (default: 1)"
504
- },
505
- "sort": {
506
- "type": "string",
507
- "description": "Sort field:direction (e.g., order:desc)"
508
408
  }
509
409
  },
510
410
  "returns": [
@@ -534,18 +434,6 @@
534
434
  },
535
435
  "limit": {
536
436
  "type": "number"
537
- },
538
- "page": {
539
- "type": "number",
540
- "description": "Page number for paginated results (default: 1)"
541
- },
542
- "sort": {
543
- "type": "string",
544
- "description": "Sort field:direction (e.g., total_volume_usd:desc)"
545
- },
546
- "filters": {
547
- "type": "object",
548
- "description": "Additional filters as JSON"
549
437
  }
550
438
  },
551
439
  "returns": [
@@ -593,18 +481,6 @@
593
481
  },
594
482
  "limit": {
595
483
  "type": "number"
596
- },
597
- "page": {
598
- "type": "number",
599
- "description": "Page number for paginated results (default: 1)"
600
- },
601
- "sort": {
602
- "type": "string",
603
- "description": "Sort field:direction (e.g., position_value_usd:desc)"
604
- },
605
- "filters": {
606
- "type": "object",
607
- "description": "Additional filters as JSON"
608
484
  }
609
485
  },
610
486
  "returns": [
@@ -635,18 +511,6 @@
635
511
  },
636
512
  "limit": {
637
513
  "type": "number"
638
- },
639
- "page": {
640
- "type": "number",
641
- "description": "Page number for paginated results (default: 1)"
642
- },
643
- "sort": {
644
- "type": "string",
645
- "description": "Sort field:direction (e.g., value_usd:desc)"
646
- },
647
- "filters": {
648
- "type": "object",
649
- "description": "Additional filters as JSON"
650
514
  }
651
515
  },
652
516
  "returns": [
@@ -910,10 +774,6 @@
910
774
  "filters": {
911
775
  "type": "object",
912
776
  "description": "Additional filters as JSON"
913
- },
914
- "page": {
915
- "type": "number",
916
- "description": "Page number for paginated results (default: 1)"
917
777
  }
918
778
  },
919
779
  "returns": [
@@ -959,10 +819,6 @@
959
819
  "filters": {
960
820
  "type": "object",
961
821
  "description": "Additional filters as JSON"
962
- },
963
- "page": {
964
- "type": "number",
965
- "description": "Page number for paginated results (default: 1)"
966
822
  }
967
823
  },
968
824
  "returns": [
@@ -1008,10 +864,6 @@
1008
864
  "filters": {
1009
865
  "type": "object",
1010
866
  "description": "Additional filters as JSON"
1011
- },
1012
- "page": {
1013
- "type": "number",
1014
- "description": "Page number for paginated results (default: 1)"
1015
867
  }
1016
868
  },
1017
869
  "returns": [
@@ -1052,10 +904,6 @@
1052
904
  "filters": {
1053
905
  "type": "object",
1054
906
  "description": "Additional filters as JSON"
1055
- },
1056
- "page": {
1057
- "type": "number",
1058
- "description": "Page number for paginated results (default: 1)"
1059
907
  }
1060
908
  },
1061
909
  "returns": [
@@ -1099,10 +947,6 @@
1099
947
  "filters": {
1100
948
  "type": "object",
1101
949
  "description": "Additional filters as JSON"
1102
- },
1103
- "page": {
1104
- "type": "number",
1105
- "description": "Page number for paginated results (default: 1)"
1106
950
  }
1107
951
  },
1108
952
  "returns": [
@@ -1155,10 +999,6 @@
1155
999
  "filters": {
1156
1000
  "type": "object",
1157
1001
  "description": "Additional filters as JSON"
1158
- },
1159
- "page": {
1160
- "type": "number",
1161
- "description": "Page number for paginated results (default: 1)"
1162
1002
  }
1163
1003
  },
1164
1004
  "returns": [
@@ -1246,10 +1086,6 @@
1246
1086
  "filters": {
1247
1087
  "type": "object",
1248
1088
  "description": "Additional filters as JSON"
1249
- },
1250
- "page": {
1251
- "type": "number",
1252
- "description": "Page number for paginated results (default: 1)"
1253
1089
  }
1254
1090
  },
1255
1091
  "returns": [
@@ -1281,10 +1117,6 @@
1281
1117
  "filters": {
1282
1118
  "type": "object",
1283
1119
  "description": "Additional filters as JSON"
1284
- },
1285
- "page": {
1286
- "type": "number",
1287
- "description": "Page number for paginated results (default: 1)"
1288
1120
  }
1289
1121
  },
1290
1122
  "returns": [
@@ -1327,10 +1159,6 @@
1327
1159
  "filters": {
1328
1160
  "type": "object",
1329
1161
  "description": "Additional filters as JSON"
1330
- },
1331
- "page": {
1332
- "type": "number",
1333
- "description": "Page number for paginated results (default: 1)"
1334
1162
  }
1335
1163
  },
1336
1164
  "returns": [
@@ -1364,10 +1192,6 @@
1364
1192
  "filters": {
1365
1193
  "type": "object",
1366
1194
  "description": "Additional filters as JSON"
1367
- },
1368
- "page": {
1369
- "type": "number",
1370
- "description": "Page number for paginated results (default: 1)"
1371
1195
  }
1372
1196
  },
1373
1197
  "returns": [
@@ -1406,10 +1230,6 @@
1406
1230
  "filters": {
1407
1231
  "type": "object",
1408
1232
  "description": "Additional filters as JSON"
1409
- },
1410
- "page": {
1411
- "type": "number",
1412
- "description": "Page number for paginated results (default: 1)"
1413
1233
  }
1414
1234
  },
1415
1235
  "returns": [
@@ -1460,10 +1280,6 @@
1460
1280
  "type": "number",
1461
1281
  "default": 25,
1462
1282
  "description": "Max results (1-50)"
1463
- },
1464
- "page": {
1465
- "type": "number",
1466
- "description": "Page number for paginated results (default: 1)"
1467
1283
  }
1468
1284
  },
1469
1285
  "returns": [
@@ -1490,10 +1306,6 @@
1490
1306
  },
1491
1307
  "filters": {
1492
1308
  "type": "object"
1493
- },
1494
- "page": {
1495
- "type": "number",
1496
- "description": "Page number for paginated results (default: 1)"
1497
1309
  }
1498
1310
  },
1499
1311
  "returns": [
@@ -1524,10 +1336,6 @@
1524
1336
  },
1525
1337
  "filters": {
1526
1338
  "type": "object"
1527
- },
1528
- "page": {
1529
- "type": "number",
1530
- "description": "Page number for paginated results (default: 1)"
1531
1339
  }
1532
1340
  },
1533
1341
  "returns": [
@@ -1564,6 +1372,389 @@
1564
1372
  }
1565
1373
  }
1566
1374
  },
1375
+ "prediction-market": {
1376
+ "description": "Polymarket prediction market analytics",
1377
+ "aliases": [
1378
+ "pm"
1379
+ ],
1380
+ "subcommands": {
1381
+ "ohlcv": {
1382
+ "description": "OHLCV candle data for a market",
1383
+ "options": {
1384
+ "market-id": {
1385
+ "type": "string",
1386
+ "required": true,
1387
+ "description": "Market ID"
1388
+ },
1389
+ "sort": {
1390
+ "type": "string",
1391
+ "description": "Sort field:direction (e.g., period_start:desc)"
1392
+ },
1393
+ "limit": {
1394
+ "type": "number",
1395
+ "description": "Number of results"
1396
+ }
1397
+ },
1398
+ "returns": [
1399
+ "market_id",
1400
+ "token_id",
1401
+ "side",
1402
+ "outcome_index",
1403
+ "period_start",
1404
+ "open",
1405
+ "high",
1406
+ "low",
1407
+ "close",
1408
+ "volume_usd",
1409
+ "trade_count",
1410
+ "unique_traders"
1411
+ ]
1412
+ },
1413
+ "orderbook": {
1414
+ "description": "Current orderbook levels",
1415
+ "options": {
1416
+ "market-id": {
1417
+ "type": "string",
1418
+ "required": true,
1419
+ "description": "Market ID"
1420
+ },
1421
+ "limit": {
1422
+ "type": "number",
1423
+ "description": "Number of results"
1424
+ }
1425
+ },
1426
+ "returns": [
1427
+ "market_id",
1428
+ "event_id",
1429
+ "outcome",
1430
+ "outcome_index",
1431
+ "asset_id",
1432
+ "side",
1433
+ "price",
1434
+ "size",
1435
+ "cumulative_size",
1436
+ "snapshot_timestamp"
1437
+ ]
1438
+ },
1439
+ "top-holders": {
1440
+ "description": "Top holders for a market",
1441
+ "options": {
1442
+ "market-id": {
1443
+ "type": "string",
1444
+ "required": true,
1445
+ "description": "Market ID"
1446
+ },
1447
+ "sort": {
1448
+ "type": "string",
1449
+ "description": "Sort field:direction"
1450
+ },
1451
+ "limit": {
1452
+ "type": "number",
1453
+ "description": "Number of results"
1454
+ }
1455
+ },
1456
+ "returns": [
1457
+ "market_id",
1458
+ "outcome_index",
1459
+ "address",
1460
+ "owner_address",
1461
+ "side",
1462
+ "position_size",
1463
+ "avg_entry_price",
1464
+ "current_price",
1465
+ "unrealized_pnl_usd"
1466
+ ]
1467
+ },
1468
+ "trades-by-market": {
1469
+ "description": "Recent trades for a market",
1470
+ "options": {
1471
+ "market-id": {
1472
+ "type": "string",
1473
+ "required": true,
1474
+ "description": "Market ID"
1475
+ },
1476
+ "limit": {
1477
+ "type": "number",
1478
+ "description": "Number of results"
1479
+ }
1480
+ },
1481
+ "returns": [
1482
+ "timestamp",
1483
+ "seller",
1484
+ "buyer",
1485
+ "taker_action",
1486
+ "side",
1487
+ "outcome_index",
1488
+ "size",
1489
+ "price",
1490
+ "usdc_value",
1491
+ "tx_hash",
1492
+ "market_id"
1493
+ ]
1494
+ },
1495
+ "trades-by-address": {
1496
+ "description": "Trades for a specific address",
1497
+ "options": {
1498
+ "address": {
1499
+ "type": "string",
1500
+ "required": true,
1501
+ "description": "EVM address (Polygon)"
1502
+ },
1503
+ "limit": {
1504
+ "type": "number",
1505
+ "description": "Number of results"
1506
+ }
1507
+ },
1508
+ "returns": [
1509
+ "timestamp",
1510
+ "seller",
1511
+ "buyer",
1512
+ "taker_action",
1513
+ "side",
1514
+ "outcome_index",
1515
+ "size",
1516
+ "price",
1517
+ "usdc_value",
1518
+ "tx_hash",
1519
+ "market_id",
1520
+ "market_question",
1521
+ "event_id",
1522
+ "event_title"
1523
+ ]
1524
+ },
1525
+ "market-screener": {
1526
+ "description": "Screen and discover markets",
1527
+ "options": {
1528
+ "sort-by": {
1529
+ "type": "string",
1530
+ "default": "volume_24hr",
1531
+ "enum": [
1532
+ "volume_24hr",
1533
+ "volume",
1534
+ "volume_1wk",
1535
+ "volume_1mo",
1536
+ "liquidity",
1537
+ "open_interest",
1538
+ "unique_traders_24h",
1539
+ "age_hours"
1540
+ ],
1541
+ "description": "Sort field"
1542
+ },
1543
+ "query": {
1544
+ "type": "string",
1545
+ "description": "Search text"
1546
+ },
1547
+ "status": {
1548
+ "type": "string",
1549
+ "enum": [
1550
+ "active",
1551
+ "closed"
1552
+ ],
1553
+ "description": "Market status filter (default: active)"
1554
+ },
1555
+ "limit": {
1556
+ "type": "number",
1557
+ "description": "Number of results"
1558
+ }
1559
+ },
1560
+ "returns": [
1561
+ "market_id",
1562
+ "question",
1563
+ "slug",
1564
+ "event_id",
1565
+ "event_title",
1566
+ "active",
1567
+ "closed",
1568
+ "end_date",
1569
+ "neg_risk",
1570
+ "tags",
1571
+ "volume",
1572
+ "volume_24hr",
1573
+ "volume_1wk",
1574
+ "volume_1mo",
1575
+ "volume_change_pct",
1576
+ "liquidity",
1577
+ "open_interest",
1578
+ "best_bid",
1579
+ "best_ask",
1580
+ "last_trade_price",
1581
+ "one_day_price_change",
1582
+ "unique_traders_24h",
1583
+ "created_at",
1584
+ "age_hours"
1585
+ ]
1586
+ },
1587
+ "event-screener": {
1588
+ "description": "Screen and discover events",
1589
+ "options": {
1590
+ "sort-by": {
1591
+ "type": "string",
1592
+ "default": "volume_24hr",
1593
+ "enum": [
1594
+ "volume_24hr",
1595
+ "volume",
1596
+ "volume_1wk",
1597
+ "volume_1mo",
1598
+ "liquidity",
1599
+ "open_interest",
1600
+ "unique_traders_24h",
1601
+ "age_hours"
1602
+ ],
1603
+ "description": "Sort field"
1604
+ },
1605
+ "query": {
1606
+ "type": "string",
1607
+ "description": "Search text"
1608
+ },
1609
+ "status": {
1610
+ "type": "string",
1611
+ "enum": [
1612
+ "active",
1613
+ "closed"
1614
+ ],
1615
+ "description": "Event status filter (default: active)"
1616
+ },
1617
+ "limit": {
1618
+ "type": "number",
1619
+ "description": "Number of results"
1620
+ }
1621
+ },
1622
+ "returns": [
1623
+ "event_id",
1624
+ "event_title",
1625
+ "tags",
1626
+ "neg_risk",
1627
+ "market_count",
1628
+ "markets",
1629
+ "total_volume",
1630
+ "total_volume_24hr",
1631
+ "total_volume_1wk",
1632
+ "total_volume_1mo",
1633
+ "total_volume_change_pct",
1634
+ "total_liquidity",
1635
+ "total_open_interest",
1636
+ "total_traders_24h",
1637
+ "max_age_hours",
1638
+ "top_market_id",
1639
+ "top_market_question",
1640
+ "top_market_volume_24hr"
1641
+ ]
1642
+ },
1643
+ "pnl-by-market": {
1644
+ "description": "PnL leaderboard for a market",
1645
+ "options": {
1646
+ "market-id": {
1647
+ "type": "string",
1648
+ "required": true,
1649
+ "description": "Market ID"
1650
+ },
1651
+ "limit": {
1652
+ "type": "number",
1653
+ "description": "Number of results"
1654
+ }
1655
+ },
1656
+ "returns": [
1657
+ "address",
1658
+ "owner_address",
1659
+ "side_held",
1660
+ "net_buy_cost_usd",
1661
+ "net_sell_proceeds_usd",
1662
+ "redemption_value_usd",
1663
+ "unrealized_value_usd",
1664
+ "total_pnl_usd",
1665
+ "question",
1666
+ "event_id",
1667
+ "event_title",
1668
+ "market_resolved",
1669
+ "market_id"
1670
+ ]
1671
+ },
1672
+ "pnl-by-address": {
1673
+ "description": "PnL breakdown for an address",
1674
+ "options": {
1675
+ "address": {
1676
+ "type": "string",
1677
+ "required": true,
1678
+ "description": "EVM address (Polygon)"
1679
+ },
1680
+ "limit": {
1681
+ "type": "number",
1682
+ "description": "Number of results"
1683
+ }
1684
+ },
1685
+ "returns": [
1686
+ "address",
1687
+ "market_id",
1688
+ "question",
1689
+ "event_id",
1690
+ "event_title",
1691
+ "side_held",
1692
+ "net_buy_cost_usd",
1693
+ "net_sell_proceeds_usd",
1694
+ "redemption_value_usd",
1695
+ "unrealized_value_usd",
1696
+ "total_pnl_usd",
1697
+ "market_resolved"
1698
+ ]
1699
+ },
1700
+ "position-detail": {
1701
+ "description": "Detailed position data",
1702
+ "options": {
1703
+ "market-id": {
1704
+ "type": "string",
1705
+ "required": true,
1706
+ "description": "Market ID"
1707
+ },
1708
+ "limit": {
1709
+ "type": "number",
1710
+ "description": "Number of results"
1711
+ }
1712
+ },
1713
+ "returns": [
1714
+ "address",
1715
+ "owner_address",
1716
+ "outcome",
1717
+ "outcome_index",
1718
+ "token_id",
1719
+ "balance",
1720
+ "buy_cost_usd",
1721
+ "buy_tokens",
1722
+ "sell_proceeds_usd",
1723
+ "sell_tokens",
1724
+ "avg_entry_price",
1725
+ "current_price",
1726
+ "unrealized_value_usd",
1727
+ "redemption_value_usd",
1728
+ "token_pnl_usd",
1729
+ "event_id",
1730
+ "event_title",
1731
+ "market_resolved",
1732
+ "market_id"
1733
+ ]
1734
+ },
1735
+ "categories": {
1736
+ "description": "List market categories",
1737
+ "options": {
1738
+ "limit": {
1739
+ "type": "number",
1740
+ "description": "Number of results"
1741
+ }
1742
+ },
1743
+ "returns": [
1744
+ "category",
1745
+ "active_markets",
1746
+ "total_open_interest",
1747
+ "total_volume",
1748
+ "total_volume_24hr",
1749
+ "total_volume_1wk",
1750
+ "total_traders_24h",
1751
+ "top_market_id",
1752
+ "top_market_question",
1753
+ "top_market_volume_24hr"
1754
+ ]
1755
+ }
1756
+ }
1757
+ },
1567
1758
  "points": {
1568
1759
  "description": "Nansen Points analytics",
1569
1760
  "subcommands": {
@@ -1576,10 +1767,6 @@
1576
1767
  },
1577
1768
  "limit": {
1578
1769
  "type": "number"
1579
- },
1580
- "page": {
1581
- "type": "number",
1582
- "description": "Page number for paginated results (default: 1)"
1583
1770
  }
1584
1771
  },
1585
1772
  "returns": [
@@ -1622,7 +1809,7 @@
1622
1809
  },
1623
1810
  "wallet": {
1624
1811
  "type": "string",
1625
- "description": "Wallet name (or \"walletconnect\"/\"wc\" for WalletConnect, EVM only). A configured wallet is required \u2014 run `nansen wallet create` if you haven't set one up yet."
1812
+ "description": "Wallet name (or \"walletconnect\"/\"wc\" for WalletConnect, EVM only). A configured wallet is required run `nansen wallet create` if you haven't set one up yet."
1626
1813
  }
1627
1814
  },
1628
1815
  "prerequisites": [
package/src/wallet.js CHANGED
@@ -546,7 +546,7 @@ export function buildWalletCommands(deps = {}) {
546
546
  if (result.isDefault) log(` ★ Set as default wallet`);
547
547
  log('');
548
548
  log(' Fund this wallet to start making API calls or trading:');
549
- log(` Base (recommended, lower fees): send USDC to ${result.evm}`);
549
+ log(` Base: send USDC to ${result.evm}`);
550
550
  log(` Solana: send USDC to ${result.solana}`);
551
551
  log('');
552
552
  if (password === null) {