nansen-cli 1.34.0 → 1.36.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.
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Request-id, credit, rate-limit, and notice metadata, read from Nansen API
3
+ * response headers.
4
+ *
5
+ * The API reports what a call actually cost, what quota is left, and an id that
6
+ * identifies the call end to end. Until now the CLI dropped those headers on the
7
+ * floor and showed only the static per-endpoint estimate published in the
8
+ * OpenAPI spec (see cost-cache.js), which is a quote rather than a charge.
9
+ *
10
+ * readResponseMeta(response) — parse the headers, or null if none are present
11
+ * creditWarning(meta) — stderr warning string when the balance is short, else null
12
+ *
13
+ * Every header is optional. Some auth rails charge no credits, some responses
14
+ * are served before quota is resolved, and older deployments may send neither
15
+ * the rate-limit triplet nor the request id — so a missing header means
16
+ * "unknown", never zero.
17
+ */
18
+
19
+ /** Header names, as documented in the API reference. */
20
+ const CREDITS_USED = 'x-nansen-credits-used';
21
+ const CREDITS_REMAINING = 'x-nansen-credits-remaining';
22
+ const RATE_LIMIT = 'x-ratelimit-limit';
23
+ const RATE_REMAINING = 'x-ratelimit-remaining';
24
+ const RATE_RESET = 'x-ratelimit-reset';
25
+ const UPGRADE_HINT = 'x-nansen-upgrade-hint';
26
+ const PLAN_NOTICE = 'x-nansen-plan-notice';
27
+ const API_KEY_NOTICE = 'x-nansen-api-key-notice';
28
+ const REQUEST_ID = 'x-request-id';
29
+
30
+ /**
31
+ * Read a header as a non-negative integer, or null when absent/unparseable.
32
+ * Tolerates any header bag with a .get() — a real Headers, or a Map in tests.
33
+ */
34
+ function intHeader(response, name) {
35
+ const raw = stringHeader(response, name);
36
+ if (raw === null) return null;
37
+ const value = Number.parseInt(raw, 10);
38
+ return Number.isInteger(value) && value >= 0 ? value : null;
39
+ }
40
+
41
+ /**
42
+ * Read a header as a trimmed non-empty string, or null when absent.
43
+ * Tolerates any header bag with a .get() — a real Headers, or a Map in tests.
44
+ */
45
+ function stringHeader(response, name) {
46
+ const raw = response?.headers?.get?.(name);
47
+ if (raw == null) return null;
48
+ const value = String(raw).trim();
49
+ return value === '' ? null : value;
50
+ }
51
+
52
+ /**
53
+ * Extract request-id, credit, rate-limit, and notice metadata from a fetch Response.
54
+ * Returns null when the response carries none of it, so callers can skip
55
+ * attaching an object full of nulls.
56
+ */
57
+ export function readResponseMeta(response) {
58
+ const used = intHeader(response, CREDITS_USED);
59
+ const remaining = intHeader(response, CREDITS_REMAINING);
60
+ const limit = intHeader(response, RATE_LIMIT);
61
+ const rateRemaining = intHeader(response, RATE_REMAINING);
62
+ const resetSeconds = intHeader(response, RATE_RESET);
63
+ const upgradeHint = stringHeader(response, UPGRADE_HINT);
64
+ const planNotice = stringHeader(response, PLAN_NOTICE);
65
+ const apiKeyNotice = stringHeader(response, API_KEY_NOTICE);
66
+ const requestId = stringHeader(response, REQUEST_ID);
67
+
68
+ const meta = {};
69
+ if (requestId !== null) {
70
+ // The single value that identifies this call to Nansen support. Opaque —
71
+ // never parse it or assume a format.
72
+ meta.requestId = requestId;
73
+ }
74
+ if (used !== null || remaining !== null) {
75
+ meta.credits = { used, remaining };
76
+ }
77
+ if (limit !== null || rateRemaining !== null || resetSeconds !== null) {
78
+ // resetSeconds is a delta in seconds — how long the tripped window needs to
79
+ // drain — not a wall-clock timestamp.
80
+ meta.rateLimit = { limit, remaining: rateRemaining, resetSeconds };
81
+ }
82
+ if (upgradeHint !== null || planNotice !== null || apiKeyNotice !== null) {
83
+ meta.notices = {
84
+ ...(upgradeHint !== null && { upgradeHint }),
85
+ ...(planNotice !== null && { planNotice }),
86
+ ...(apiKeyNotice !== null && { apiKeyNotice }),
87
+ };
88
+ }
89
+ return Object.keys(meta).length > 0 ? meta : null;
90
+ }
91
+
92
+ /**
93
+ * Yield notice strings for any server-set advisory headers.
94
+ * Each yields a `⚠️ <message>` line for stderr.
95
+ * Order: apiKeyNotice (most urgent) → upgradeHint → planNotice.
96
+ */
97
+ export function noticeWarnings(meta) {
98
+ const notices = meta?.notices;
99
+ if (!notices) return [];
100
+ const out = [];
101
+ if (notices.apiKeyNotice) out.push(`⚠️ ${notices.apiKeyNotice}`);
102
+ if (notices.upgradeHint) out.push(`ℹ️ ${notices.upgradeHint}`);
103
+ if (notices.planNotice) out.push(`ℹ️ ${notices.planNotice}`);
104
+ return out;
105
+ }
106
+
107
+ /**
108
+ * Warn only when the remaining balance will not cover another call of the size
109
+ * just made.
110
+ */
111
+ export function creditWarning(meta) {
112
+ const credits = meta?.credits;
113
+ if (!credits) return null;
114
+ const { used, remaining } = credits;
115
+ if (remaining === null) return null;
116
+ if (remaining === 0) {
117
+ return '⚠️ Out of API credits. Top up at https://app.nansen.ai/api';
118
+ }
119
+ if (used !== null && used > 0 && remaining < used) {
120
+ return `⚠️ ${remaining} API credit${remaining === 1 ? '' : 's'} left — less than this call cost (${used}). Top up at https://app.nansen.ai/api`;
121
+ }
122
+ return null;
123
+ }
package/src/rpc-urls.js CHANGED
@@ -19,17 +19,24 @@
19
19
  * working while new code uses the standardised NANSEN_BASE_RPC name.
20
20
  */
21
21
 
22
- const DEFAULT_EVM_RPC = 'https://eth.public-rpc.com';
23
- const DEFAULT_BASE_RPC = 'https://mainnet.base.org';
24
- const DEFAULT_BSC_RPC = 'https://bsc-dataseed.binance.org';
25
- const DEFAULT_XLAYER_RPC = 'https://rpc.xlayer.tech';
26
- const DEFAULT_SOLANA_RPC = 'https://api.mainnet-beta.solana.com';
22
+ const DEFAULT_EVM_RPC = 'https://eth.public-rpc.com';
23
+ const DEFAULT_BASE_RPC = 'https://mainnet.base.org';
24
+ const DEFAULT_BSC_RPC = 'https://bsc-dataseed.binance.org';
25
+ const DEFAULT_XLAYER_RPC = 'https://rpc.xlayer.tech';
26
+ const DEFAULT_SOLANA_RPC = 'https://api.mainnet-beta.solana.com';
27
+ const DEFAULT_ARBITRUM_RPC = 'https://arb1.arbitrum.io/rpc';
28
+ const DEFAULT_POLYGON_RPC = 'https://polygon-rpc.com';
29
+ const DEFAULT_BNB_RPC = 'https://bsc-dataseed.bnbchain.org';
27
30
 
31
+ // `bsc` (x402.js) and `bnb` (bridge/perp) are both chain 56 — both keys are read.
28
32
  export const CHAIN_RPCS = {
29
- ethereum: process.env.NANSEN_EVM_RPC || DEFAULT_EVM_RPC,
30
- evm: process.env.NANSEN_EVM_RPC || DEFAULT_EVM_RPC, // generic EVM fallback
31
- base: process.env.NANSEN_BASE_RPC || process.env.NANSEN_RPC_BASE || DEFAULT_BASE_RPC,
32
- bsc: process.env.NANSEN_BSC_RPC || DEFAULT_BSC_RPC,
33
- xlayer: process.env.NANSEN_XLAYER_RPC || DEFAULT_XLAYER_RPC,
34
- solana: process.env.NANSEN_SOLANA_RPC || DEFAULT_SOLANA_RPC,
33
+ ethereum: process.env.NANSEN_EVM_RPC || DEFAULT_EVM_RPC,
34
+ evm: process.env.NANSEN_EVM_RPC || DEFAULT_EVM_RPC, // generic EVM fallback
35
+ base: process.env.NANSEN_BASE_RPC || process.env.NANSEN_RPC_BASE || DEFAULT_BASE_RPC,
36
+ bsc: process.env.NANSEN_BSC_RPC || DEFAULT_BSC_RPC,
37
+ xlayer: process.env.NANSEN_XLAYER_RPC || DEFAULT_XLAYER_RPC,
38
+ solana: process.env.NANSEN_SOLANA_RPC || DEFAULT_SOLANA_RPC,
39
+ arbitrum: process.env.NANSEN_ARBITRUM_RPC || DEFAULT_ARBITRUM_RPC,
40
+ polygon: process.env.NANSEN_POLYGON_RPC || DEFAULT_POLYGON_RPC,
41
+ bnb: process.env.NANSEN_BNB_RPC || DEFAULT_BNB_RPC,
35
42
  };
package/src/schema.json CHANGED
@@ -1,5 +1,414 @@
1
1
  {
2
2
  "commands": {
3
+ "perp": {
4
+ "description": "Hyperliquid perpetual trading commands",
5
+ "subcommands": {
6
+ "order": {
7
+ "submitsTo": "https://api.hyperliquid.xyz/exchange",
8
+ "apiEndpoints": [
9
+ "/api/v1/perp/meta",
10
+ "/api/v1/perp/builder-fee",
11
+ "/api/v1/sanctions/screen"
12
+ ],
13
+ "description": "Place a perp order (limit or market, with optional take-profit/stop-loss)",
14
+ "options": {
15
+ "coin": {
16
+ "type": "string",
17
+ "required": true,
18
+ "description": "Asset symbol, e.g. BTC, ETH (alias: --symbol)"
19
+ },
20
+ "side": {
21
+ "type": "string",
22
+ "required": true,
23
+ "enum": [
24
+ "buy",
25
+ "long",
26
+ "sell",
27
+ "short"
28
+ ],
29
+ "description": "buy/long opens a long, sell/short opens a short"
30
+ },
31
+ "size": {
32
+ "type": "string",
33
+ "required": true,
34
+ "description": "Position size in base asset units"
35
+ },
36
+ "price": {
37
+ "type": "string",
38
+ "required": true,
39
+ "description": "Limit price (or mark price for market orders)"
40
+ },
41
+ "type": {
42
+ "type": "string",
43
+ "default": "limit",
44
+ "enum": [
45
+ "limit",
46
+ "market"
47
+ ],
48
+ "description": "Order type"
49
+ },
50
+ "tif": {
51
+ "type": "string",
52
+ "default": "Gtc",
53
+ "enum": [
54
+ "Gtc",
55
+ "Ioc",
56
+ "Alo"
57
+ ],
58
+ "description": "Time-in-force"
59
+ },
60
+ "slippage": {
61
+ "type": "string",
62
+ "default": "0.03",
63
+ "description": "Slippage tolerance for market orders as a decimal in [0,1] (0.03 = 3%)"
64
+ },
65
+ "take-profit": {
66
+ "type": "string",
67
+ "description": "Take-profit trigger price"
68
+ },
69
+ "stop-loss": {
70
+ "type": "string",
71
+ "description": "Stop-loss trigger price"
72
+ },
73
+ "wallet": {
74
+ "type": "string",
75
+ "description": "Wallet name (defaults to the configured default wallet)"
76
+ }
77
+ }
78
+ },
79
+ "cancel": {
80
+ "submitsTo": "https://api.hyperliquid.xyz/exchange",
81
+ "apiEndpoints": [
82
+ "/api/v1/perp/meta",
83
+ "/api/v1/sanctions/screen"
84
+ ],
85
+ "description": "Cancel an open order by order id",
86
+ "options": {
87
+ "coin": {
88
+ "type": "string",
89
+ "required": true,
90
+ "description": "Asset symbol (alias: --symbol)"
91
+ },
92
+ "oid": {
93
+ "type": "string",
94
+ "required": true,
95
+ "description": "Order id to cancel"
96
+ },
97
+ "wallet": {
98
+ "type": "string",
99
+ "description": "Wallet name"
100
+ }
101
+ }
102
+ },
103
+ "close": {
104
+ "submitsTo": "https://api.hyperliquid.xyz/exchange",
105
+ "apiEndpoints": [
106
+ "/api/v1/perp/positions",
107
+ "/api/v1/perp/meta",
108
+ "/api/v1/perp/builder-fee",
109
+ "/api/v1/sanctions/screen"
110
+ ],
111
+ "description": "Close a position (reduce-only market order)",
112
+ "options": {
113
+ "coin": {
114
+ "type": "string",
115
+ "required": true,
116
+ "description": "Asset symbol (alias: --symbol)"
117
+ },
118
+ "size": {
119
+ "type": "string",
120
+ "required": true,
121
+ "description": "Size to close in base asset units"
122
+ },
123
+ "price": {
124
+ "type": "string",
125
+ "required": true,
126
+ "description": "Mark price"
127
+ },
128
+ "side": {
129
+ "type": "string",
130
+ "required": true,
131
+ "enum": [
132
+ "buy",
133
+ "sell"
134
+ ],
135
+ "description": "sell closes a long, buy closes a short"
136
+ },
137
+ "slippage": {
138
+ "type": "string",
139
+ "default": "0.03",
140
+ "description": "Slippage tolerance as a decimal in [0,1] (0.03 = 3%)"
141
+ },
142
+ "wallet": {
143
+ "type": "string",
144
+ "description": "Wallet name"
145
+ }
146
+ }
147
+ },
148
+ "leverage": {
149
+ "submitsTo": "https://api.hyperliquid.xyz/exchange",
150
+ "apiEndpoints": [
151
+ "/api/v1/perp/meta",
152
+ "/api/v1/sanctions/screen"
153
+ ],
154
+ "description": "Set leverage and margin mode for an asset",
155
+ "options": {
156
+ "coin": {
157
+ "type": "string",
158
+ "required": true,
159
+ "description": "Asset symbol (alias: --symbol)"
160
+ },
161
+ "leverage": {
162
+ "type": "string",
163
+ "required": true,
164
+ "description": "Leverage multiplier (positive integer, capped at the asset maximum)"
165
+ },
166
+ "margin-type": {
167
+ "type": "string",
168
+ "default": "cross",
169
+ "enum": [
170
+ "cross",
171
+ "isolated"
172
+ ],
173
+ "description": "Margin mode"
174
+ },
175
+ "wallet": {
176
+ "type": "string",
177
+ "description": "Wallet name"
178
+ }
179
+ }
180
+ },
181
+ "transfer": {
182
+ "submitsTo": "https://api.hyperliquid.xyz/exchange",
183
+ "apiEndpoints": [
184
+ "/api/v1/sanctions/screen"
185
+ ],
186
+ "description": "Move USDC between a wallet's Spot and Perps balances",
187
+ "options": {
188
+ "direction": {
189
+ "type": "string",
190
+ "required": true,
191
+ "enum": [
192
+ "spot-to-perp",
193
+ "perp-to-spot"
194
+ ],
195
+ "description": "Transfer direction"
196
+ },
197
+ "amount": {
198
+ "type": "string",
199
+ "required": true,
200
+ "description": "USDC amount to transfer"
201
+ },
202
+ "wallet": {
203
+ "type": "string",
204
+ "description": "Wallet name (defaults to the configured default wallet)"
205
+ }
206
+ }
207
+ },
208
+ "approve-builder-fee": {
209
+ "submitsTo": "https://api.hyperliquid.xyz/exchange",
210
+ "apiEndpoints": [
211
+ "/api/v1/perp/builder-fee",
212
+ "/api/v1/sanctions/screen"
213
+ ],
214
+ "description": "Authorize the Nansen builder fee (one-time; auto-fired on the first order/close)",
215
+ "options": {
216
+ "wallet": {
217
+ "type": "string",
218
+ "description": "Wallet name (defaults to the configured default wallet)"
219
+ }
220
+ }
221
+ },
222
+ "positions": {
223
+ "endpoint": "/api/v1/perp/positions",
224
+ "description": "View open positions",
225
+ "options": {
226
+ "wallet": {
227
+ "type": "string",
228
+ "description": "Wallet name"
229
+ }
230
+ }
231
+ },
232
+ "orders": {
233
+ "endpoint": "/api/v1/perp/orders",
234
+ "description": "View open/resting orders",
235
+ "options": {
236
+ "wallet": {
237
+ "type": "string",
238
+ "description": "Wallet name"
239
+ }
240
+ }
241
+ },
242
+ "account": {
243
+ "endpoint": "/api/v1/perp/account",
244
+ "description": "View account state (account value, unrealized PnL, margin, withdrawable)",
245
+ "options": {
246
+ "wallet": {
247
+ "type": "string",
248
+ "description": "Wallet name"
249
+ }
250
+ }
251
+ },
252
+ "meta": {
253
+ "endpoint": "/api/v1/perp/meta",
254
+ "description": "View available perp assets (id, size decimals, max leverage)",
255
+ "options": {
256
+ "filter": {
257
+ "type": "string",
258
+ "description": "Filter assets by name substring (also shows the full matching set)"
259
+ },
260
+ "all": {
261
+ "type": "boolean",
262
+ "description": "Show all assets instead of the first 20"
263
+ }
264
+ }
265
+ }
266
+ },
267
+ "notes": "Signed locally and submitted directly to Hyperliquid. apiEndpoints lists the Nansen API routes each command reads (compliance screening, market metadata, builder-fee status)."
268
+ },
269
+ "bridge": {
270
+ "description": "Move funds between Base and Hyperliquid",
271
+ "notes": "Supported routes: base -> hyperliquid (deposit); hyperliquid -> base, hyperliquid -> ethereum, hyperliquid -> arbitrum (withdrawal). Any other combination is rejected. Deposits broadcast an EVM transaction from the local wallet, so they require a locally signable origin chain; withdrawals sign a Hyperliquid action and never transact on the destination chain.",
272
+ "routes": [
273
+ {
274
+ "origin": "base",
275
+ "destination": "hyperliquid",
276
+ "direction": "deposit"
277
+ },
278
+ {
279
+ "origin": "hyperliquid",
280
+ "destination": "base",
281
+ "direction": "withdrawal"
282
+ },
283
+ {
284
+ "origin": "hyperliquid",
285
+ "destination": "ethereum",
286
+ "direction": "withdrawal"
287
+ },
288
+ {
289
+ "origin": "hyperliquid",
290
+ "destination": "arbitrum",
291
+ "direction": "withdrawal"
292
+ }
293
+ ],
294
+ "subcommands": {
295
+ "quote": {
296
+ "endpoint": "/api/v1/perp/bridge/quote",
297
+ "description": "Get a bridge quote and cache it locally for execute (quotes expire after 1 hour)",
298
+ "options": {
299
+ "from-chain": {
300
+ "type": "string",
301
+ "required": true,
302
+ "enum": [
303
+ "base",
304
+ "hyperliquid"
305
+ ],
306
+ "description": "Source chain (alias: --from)"
307
+ },
308
+ "to-chain": {
309
+ "type": "string",
310
+ "required": true,
311
+ "enum": [
312
+ "hyperliquid",
313
+ "base",
314
+ "ethereum",
315
+ "arbitrum"
316
+ ],
317
+ "description": "Destination chain (alias: --to)"
318
+ },
319
+ "from-token": {
320
+ "type": "string",
321
+ "required": true,
322
+ "description": "Source token symbol (USDC) or address (alias: --token)"
323
+ },
324
+ "to-token": {
325
+ "type": "string",
326
+ "default": "USDC",
327
+ "description": "Destination token symbol or address"
328
+ },
329
+ "amount": {
330
+ "type": "string",
331
+ "required": true,
332
+ "description": "Amount in base units by default. USDC is 6 decimals on EVM chains but 8 on Hyperliquid, so prefer --amount-unit to avoid the per-chain magnitude trap."
333
+ },
334
+ "amount-unit": {
335
+ "type": "string",
336
+ "enum": [
337
+ "token",
338
+ "usd"
339
+ ],
340
+ "description": "Interpret --amount as a human token amount or a USD amount. Omit for base units."
341
+ },
342
+ "slippage": {
343
+ "type": "number",
344
+ "default": 50,
345
+ "description": "Slippage in whole basis points, 0-10000 (50 = 0.5%)"
346
+ },
347
+ "recipient": {
348
+ "type": "string",
349
+ "description": "Destination wallet address (defaults to the signing wallet)"
350
+ },
351
+ "wallet": {
352
+ "type": "string",
353
+ "description": "Wallet name (defaults to the configured default wallet)"
354
+ }
355
+ },
356
+ "prerequisites": [
357
+ "A wallet must be configured. Run: nansen wallet create"
358
+ ]
359
+ },
360
+ "execute": {
361
+ "endpoint": "/api/v1/perp/bridge/execute",
362
+ "apiEndpoints": [
363
+ "/api/v1/perp/bridge/execute",
364
+ "/api/v1/perp/bridge/status",
365
+ "/api/v1/sanctions/screen"
366
+ ],
367
+ "description": "Execute a cached bridge quote. Screens the signing wallet, signs, submits, then polls to completion.",
368
+ "notes": "The wallet must match the one the quote was created for. A deposit broadcasts its EVM transaction straight to a public RPC rather than through the Nansen API; only the Hyperliquid signature legs are proxied. Quotes are single-use. If a deposit transaction is stuck in the mempool, replace it by requesting a fresh quote and executing it with --nonce set to the stuck nonce and a higher --priority-fee; a replacement must reuse the nonce and outbid the original by roughly 10%.",
369
+ "options": {
370
+ "quote": {
371
+ "type": "string",
372
+ "required": true,
373
+ "description": "Quote ID returned by bridge quote"
374
+ },
375
+ "wallet": {
376
+ "type": "string",
377
+ "description": "Wallet name (defaults to the configured default wallet)"
378
+ },
379
+ "priority-fee": {
380
+ "type": "string",
381
+ "description": "Priority fee in gwei, overriding the quoted one (EVM deposit legs only)"
382
+ },
383
+ "max-fee": {
384
+ "type": "string",
385
+ "description": "Fee cap in gwei, overriding the computed one (EVM deposit legs only)"
386
+ },
387
+ "nonce": {
388
+ "type": "string",
389
+ "description": "Sign at this nonce instead of the next one, to replace a stuck transaction (EVM deposit legs only)"
390
+ }
391
+ },
392
+ "prerequisites": [
393
+ "A wallet must be configured. Run: nansen wallet create"
394
+ ]
395
+ },
396
+ "status": {
397
+ "endpoint": "/api/v1/perp/bridge/status",
398
+ "description": "Check the status of a bridge transfer",
399
+ "options": {
400
+ "request-id": {
401
+ "type": "string",
402
+ "description": "Bridge request ID (required unless --tx-hash is given)"
403
+ },
404
+ "tx-hash": {
405
+ "type": "string",
406
+ "description": "Source chain transaction hash (required unless --request-id is given)"
407
+ }
408
+ }
409
+ }
410
+ }
411
+ },
3
412
  "research": {
4
413
  "description": "Research and analytics commands",
5
414
  "subcommands": {
@@ -936,7 +1345,7 @@
936
1345
  "description": "Reference date for label and pricing resolution (YYYY-MM-DD)"
937
1346
  },
938
1347
  "block-timestamp": {
939
- "description": "Block timestamp (YYYY-MM-DD HH:MM:SS) \u2014 skips slow hash-resolution step if provided"
1348
+ "description": "Block timestamp (YYYY-MM-DD HH:MM:SS) skips slow hash-resolution step if provided"
940
1349
  },
941
1350
  "chain": {
942
1351
  "default": "ethereum",
@@ -965,7 +1374,7 @@
965
1374
  }
966
1375
  },
967
1376
  "alerts": {
968
- "description": "Smart alert management \u2014 create, update, toggle, delete alerts",
1377
+ "description": "Smart alert management create, update, toggle, delete alerts",
969
1378
  "subcommands": {
970
1379
  "list": {
971
1380
  "description": "List all alerts",
@@ -1116,7 +1525,7 @@
1116
1525
  },
1117
1526
  "to-chain": {
1118
1527
  "type": "string",
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."
1528
+ "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."
1120
1529
  },
1121
1530
  "from": {
1122
1531
  "type": "string",
@@ -1139,7 +1548,7 @@
1139
1548
  },
1140
1549
  "wallet": {
1141
1550
  "type": "string",
1142
- "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."
1551
+ "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."
1143
1552
  },
1144
1553
  "to-wallet": {
1145
1554
  "type": "string",
@@ -1192,7 +1601,7 @@
1192
1601
  },
1193
1602
  "aggregator": {
1194
1603
  "type": "string",
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."
1604
+ "description": "lifi or relay. Overrides auto-detection use when polling from a different machine or after the 30-day local record TTL has expired."
1196
1605
  }
1197
1606
  }
1198
1607
  },
@@ -1424,7 +1833,7 @@
1424
1833
  }
1425
1834
  },
1426
1835
  "agent": {
1427
- "description": "Nansen AI research agent \u2014 ask questions about wallets, tokens, and on-chain activity",
1836
+ "description": "Nansen AI research agent ask questions about wallets, tokens, and on-chain activity",
1428
1837
  "options": {
1429
1838
  "expert": {
1430
1839
  "type": "boolean",