nansen-cli 1.31.0 → 1.32.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,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.32.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#451](https://github.com/nansen-ai/nansen-cli/pull/451) [`73600d9`](https://github.com/nansen-ai/nansen-cli/commit/73600d9cd13248a265332ec0728c602b16f44868) Thanks [@kome12](https://github.com/kome12)! - Add `nansen research profiler dex-trades` command for DEX trade history
8
+
9
+ ## 1.31.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [#443](https://github.com/nansen-ai/nansen-cli/pull/443) [`0ee84db`](https://github.com/nansen-ai/nansen-cli/commit/0ee84db6cdab06054c6ae79c6d871bae0b4f3edb) Thanks [@araa47](https://github.com/araa47)! - Skip native gas pre-check for trades >= $10 USD, where gasless/solver-paid routes (e.g. Relay) are viable. When gas is insufficient on smaller trades, the error now also suggests increasing the trade value as an alternative to topping up gas.
14
+
3
15
  ## 1.31.0
4
16
 
5
17
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nansen-cli",
3
- "version": "1.31.0",
3
+ "version": "1.32.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",
package/src/api.js CHANGED
@@ -973,6 +973,20 @@ export class NansenAPI {
973
973
  });
974
974
  }
975
975
 
976
+ async addressDexTrades(params = {}) {
977
+ const { address, chain = 'ethereum', filters = {}, orderBy, pagination, days = 30, date } = params;
978
+ if (address) requireValidAddress(address, chain);
979
+ const dateRange = date || buildDateRange(days);
980
+ return this.request('/api/v1/profiler/dex-trades', {
981
+ address,
982
+ chain,
983
+ date: dateRange,
984
+ filters,
985
+ order_by: orderBy,
986
+ pagination
987
+ });
988
+ }
989
+
976
990
  // ============= Token God Mode Endpoints =============
977
991
 
978
992
  async tokenScreener(params = {}) {
package/src/cli.js CHANGED
@@ -1148,6 +1148,10 @@ export function buildCommands(deps = {}) {
1148
1148
  'pnl-summary': () => apiInstance.addressPnlSummary({ address, chain, orderBy, pagination, days }),
1149
1149
  'perp-positions': () => apiInstance.addressPerpPositions({ address, filters, orderBy, pagination }),
1150
1150
  'perp-trades': () => apiInstance.addressPerpTrades({ address, filters, orderBy, pagination, days }),
1151
+ 'dex-trades': () => {
1152
+ const date = parseDateOption(options.date, days);
1153
+ return apiInstance.addressDexTrades({ address, chain, filters, orderBy, pagination, days, date });
1154
+ },
1151
1155
  'batch': () => {
1152
1156
  let addresses = [];
1153
1157
  if (options.addresses) {
@@ -1186,7 +1190,7 @@ export function buildCommands(deps = {}) {
1186
1190
  return compareWallets(apiInstance, { addresses: addrs, chain, days });
1187
1191
  },
1188
1192
  'help': () => ({
1189
- commands: ['balance', 'labels', 'transactions', 'pnl', 'search', 'historical-balances', 'related-wallets', 'counterparties', 'pnl-summary', 'perp-positions', 'perp-trades', 'batch', 'trace', 'compare'],
1193
+ commands: ['balance', 'labels', 'transactions', 'pnl', 'search', 'historical-balances', 'related-wallets', 'counterparties', 'pnl-summary', 'perp-positions', 'perp-trades', 'dex-trades', 'batch', 'trace', 'compare'],
1190
1194
  description: 'Wallet profiling endpoints',
1191
1195
  example: 'nansen research profiler compare --addresses "0xABC...,0xDEF..." --chain ethereum'
1192
1196
  })
package/src/schema.json CHANGED
@@ -203,6 +203,21 @@
203
203
  }
204
204
  }
205
205
  },
206
+ "dex-trades": {
207
+ "endpoint": "/api/v1/profiler/dex-trades",
208
+ "description": "DEX trade history for a wallet",
209
+ "options": {
210
+ "address": {
211
+ "required": true
212
+ },
213
+ "chain": {
214
+ "default": "ethereum"
215
+ },
216
+ "days": {
217
+ "default": 30
218
+ }
219
+ }
220
+ },
206
221
  "search": {
207
222
  "endpoint": "/api/v1/search/entity-name",
208
223
  "description": "Search for entities by name",
@@ -136,6 +136,10 @@ const FEE_BUFFER = { solana: 0.005, base: 0.00004 };
136
136
  const HIGH_PERCENTAGE_THRESHOLD = 95;
137
137
  const AUTO_ADJUST_THRESHOLD_PERCENT = 2;
138
138
 
139
+ // Trades at or above this USD value can use gasless/solver-paid routes (e.g. Relay),
140
+ // so the native gas pre-check is skipped for them.
141
+ export const GASLESS_MIN_TRADE_USD = 10;
142
+
139
143
  /**
140
144
  * Check if an address is USDC or the native token for a chain (case-insensitive for EVM).
141
145
  */
@@ -306,12 +310,19 @@ export async function resolvePercentAmount({ chain, from, walletAddress, percent
306
310
  *
307
311
  * Returns { hasSufficientNative } or throws on validation failure.
308
312
  * Best-effort: if RPC fails, returns passing result.
313
+ *
314
+ * Gasless bypass: trades >= $10 USD can use solver-paid options (e.g. Relay),
315
+ * so the gas check is skipped in that case.
309
316
  */
310
- export async function validateGasBalance({ chain, walletAddress }) {
317
+ export async function validateGasBalance({ chain, walletAddress, tradeValueUsd }) {
311
318
  const normalizedChain = chain.toLowerCase();
312
319
  const minGas = MIN_GAS_AMOUNTS[normalizedChain];
313
320
  if (minGas === undefined) return { hasSufficientNative: true };
314
321
 
322
+ // High-value trades can use gasless/solver-paid routes — skip the check.
323
+ const tradeUsd = parseFloat(tradeValueUsd) || 0;
324
+ if (tradeUsd >= GASLESS_MIN_TRADE_USD) return { hasSufficientNative: true };
325
+
315
326
  const balance = await fetchNativeBalance(normalizedChain, walletAddress);
316
327
 
317
328
  // RPC failure — proceed without validation.
@@ -323,7 +334,7 @@ export async function validateGasBalance({ chain, walletAddress }) {
323
334
 
324
335
  const symbol = NATIVE_SYMBOLS[normalizedChain] || 'native token';
325
336
  throw new Error(
326
- `Insufficient ${symbol} for gas fees. Wallet has ${balance} ${symbol} but needs at least ${minGas} ${symbol}. Fund the wallet before trading.`
337
+ `Insufficient ${symbol} for gas fees. Wallet has ${balance} ${symbol} but needs at least ${minGas} ${symbol}. Either fund the wallet with ${symbol} or trade a value of $${GASLESS_MIN_TRADE_USD}+ to use gasless options.`
327
338
  );
328
339
  }
329
340
 
package/src/trading.js CHANGED
@@ -1331,8 +1331,10 @@ CROSS-CHAIN NOTES (when using --to-chain):
1331
1331
  response.quotes.forEach((q, i) => log(formatQuote(q, i)));
1332
1332
 
1333
1333
  // Gas balance validation — check that the wallet has enough native token for gas.
1334
+ // High-value trades (>= $10) can use gasless/solver-paid routes and bypass this check.
1334
1335
  try {
1335
- await validateGasBalance({ chain, walletAddress });
1336
+ const tradeValueUsd = response.quotes[0]?.inUsdValue;
1337
+ await validateGasBalance({ chain, walletAddress, tradeValueUsd });
1336
1338
  } catch (gasErr) {
1337
1339
  throw new CommandError(`Error: ${gasErr.message}`, 'INSUFFICIENT_GAS');
1338
1340
  }