nansen-cli 1.27.0 → 1.28.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/src/privy.js CHANGED
@@ -125,6 +125,15 @@ export class PrivyClient {
125
125
  });
126
126
  }
127
127
 
128
+ async signSolanaMessage(walletId, messageBuffer) {
129
+ const messageBase64 = Buffer.from(messageBuffer).toString('base64');
130
+ return this._request("POST", `/wallets/${walletId}/rpc`, {
131
+ method: "signMessage",
132
+ chain_type: "solana",
133
+ params: { message: messageBase64, encoding: "base64" },
134
+ });
135
+ }
136
+
128
137
  }
129
138
 
130
139
  // ============= Helpers =============
package/src/schema.json CHANGED
@@ -500,6 +500,19 @@
500
500
  "default": true
501
501
  }
502
502
  }
503
+ },
504
+ "top-tokens": {
505
+ "endpoint": "/api/v1/nansen-score/top-tokens",
506
+ "description": "Top tokens ranked by Nansen Score (public endpoint, any authenticated API key)",
507
+ "options": {
508
+ "market-cap": {
509
+ "description": "Filter by market cap group",
510
+ "enum": ["lowcap", "midcap", "largecap"]
511
+ },
512
+ "limit": {
513
+ "default": 25
514
+ }
515
+ }
503
516
  }
504
517
  },
505
518
  "description": "Token God Mode - deep analytics for any token"
@@ -839,7 +852,7 @@
839
852
  },
840
853
  "to-chain": {
841
854
  "type": "string",
842
- "description": "Destination blockchain for cross-chain swap (solana or base). Omit for same-chain."
855
+ "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. Minimum ~$5 per cross-chain trade (Li.Fi bridge)."
843
856
  },
844
857
  "from": {
845
858
  "type": "string",
@@ -906,6 +919,138 @@
906
919
  "description": "Destination chain (solana or base)"
907
920
  }
908
921
  }
922
+ },
923
+ "limit-order": {
924
+ "description": "Limit order management (Solana only)",
925
+ "subcommands": {
926
+ "create": {
927
+ "description": "Place a new limit order",
928
+ "options": {
929
+ "from": {
930
+ "type": "string",
931
+ "required": true,
932
+ "description": "Token to sell (address or symbol)"
933
+ },
934
+ "to": {
935
+ "type": "string",
936
+ "required": true,
937
+ "description": "Token to buy (address or symbol)"
938
+ },
939
+ "amount": {
940
+ "type": "string",
941
+ "required": true,
942
+ "description": "Amount in base units (e.g. lamports)"
943
+ },
944
+ "trigger-price": {
945
+ "type": "number",
946
+ "required": true,
947
+ "description": "Trigger price in USD"
948
+ },
949
+ "trigger-condition": {
950
+ "type": "string",
951
+ "required": true,
952
+ "description": "Trigger when price is 'above' or 'below' target"
953
+ },
954
+ "trigger-mint": {
955
+ "type": "string",
956
+ "required": true,
957
+ "description": "Token whose price triggers the order (e.g. SOL)"
958
+ },
959
+ "slippage-bps": {
960
+ "type": "number",
961
+ "description": "Slippage tolerance in basis points (e.g. 50 = 0.5%)"
962
+ },
963
+ "expires": {
964
+ "type": "string",
965
+ "default": "30d",
966
+ "description": "Expiry duration (e.g. 24h, 7d, 30d) or epoch ms"
967
+ },
968
+ "wallet": {
969
+ "type": "string",
970
+ "description": "Wallet name (or \"walletconnect\"/\"wc\")"
971
+ }
972
+ },
973
+ "chains": ["solana"],
974
+ "prerequisites": [
975
+ "A Solana wallet must be configured. Run: nansen wallet create"
976
+ ]
977
+ },
978
+ "list": {
979
+ "description": "List your limit orders",
980
+ "options": {
981
+ "state": {
982
+ "type": "string",
983
+ "description": "Filter by state (active, past)"
984
+ },
985
+ "mint": {
986
+ "type": "string",
987
+ "description": "Filter by token mint address"
988
+ },
989
+ "limit": {
990
+ "type": "number",
991
+ "default": 20,
992
+ "description": "Max results per page"
993
+ },
994
+ "offset": {
995
+ "type": "number",
996
+ "default": 0,
997
+ "description": "Pagination offset"
998
+ },
999
+ "sort": {
1000
+ "type": "string",
1001
+ "description": "Sort field"
1002
+ },
1003
+ "dir": {
1004
+ "type": "string",
1005
+ "default": "desc",
1006
+ "description": "Sort direction (asc or desc)"
1007
+ },
1008
+ "wallet": {
1009
+ "type": "string",
1010
+ "description": "Wallet name (or \"walletconnect\"/\"wc\")"
1011
+ }
1012
+ },
1013
+ "chains": ["solana"]
1014
+ },
1015
+ "cancel": {
1016
+ "description": "Cancel an open limit order",
1017
+ "options": {
1018
+ "order": {
1019
+ "type": "string",
1020
+ "required": true,
1021
+ "description": "Order ID to cancel"
1022
+ },
1023
+ "wallet": {
1024
+ "type": "string",
1025
+ "description": "Wallet name (or \"walletconnect\"/\"wc\")"
1026
+ }
1027
+ },
1028
+ "chains": ["solana"]
1029
+ },
1030
+ "update": {
1031
+ "description": "Update trigger price or slippage on an existing order",
1032
+ "options": {
1033
+ "order": {
1034
+ "type": "string",
1035
+ "required": true,
1036
+ "description": "Order ID to update"
1037
+ },
1038
+ "trigger-price": {
1039
+ "type": "number",
1040
+ "description": "New trigger price in USD"
1041
+ },
1042
+ "slippage-bps": {
1043
+ "type": "number",
1044
+ "description": "New slippage in basis points (0-10000)"
1045
+ },
1046
+ "wallet": {
1047
+ "type": "string",
1048
+ "description": "Wallet name (or \"walletconnect\"/\"wc\")"
1049
+ }
1050
+ },
1051
+ "chains": ["solana"]
1052
+ }
1053
+ }
909
1054
  }
910
1055
  }
911
1056
  },
package/src/telemetry.js CHANGED
@@ -158,9 +158,13 @@ function buildContext() {
158
158
 
159
159
  /**
160
160
  * Convert a command string like "smart-money netflow" to a path like "/smart-money/netflow".
161
+ * Agent ("agent …") always maps to "/agent" so prompts are not exploded into path segments.
161
162
  */
162
163
  function commandToPath(command) {
163
- return '/' + command.replace(/\s+/g, '/');
164
+ if (typeof command === 'string' && /^agent(?:\s+|$)/.test(command.trimStart())) {
165
+ return '/agent';
166
+ }
167
+ return '/' + String(command).replace(/\s+/g, '/');
164
168
  }
165
169
 
166
170
  /**
package/src/trading.js CHANGED
@@ -994,6 +994,16 @@ EXAMPLES:
994
994
  nansen trade quote --chain base --from ETH --to USDC --amount 1000000000000000000
995
995
  nansen trade quote --chain base --to-chain solana --from USDC --to USDC --amount 1000000
996
996
  nansen trade quote --chain solana --to-chain base --from SOL --to ETH --amount 1000000000
997
+
998
+ CROSS-CHAIN NOTES (when using --to-chain):
999
+ Supported combos:
1000
+ native → native (ETH <-> SOL) — requires $5+ per trade
1001
+ USDC → USDC (both directions)
1002
+ USDC → native (USDC → ETH or SOL)
1003
+ native → USDC (ETH/SOL → USDC)
1004
+ non-native → non-native — not supported (use USDC as intermediate)
1005
+ Bridge provider: Li.Fi
1006
+ Typical bridge time: 1-5 minutes
997
1007
  `, 'MISSING_ARGS');
998
1008
  }
999
1009
 
@@ -1157,6 +1167,10 @@ EXAMPLES:
1157
1167
  };
1158
1168
  if (isCrossChain) {
1159
1169
  params.toChainIndex = toChainConfig.index;
1170
+ // Opt out of Relay aggregator: CLI bypasses backend /execute so the
1171
+ // Redis aggregator hint is never set, and /bridge/status defaults to
1172
+ // LiFi — polling a Relay txHash there returns NOT_FOUND.
1173
+ params.disabledAggregators = 'relay';
1160
1174
  if (toWallet) {
1161
1175
  params.toWalletAddress = toWallet;
1162
1176
  log(` Destination wallet: ${toWallet}`);
package/src/transfer.js CHANGED
@@ -302,7 +302,7 @@ function modPowBig(base, exp, mod) {
302
302
  return result;
303
303
  }
304
304
 
305
- async function getTokenInfo(rpcUrl, mint) {
305
+ export async function getTokenInfo(rpcUrl, mint) {
306
306
  // Get mint account to determine token program and decimals
307
307
  const info = await rpcCall(rpcUrl, 'getAccountInfo', [mint, { encoding: 'jsonParsed' }]);
308
308
  if (!info || !info.value) throw new Error(`Token mint ${mint} not found`);
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  import { wcExec } from './walletconnect-exec.js';
12
+ import { base58Encode } from './wallet.js';
12
13
 
13
14
  const SOLANA_MAINNET_CHAIN = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';
14
15
 
@@ -153,3 +154,27 @@ export async function sendSolanaTransactionViaWalletConnect(txBase58, timeoutMs
153
154
 
154
155
  throw new Error('Unexpected response from walletconnect Solana sign');
155
156
  }
157
+
158
+ /**
159
+ * Sign a Solana message via WalletConnect.
160
+ *
161
+ * Used for challenge-response authentication (e.g., Jupiter Limit Order V2).
162
+ * Returns the raw Ed25519 signature as base58.
163
+ *
164
+ * @param {Buffer} messageBuffer - Raw message bytes to sign
165
+ * @param {number} [timeoutMs=120000] - Timeout for user approval
166
+ * @returns {{ signature: string }} Base58-encoded signature
167
+ */
168
+ export async function signSolanaMessageViaWalletConnect(messageBuffer, timeoutMs = 120000) {
169
+ const payload = {
170
+ message: base58Encode(messageBuffer),
171
+ chainId: SOLANA_MAINNET_CHAIN,
172
+ };
173
+
174
+ const output = await wcExec('walletconnect', ['sign-message', JSON.stringify(payload)], timeoutMs);
175
+ const result = parseWcJson(output);
176
+
177
+ if (result.signature) return { signature: result.signature };
178
+
179
+ throw new Error('Unexpected response from walletconnect sign-message');
180
+ }