Skip to content

Latest commit

 

History

History
1091 lines (604 loc) · 140 KB

File metadata and controls

1091 lines (604 loc) · 140 KB

Changelog

1.46.0

Minor Changes

  • #667 8dad3b9 Thanks @gulshngill! - trade execute and bridge execute now take --dry-run and --yes. --dry-run runs the sign-free preflight available from the cached quote, its public signer address, and read-only RPC calls; prints the trade or transfer that would be sent (chain, tokens, amounts, recipient, approvals, fees — plus the current allowance and revert simulation on EVM); and stops before wallet credentials or signing: no wallet password needed, the quote is not consumed, exit code 0. Real execution still resolves and revalidates the live signer. When stdin is an interactive terminal, both commands now print that plan and ask Broadcast this transaction? [y/N] before broadcasting; declining exits 1 with nothing signed. --yes (-y) or NANSEN_YES=1 skips the prompt. Non-interactive callers — agents, CI, pipes — are unchanged: they proceed without prompting, and --yes is accepted there as a no-op.

  • #501 5a79f9d Thanks @gulshngill! - Guard wallet export against accidental plaintext key disclosure. The default output is now redacted (addresses only — no decryption, no password needed). Printing private keys to stdout requires explicit acknowledgement via --reveal (which also warns on stderr when stdout is an interactive terminal), and the new --file <path> writes keys to a file created with 0600 permissions (refusing to overwrite) while keeping stdout clean. Scripts that parsed wallet export output must add --reveal or switch to --file. --file failures carry machine-readable codes: FILE_EXISTS when the path already exists, FILE_WRITE_FAILED for any other create/write error.

    This safety hardening is intentionally classified as a minor change rather than a major release: it changes an unsafe default to prevent accidental private-key disclosure while preserving explicit export through --reveal and --file.

  • #669 b821104 Thanks @gulshngill! - Show the real subcommand help for nansen research perp screener --help and nansen research perp leaderboard --help. Because perp is also a top-level trading command, the help lookup stopped at the trading command's subcommand list and fell back to printing the category listing — "Use: nansen research perp --help", the command that had just been run — so the parameters, credit cost and example were unreachable. nansen perp screener --help now resolves to the same help, with an example pointing at the research path. Boolean options now accept --flag=false and reject invalid or repeated values instead of silently falling back to the server default; value-taking options also accept the conventional --key=value spelling, while valueless switches reject inline values instead of creating unusable stale flags. Invalid changelog --since values now return a structured error and a non-zero exit status.

    The stricter validation intentionally rejects invalid, previously undocumented inputs that only appeared to succeed while being ignored; relying on that quiet fallback was relying on a bug, so this is classified as a minor change rather than a major breaking release.

Patch Changes

  • #682 3e172f2 Thanks @Bruce039! - alerts update no longer resends a PATCH through the retry loop after a transient failure, matching alerts create

  • #649 66152af Thanks @kriss39! - research profiler compare no longer turns failed API requests into an empty comparison. When every request fails the command errors with the underlying code (for example UNAUTHORIZED or RATE_LIMITED); when some fail the result carries incomplete: true, an errors list, and null for the fields that could not be computed. Shared tokens are now matched on the token address when both wallets report one, falling back to the symbol when either side omits it, so two different contracts with the same symbol are no longer reported as shared.

  • #674 ad178db Thanks @0xShadowX! - A repeated list option whose values are themselves comma-separated (--tags defi,nft --tags sports) is now flattened to defi, nft, sports. Previously the first value was kept as the literal defi,nft, so the same list was read differently depending on whether it was passed once or as repeated flags.

  • #652 d0433d4 Thanks @Bruce039! - Resolve ENS names when the profiler chain is all. The profiler commands default --chain to all, but the resolver only accepted explicit EVM chains, so research profiler labels --address vitalik.eth (and every other profiler subcommand except first-funder) failed with ENS names can only be resolved on EVM chains, not all unless --chain ethereum was passed.

  • #654 0aad196 Thanks @Bruce039! - --fields now supports dotted paths. --fields data.results.address selects that field at that position only (array elements do not add a segment), while a bare name such as --fields address keeps matching at any depth. Dotted paths were mentioned in the code but matched nothing, so --fields data.results returned an empty object.

  • #672 b10dc31 Thanks @0xShadowX! - --filters is validated as a JSON object before the request is sent. A value such as --filters '[]', --filters abc or a repeated --filters flag used to be forwarded to the API as-is and only failed there with a 422; it now fails with an INVALID_PARAMS error that shows the expected form.

  • #660 42db750 Thanks @Ahmett101! - Parse SSE data: fields with or without the optional space after the colon so standards-compliant agent streams do not produce an empty response.

  • #651 ab784a3 Thanks @kriss39! - Respect the server's Retry-After header when retrying rate-limited (429) requests. The wait was capped at the local backoff ceiling (30s), so a Retry-After: 60 led to a retry after 30s that could only hit the limiter again. The client now waits at least as long as the header asks, and if the server asks for more than maxRetryAfterMs (default 120s) it fails immediately with the retryAfterMs in the error details instead of retrying too early. A Retry-After on a 5xx response is still treated as advisory and capped at the backoff ceiling as before.

  • #663 bc4ecc8 Thanks @gulshngill! - Option values that spell a JSON keyword (--sort true, --search false, --label null) are now kept as the literal strings true/false/null instead of being converted to a boolean or null, so string options no longer crash or silently drop the value; --filters '{}' and --order-by '[...]' still parse as JSON, and --sort now rejects a repeated or non-text value with --sort must be "field" or "field:direction".

  • #671 8a4e98f Thanks @0xShadowX! - Keep the body of a non-JSON error response (gateway HTML, plain text) in the error details instead of reporting body: null, and apply the same retry policy to it as to a JSON error: a plain-text 429 is now retried, with its Retry-After respected, instead of failing on the first attempt.

  • #676 0112fa1 Thanks @0xShadowX! - Refuse to sign EVM approval, revoke, and Privy swap transactions when the quote carries no gas price, instead of defaulting to an unmineable 0.001 gwei fee that left the wallet's nonce stuck

  • #681 c82492d Thanks @kriss39! - wallet send and trade limit-order create reject an amount of zero, or one that truncates to zero base units at the token's precision, instead of broadcasting a transfer of nothing or creating a limit order with inputAmount: "0"

  • #650 d4b4925 Thanks @kriss39! - research token screener --search now honours --page. The search filter runs client-side, and previously every page returned the same first slice of matches; the candidate fetch is now widened to cover the requested page and the filtered list is sliced at the page offset.

  • #661 fe5b294 Thanks @gulshngill! - Recognise the API's full set of structured error codes. A 401 unauthenticated response once again shows Not logged in. Run: nansen login, insufficient_credits gets its do-not-retry hint, and codes that previously leaked through as raw server strings now surface as CLI codes, including the new PLAN_UPGRADE_REQUIRED, GEO_BLOCKED, QUERY_TOO_LARGE, PAYLOAD_TOO_LARGE, METHOD_NOT_ALLOWED, and CONFLICT. Retry behaviour is unchanged: it stays keyed on the HTTP status.

  • #679 5c8d22b Thanks @0xShadowX! - Fail with an actionable error when a Solana RPC cannot return an SPL mint's decimals, instead of silently assuming 9 and building a transfer or limit order with a mis-scaled amount

  • #675 938a011 Thanks @kome12! - Reject malformed or negative profiler --delay and token top-tokens --limit values instead of partially parsing them.

  • #646 3290e3c Thanks @gulshngill! - --table and --format csv error output now includes the error code, HTTP status, and details instead of only the message. CSV errors are emitted as a header row plus one record; table errors keep the leading Error: line and add one key: value line per field.

  • #662 7fd923f Thanks @gulshngill! - Sync the chains list reported by nansen schema (and mirrored in --help and the README) with the chains the Nansen API actually accepts. Drops scroll and ronin, which no endpoint serves any more, and adds the chains that were missing: algorand, aptos, arc, bitcoin, bitlayer, chiliz, citrea, gravity, hyperliquid, injective, mantra, near, robinhood, stacks, starknet, stellar, sui, ton, tron, viction. Not every chain is served by every endpoint; the API still validates --chain per endpoint.

  • #664 d034ae1 Thanks @gulshngill! - trade quote and trade execute now screen the signing wallet (and any distinct --to-wallet destination) against the compliance blocklist before requesting a quote or signing — the same fail-closed check bridge and perp already run — so a flagged address, or a screening call that fails, aborts the command before anything is signed or broadcast. Both commands now require API access for this check; authenticate with nansen login or NANSEN_API_KEY before trading.

  • #653 337271d Thanks @Bruce039! - --sort now rejects a direction other than asc/desc and an empty field name with an INVALID_PARAMS error. Previously --sort pnl_usd:sideways was uppercased and sent to the API as direction: SIDEWAYS, which only failed later with an upstream 422.

  • #648 0514c76 Thanks @kriss39! - Validate token screener --search and token who-bought-sold --buy-or-sell before the request is sent, so a JSON array/object or a repeated flag (--search '[]', --buy-or-sell '{}') and values outside the BUY/SELL enum produce an actionable INVALID_PARAMS error instead of a raw .toLowerCase()/.toUpperCase() TypeError.

  • #666 6539558 Thanks @gulshngill! - Make every wallet subcommand discoverable from the places agents look first. nansen --help now lists send, forget-password and secure on the wallet line (previously only seven of the nine were shown) and the full perp subcommand set (transfer, approve-builder-fee, orders, account, meta, screener and leaderboard were missing). It also stops describing the combined top-level perp command as a deprecated analytics alias. README lists the same wallet set, and nansen schema wallet now documents forget-password and secure with descriptions plus an example for every wallet subcommand. Help text, README, runtime command help and schema are pinned together by a new drift-guard test.

  • #677 b91e108 Thanks @0xShadowX! - Read a pretty-printed WalletConnect sign-typed-data result on the x402 payment path instead of failing after the user has already approved the payment in their wallet

  • #673 05a2056 Thanks @0xShadowX! - web search --num-results now rejects a malformed value (5abc, 2.5, abc, a repeated or valueless flag) with INVALID_PARAMS. Previously 5abc was silently truncated to 5, 2.5 to 2, and a non-numeric value fell back to the API default instead of reporting the mistake.

1.45.0

Minor Changes

  • #624 8bd2f00 Thanks @gulshngill! - Add nansen research profiler counterparties-batch — top counterparties for up to 10 wallets in a single request. Takes --addresses "0xabc,0xdef" (comma-separated or a JSON array) or --file, validates the 10-address and 90-day limits client-side, and returns rows tagged with the wallet_address they belong to (results are not aggregated across wallets). --chain defaults to all, which auto-detects the ecosystem; one ecosystem per request, as EVM and Solana addresses cannot be mixed.

Patch Changes

  • #643 b459772 Thanks @Codier! - Ignore failed and malformed OpenAPI responses when refreshing the credit-cost cache. A non-2xx response that still returned JSON replaced the cached cost map with an empty one and stamped it fresh, so credit estimates went missing for up to 24 hours and the next refresh was suppressed.

  • #634 a5a3b27 Thanks @Bruce039! - Avoid caching failed or malformed update-check responses as fresh results, so transient registry errors are retried instead of suppressing checks for 24 hours.

  • #637 a0f889d Thanks @gulshngill! - Fix the --chain allowlist on nansen research profiler counterparties-batch. It was built from the CLI's internal EVM chain list, which disagreed with the endpoint in both directions: scroll and ronin were accepted and always 422'd upstream, while every non-EVM chain the profiler serves (bitcoin, tron, sui, ton, near, injective, mantra, robinhood, arc, starknet) was rejected client-side. The allowlist is now the endpoint's own ProfilerChain enum, and --chain bsc is accepted and sent as bnb. Addresses on a chain whose format the CLI cannot check are still required to be address-shaped, so a newline --file cannot post arbitrary lines as wallet addresses; TON accepts both friendly and raw (0:/-1: plus 64 hex) addresses.

  • #645 dda318e Thanks @gulshngill! - Declare the DELETE /api/v1/smart-alert/{alertId} route the alerts delete command already calls in src/schema.json. This was the last route in the parity checker's schema-drift list; the sibling routes (list/create/update/toggle/account/web/agent) were declared in #549.

  • #640 60961cf Thanks @hulk-linus! - Fix parseArgs treating an explicit empty-string option value (--flag "") as a boolean flag and leaking the "" into positional arguments. nansen web fetch <url> --question "" now reports the blank-question error instead of Invalid URL: "".

    Register --all, --max, --gasless, --auto-slippage, and --unsafe-no-password as valueless flags. They are read only as booleans, so a following token such as nansen perp meta --all plus an asset name was parsed as their value and the switch went dead.

    Reject a blank nansen mcp verify --url "" instead of falling back to the default Nansen endpoint, which reported the default URL as verified when the caller passed an unset shell variable.

    Reject a blank --slippage or --max-auto-slippage on nansen trade quote. An empty string became 0 in the range check, satisfied the rule that --swap-mode exactOut --auto-slippage needs an explicit cap, and was then dropped when the request was built, so the ERC-20 approval was scoped by a cap that never reached the server.

    Reject a blank nansen web fetch --url "" instead of dropping it and fetching only the positional URLs.

  • #644 14bbd9b Thanks @hulk-linus! - Reject explicitly blank quote options, execute and limit-order wallet selectors, limit-order expiry and list options, wallet creation names and send options, and research chain/timeframe, days, buy-or-sell, and profiler batch/trace tuning options with an actionable error instead of selecting defaults. Preserve numeric zero slippage caps in programmatic quote requests.

  • #542 055488a Thanks @gulshngill! - Stop calling the removed points leaderboard API route. Both points leaderboard and research points leaderboard now return a structured unavailable error and exit with a failure status, without suggesting the other unavailable command as a replacement.

  • #549 28714c6 Thanks @gulshngill! - Declare the API routes alerts, account, web and agent already call in src/schema.json. The schema is what shell completions, --help and docs tooling read, so eight routes the code requests were invisible to them (and to the API/MCP/CLI parity check).

  • #647 2b84502 Thanks @kome12! - Reject invalid profiler trace width values instead of returning an empty-looking trace.

  • #642 b6c928f Thanks @kome12! - Validate nansen alerts string/array options (--chains, --token/--exclude-token, --subject/--counterparty/--caller/--contract and their --exclude-* variants, --events, --signature-hash, --token-sector/--exclude-token-sector, and alerts list --token-address/--chain) so JSON primitives (e.g. --chains true) produce actionable INVALID_PARAMS errors instead of a raw TypeError crash or being silently dropped/passed through into the alert payload.

  • #630 7cb8bb2 Thanks @kriss39! - Validate supported analytics --days values as non-negative integers with a representable date range instead of truncating malformed inputs or forwarding NaN.

  • #639 17e4f64 Thanks @kome12! - Validate more CLI string options (profiler batch --include, perp screener --sectors-filter/--sm-label-filter/--trader-label-filter, prediction-market market-screener/event-screener --tags, and --fields) so JSON primitives produce actionable INVALID_PARAMS errors instead of raw .split()/.trim() TypeErrors.

  • #632 d9c7e6e Thanks @Bruce039! - Reject malformed or valueless --date inputs instead of silently falling back to the rolling --days range.

  • #631 17cbed5 Thanks @Bruce039! - Reject malformed and non-finite prediction-market screener numeric filters before they can be serialized as null or silently ignored.

  • #629 b802bca Thanks @kriss39! - Reject malformed, fractional, non-finite, repeated, or valueless profiler trace --depth inputs while preserving the existing 1-5 clamping behavior for valid integers.

  • #633 901f63e Thanks @Bruce039! - Validate web --query and --question option types so JSON primitives produce actionable CLI errors instead of raw .trim() TypeErrors.

1.44.3

Patch Changes

  • #621 6ece0a1 Thanks @kome12! - Validate alerts list pagination flags before fetching alerts.

  • #620 bf8f40f Thanks @Radovenchyk! - Fix nansen agent throwing a raw AbortError instead of a NansenError(TIMEOUT) when the request timeout fires while reading the SSE response body (as opposed to during the initial connection). Both streaming and --json output modes now report a consistent timeout error regardless of which phase of the request the abort happened in.

  • #618 1e08a15 Thanks @Radovenchyk! - Fix consumeSSEStream silently dropping the final SSE event when the stream closes without a trailing blank line (e.g. a finish event carrying conversation_id, or a trailing delta chunk).

  • #623 9ae1dc2 Thanks @kome12! - Improve Solana raw-instruction bridge error handling for RPC failures and malformed instruction data.

  • #622 d86aae9 Thanks @kome12! - Tolerate small refunded native input amounts during bridge outcome verification.

  • #617 d048c0f Thanks @teyrebaz33! - Fix x402 auto-payment via WalletConnect signing a payment authorization from any connected EVM account instead of verifying the WalletConnect session is actually approved for the payment's chain.

    handleX402Payment resolved its signer with its own checkWalletConnection() helper and took wallet.accounts[0]?.address with no chain filtering at all -- the same defect class fixed in getWalletConnectAddress for nansen transfer/nansen trade execute (see the WalletConnect chain-scoped signing fix), just left unguarded here because this path never reused that helper. Because EVM addresses are identical across chains, a WalletConnect session approved only for, say, Base could be silently used to authorize an x402 payment on BNB Smart Chain or X Layer -- the other two EVM networks Nansen's x402 payments support.

    handleX402Payment now resolves its signer via getWalletConnectAddress('evm', chainId), scoped to the exact chain of the selected payment requirement, and refuses to pay with a clear error when no WalletConnect session is approved for that chain. The now-unused, duplicate checkWalletConnection helper was removed.

1.44.2

Patch Changes

  • #604 9d541d7 Thanks @kome12! - Bind limit-order deposits to the trusted vault destination: reject any deposit whose wallet-sourced transfer (SPL token or native SOL) does not land in a token account this same transaction creates via CreateAccountWithSeed seeded off the user's vault. Covers both the SPL-token and native-SOL deposit paths.

  • #600 c86af55 Thanks @kome12! - Isolate the response cache by credential and request context so cached responses can no longer be shared across different API keys or API origins that use the same cache directory. Cache keys now include the base URL, HTTP method, and a hashed form of the effective credentials, and use SHA-256.

  • #612 492b441 Thanks @gulshngill! - Reject hard-linked .credentials files in the wallet-password fallback write, so the credential write cannot chmod, truncate, or overwrite an unrelated file

  • #611 959225c Thanks @gulshngill! - Report from_cache telemetry from the API instance so it survives command handlers that rebuild their result, and pass it on the alerts list --table path, which previously never reported the field at all

  • #609 288f566 Thanks @gulshngill! - Fix from_cache telemetry always reporting false on cache hits

  • #586 b254240 Thanks @Kewe63! - Tighten POSIX permissions when rewriting the fallback wallet credentials file and refuse non-regular credential paths.

  • #615 9166884 Thanks @teyrebaz33! - Fix nansen transfer/nansen trade execute with --wallet walletconnect using any connected EVM account instead of verifying the WalletConnect session is actually approved for the chain being signed/broadcast on.

    getWalletConnectAddress('evm') matched any account whose CAIP-2 chain tag started with eip155:, regardless of which specific chain it was approved for. Because EVM addresses are identical across chains, a session connected only to Ethereum mainnet would be silently used to sign a transaction destined for Base (or vice versa) -- nothing downstream (including the quote/request-intent binding checks) could catch this, since they only compare addresses, not chains.

    getWalletConnectAddress now accepts an optional chainId, and when given, only returns an account the session has approved for that exact chain (mirroring the mainnet-only exact match already used for Solana in the same function). Every place that resolves a WalletConnect EVM address before signing or broadcasting a real transaction now passes the target chain ID and fails closed with a clear error instead of proceeding with a wrong-chain session: nansen transfer's sendTokensViaWalletConnect, and nansen trade execute's quote-building, pre-execute wallet-match check, and immediate pre-signing check for its EVM WalletConnect swap path.

1.44.1

Patch Changes

  • #588 0db1c74 Thanks @Kewe63! - Prevent duplicate alert creation after ambiguous network failures and keep Smart Alert mutations out of the response cache.

  • #595 1e3fadb Thanks @devorun! - Fix --cache reshaping a cached array response into an object. Endpoints that return a top-level JSON array were object-spread on a cache hit, so [a, b] came back as { 0: a, 1: b } and every Array.isArray() branch downstream stopped matching — the first call printed rows and the second printed nothing. Cached arrays now stay arrays, and primitive response bodies are returned untouched instead of being exploded into character maps.

  • #589 0cc4c18 Thanks @ygd58! - Fix nansen alerts list --limit/--offset silently misbehaving on invalid or edge-case input. --limit 0 and --offset 0 were treated as "not set" (falsy check) and silently ignored instead of honored; a non-numeric value like --limit abc silently returned zero results (Array.prototype.slice coerces NaN to 0) instead of erroring; and a negative --offset was silently accepted by slice(), which treats negative indices as "from the end" — returning the wrong records instead of rejecting the input. Both flags are now validated as non-negative integers, matching the strict-validation convention already used elsewhere in the CLI (e.g. --slippage), and throw a clear INVALID_PARAMS error otherwise.

  • #577 3c214a1 Thanks @batuhankocyigit! - Fix nansen alerts create/update silently dropping numeric range filters (--usd-min/max, --market-cap-min/max, --fdv-min/max, --token-amount-min/max, --token-age-min/max, and the --inflow/outflow/netflow-*-min/max flags) instead of rejecting bad input. These flags were converted with plain Number(val), so a typo or garbage value (e.g. --usd-min abc) became NaN, which JSON.stringify silently turns into null in the request body — the alert would get created without the filter the user thought they'd set, with no error at any point. --*-min/--*-max now reject non-numeric input with a clear Invalid --<flag> "<value>": must be a number error; valid negative values (e.g. --netflow-1h-min -5000 for a net-outflow filter) are unaffected.

  • #605 9656d08 Thanks @kome12! - Keep non-JSON 4xx responses from trade execute reusable instead of treating them as ambiguous broadcast failures.

  • #602 9c72189 Thanks @kome12! - trade limit-order cancel: give distinct, actionable errors when the refund can't be verified — a fully-filled order now says so plainly ("nothing left to refund") instead of sharing the same generic message as unparseable order metadata.

  • #598 1450b66 Thanks @kome12! - Close two dust-refund gaps in limit-order cancel verification: a native-SOL refund at or below the fee/rent slack could be "cancelled" by returning a single lamport while the rest of the escrow was rerouted, and a cancel now fails closed when the order is found but its remaining refund amount can't be computed instead of silently downgrading to a bare positive-inflow check.

  • #598 b6d5baf Thanks @kome12! - Limit-order create and cancel now verify the API-provided Solana transaction's simulated balance effect against the requested operation before signing, refusing to sign a deposit that would move unexpected funds out of the wallet or a cancel that fails to return the order's own deposited asset to it. The cancel check binds to the full expected remaining refund, not just a positive inflow, so a withdrawal that reroutes most of the escrow and returns only a dust amount of the right asset is refused. Also closes a gap where a cancel could pass on an inflow of any asset (not just the deposited one), and a tiny native-SOL deposit could pass on a fee-only outflow. The pre-cancel order lookup now paginates the active-order list, so an order beyond the first page can still be cancelled.

  • #582 8e674c2 Thanks @devorun! - Telemetry now creates ~/.nansen with mode 0700 and writes its id/session files with mode 0600, matching every other module that writes to that directory. Previously these were the only writes there that used default permissions, so when they were the first to create the directory (for example when authenticating with NANSEN_API_KEY instead of nansen login) it was left group- and world-readable.

  • #594 95bdde1 Thanks @Kewe63! - Reject invalid cache TTL values before constructing the API client.

  • #593 dfc908a Thanks @Kewe63! - Reject invalid retry counts before constructing the API client.

  • #599 bdbdcb2 Thanks @kome12! - x402 auto-pay now signs only for supported schemes and recognized payment networks (exact Solana mainnet CAIP-2 binding), and derives the EIP-712 chain id from the validated network. The EIP-712 domain version is now required across all signing backends (local, WalletConnect, Privy) so a missing version can no longer be silently defaulted to a wrong value, while a null/empty remote chain id is treated as unspecified rather than a conflict.

1.44.0

Minor Changes

  • #563 3b3e11b Thanks @hulk-linus! - Emit privacy-preserving per-leg Hyperliquid attribution through the canonical trade-perps outcome events.

  • #580 c5085c5 Thanks @gulshngill! - Add nansen completion <bash|zsh|fish>, which prints a shell completion script generated from the CLI's own command schema. Completions cover nested subcommands, per-command flags, global flags, and the enum values a flag accepts.

  • #597 8453355 Thanks @kome12! - Security: nansen mcp verify no longer sends a saved API key (from nansen login / NANSEN_API_KEY / config) to a custom --url without explicit consent. Forwarding a saved key to a non-default URL now requires --send-api-key, and no key is ever sent over plain HTTP to a non-loopback host. An inline --api-key is unaffected.

    Note: verifying a custom --url with a saved key now errors unless --send-api-key is passed (previously it warned and proceeded).

  • #557 5a73b43 Thanks @gulshngill! - Add the nansen research address-premium-labels command.

  • #555 4285d7f Thanks @gulshngill! - Add the nansen research chain-rank command.

  • #561 dd8035c Thanks @gulshngill! - Add the nansen research historical-token-ohlcv command.

  • #560 52f2f09 Thanks @gulshngill! - Add the nansen research perp-pnl-summary command.

  • #559 ed2d7a5 Thanks @gulshngill! - Add the nansen research position-intelligence command.

  • #558 e273152 Thanks @gulshngill! - Add the nansen research smart-money-pnl-leaderboard command.

  • #556 3c14359 Thanks @gulshngill! - Add the nansen research token-sectors command.

  • #562 0d0f5e6 Thanks @gulshngill! - Add the nansen research transaction-with-token-transfer-lookup command.

  • #581 8726a23 Thanks @gulshngill! - Every command option in nansen schema now carries a type and a description (140 research and wallet send options had neither), and the research points group is described. research token ohlcv --timeframe documents its real default (1d), and wallet send --chain, research search --type, and the prediction-market --neg-risk filters declare the values they accept, so --help and shell completion offer them. Fixed --neg-risk true on the prediction-market screeners, which was sent to the API as neg_risk: false because the parsed boolean was compared against the string 'true'. nansen mcp install and nansen mcp uninstall declare their positional client in the schema, and nansen completion scripts now complete it (claude-code, claude-desktop, cursor) in bash, zsh, and fish.

Patch Changes

  • #575 927ffea Thanks @kome12! - Fail closed on an ambiguous broadcast failure in swap and bridge execute. When /execute (swap) returns any 5xx (regardless of body shape — a structured 504 UPSTREAM_TIMEOUT is treated the same as a bare 502) or any other uninterpretable response — or the POST, or reading its body, throws a network error — after the signed tx was sent, or a bridge broadcast fails ambiguously, the tx may already be live. The quote is now marked spent and the run aborts — rather than trying the next candidate quote or leaving the quote reusable — so a re-execute (or agent auto-retry) can't double-broadcast. Gasless (Relay solver-paid) swaps additionally do not retry the /execute POST: the signed authorization is broadcast by Relay's own wrapping tx, so a re-POST can't be node-deduped and could trigger a second solve — a single attempt fails closed instead. A bridge send is kept reusable only when the node's error proves the tx never entered the mempool (a pre-broadcast validation rejection such as insufficient funds); in-flight txpool states like "already known" or "nonce too low" fail closed.

  • #572 2ba5c15 Thanks @teyrebaz33! - Fix nansen changelog --since <version> silently returning "No changelog entries found" for a version missing its patch number (e.g. --since 1.43 instead of --since 1.43.0), even when matching entries exist. The comparison compared the missing component against undefined, and > is always false against undefined in both directions, so a version that matched on major.minor always came out "less than" the since-value. A missing component is now treated as 0, and a --since value that isn't a valid version (e.g. --since abc) now prints a clear error instead of silently matching nothing.

    The version-comparison logic is now shared (src/semver.js) between nansen changelog --since and the update-notifier's isNewer check, which had the identical bug in its own separate parser. isNewer couldn't misfire in practice (both versions it compares are always fully-qualified x.y.z today), but it's the same defect class, so it's fixed the same way rather than left in place.

  • #569 04932c7 Thanks @memosr! - Refuse to re-execute a swap quote that has already been broadcast, mirroring the single-use guard nansen bridge execute already had. nansen trade execute now marks the quote as spent (executedAt) the instant a transaction is broadcast — before waiting for its receipt — so a RECEIPT_TIMEOUT (the tx is on-chain but the command exits non-zero) no longer leaves the quote replayable. Retrying the same --quote <id> after such a failure previously re-signed and re-broadcast the swap under a fresh nonce instead of being refused.

  • #592 60bd2ef Thanks @ygd58! - Fix the x402 auto-payment fallback in src/api.js generating multiple payment authorizations for the same request after an ambiguous outcome (issue #583). After a signed Payment-Signature was transmitted, _x402Retry previously collapsed every non-ok response — a clean rejection, a 5xx, an unreadable body — and every transport failure into a single null, and callers treated any null as "safe to try the next payment option/provider". That meant a 5xx, a timeout, or an unparseable response (any of which could mean the server already received and settled the payment) triggered signing and transmitting a second independent payment for the same logical request. Separately, a genuine successful response whose JSON body happened to be null was indistinguishable from a rejection, risking a second payment for an already-settled call.

    _x402Retry now returns a dedicated X402_PAYMENT_REJECTED sentinel only for a provably clean rejection (a non-5xx status with a readable body), and throws NansenError with the new PAYMENT_AMBIGUOUS code for anything else — a transport failure, a 5xx, or an unreadable body on either a rejection or a success. All three fallback call sites (Privy, local wallet, WalletConnect) now check against the sentinel instead of null, and re-throw a PAYMENT_AMBIGUOUS error immediately instead of silently moving on to the next provider.

  • #524 3e8dcc2 Thanks @dolmaciabdullah-byte! - Use BigInt for EVM balance in checkX402Balance to avoid precision loss on 18-decimal tokens (BSC stablecoins): parseInt(hex, 16) loses integer precision once the raw wei value exceeds Number.MAX_SAFE_INTEGER (~9.0e15 wei, i.e. ~0.009 tokens at 18 decimals), skewing the low-balance warning.

  • #568 9a45fc4 Thanks @Kewe63! - Reject non-finite limit-order trigger prices and expiry values before wallet or API activity.

  • #567 c0fe57b Thanks @Kewe63! - Keep research perp analytics-only instead of routing trading subcommands through the top-level perp dispatcher.

  • #558 002921e Thanks @gulshngill! - Reject non-integer or non-positive --limit values with an actionable error instead of forwarding them to the API.

1.43.1

Patch Changes

  • #526 a7ab05c Thanks @dolmaciabdullah-byte! - Fix formatValue displaying 1000.00K instead of 1.00M when a value like 999999.995 rounds up at the K/M boundary.

  • #548 000d01a Thanks @Sertug17! - Fix parseAmount silently producing wrong values for negative decimal inputs. Negative amounts are now rejected with a clear error.

  • #551 092535a Thanks @kome12! - Harden parseAmount input validation: reject negative amounts wrapped in whitespace (previously silently miscalculated), and reject non-numeric or malformed inputs (e.g. abc, empty string, 1., .5) with a clear error instead of throwing a raw error or silently returning 0.

  • #433 977fbc5 Thanks @aikido-autofix! - Validate the wallet name before the Privy pre-read in wallet delete and wallet send, routing both reads through getWalletFile() so the path stays confined to the wallets directory.

  • #545 642eb20 Thanks @kome12! - Update Noble crypto dependencies to the patched 2.4.x releases.

1.43.0

Minor Changes

  • #539 2ba6c40 Thanks @kome12! - x402 auto-payment now refuses to sign payments for unknown tokens/networks and enforces a configurable per-payment USD cap (NANSEN_X402_MAX_AMOUNT, default $1.00) before signing.

Patch Changes

  • #535 863ef23 Thanks @crazywriter1! - Fix EVM swap execution when quotes omit gas limits: WalletConnect and local wallet paths now fall back to eth_estimateGas (×1.5) and then 210000, matching the Privy path.

  • #541 7492bbe Thanks @kome12! - Refuse x402 auto-payments whose payment requirement is missing a payTo/pay_to recipient, matching the existing missing-amount check. Previously this fell through to the per-signing-path field validation inconsistently, and the WalletConnect path had no check at all.

1.42.0

Minor Changes

  • #508 3fc6e6b Thanks @gulshngill! - Add nansen mcp verify to verify the hosted Nansen MCP setup with an authenticated data-path check.

  • #487 bb3f33e Thanks @gulshngill! - Add nansen mcp install <client> / nansen mcp uninstall <client> for one-step setup of the hosted Nansen MCP server (https://mcp.nansen.ai/ra/mcp) in Claude Code, Claude Desktop, and Cursor. Writes are merge-only and atomic (existing servers preserved, .bak backup on install and uninstall, refuses unparseable configs), use the API key from nansen login / NANSEN_API_KEY, never print the key, and support --dry-run.

Patch Changes

  • #536 f5e48df Thanks @kome12! - bridge quote now prints a notice when a Hyperliquid USDC amount is floored to the 6-decimal precision the bridge signs, instead of adjusting the amount silently. The adjustment is unchanged (it's what keeps the persisted amount matching what gets signed); it's just no longer hidden.

  • #533 a96418d Thanks @kome12! - Bridge withdrawals now verify the Hyperliquid action's type, amount, network, and source token/routing fields against your request before signing, so a tampered quote cannot inflate a withdrawal, swap in a different token, or authorize on another account. The deposit action's EIP-712 primary type and exact ordered field list are now pinned too — not just the shared signing domain — so a quote can no longer pass every value check yet have the wallet sign a differently shaped Hyperliquid action (e.g. an agent approval) that the amount cap doesn't bound. The relayer authorization step is likewise pinned exactly to its real EIP-712 domain, field shape, and signing wallet, and its signature can only ever be submitted to the relayer's own fixed authorize endpoint — closing a gap where a malicious quote could have requested a signature over unrelated typed data and relayed it elsewhere. All of a withdrawal's steps are verified against this before any of them are signed or posted, so a bad step later in a multi-step quote (e.g. the real [authorize, sendAsset] order) can no longer let an earlier, valid-looking step reach the relayer or Hyperliquid first.

    Also fixes a false rejection: Hyperliquid withdrawals whose --amount was given in base units (the default, no --amount-unit) and whose last two digits weren't zero were rejected at execute time as an amount mismatch, because the amount wasn't floored to the 6-decimal precision the bridge actually sends. Base-unit amounts are now floored the same way --amount-unit amounts already were, so these withdrawals execute.

  • #530 4312b50 Thanks @kome12! - Trade safety: tolerate a bounded native-token fee on cross-chain bridge swaps. The pre-signing swap-outcome check rejected any non-input token leaving the wallet, which could reject a legitimate bridge that pays its network fee in the native token on a token-input route. The tolerance is capped and applies only to the native token on bridges; every other token, and all same-chain swaps, stay strict.

  • #537 2d630d5 Thanks @kome12! - Fix nansen mcp verify routing after merging MCP install commands.

  • #538 853c48a Thanks @kome12! - Harden the Hyperliquid bridge deposit leg: EVM approvals are now re-scoped to the requested amount (never unlimited) and the deposit target contract/method is pinned, so a tampered quote can't drain the wallet.

  • #534 e23af5c Thanks @gulshngill! - Credential hygiene: nansen login verification failures cannot relay the API key, invalid-key remediation points at key management, and login guidance leads with paths that avoid shell history. Every request that carries a credential — API key, agent, limit-order JWT/X-API-Key, MCP verify, and Privy auth — now refuses to follow HTTP redirects, so a credential can't be relayed to a redirect target. Interactive password and API-key prompts stay masked (no cleartext echo) even when stdout is redirected.

  • #529 45b8584 Thanks @gulshngill! - Docs: stop pointing at the retired Cursor install deep link, pin the mcp-remote bridge to the version mcp install writes, and correct the header-formatting note (whitespace after the colon is trimmed; the key belongs in env, not in the argument list).

  • #531 9bb44a7 Thanks @crazywriter1! - Honor the original HTTP method on x402 paid retries so GET/DELETE/PATCH requests are not resent as POST after payment.

1.41.1

Patch Changes

  • #527 02efb6d Thanks @kome12! - Cross-chain (bridge) swaps now run swap-outcome verification instead of skipping it entirely. The output-arrival check is still skipped (the output settles on the destination chain), but the input-outflow cap and no-sibling-drain checks now run on the source-chain leg, closing a gap where a compromised quote's bridge instructions could move more than the declared input. Bridges also now enforce an intent-relative lower bound on the source-chain input outflow (an exactIn bridge must spend ~the requested input, so a large fee-only or partial no-op no longer verifies) and still validate the quote's output-amount integrity, and the native-SOL bridge log no longer contradicts itself about whether the output check ran. Note the lower bound relaxes by a native-SOL fee/rent allowance (~0.013 SOL), so on a small native-SOL leg at or below that allowance the floor effectively collapses to a bare "outflow > 0" — the tightest bound possible for a native leg whose fees are indistinguishable from the transfer. --swap-mode is now validated against exactIn/exactOut at the CLI, and both the swap-outcome verifier and the pre-signing request-intent completeness checks fail closed on an unrecognized mode in a persisted quote so a garbage value cannot bypass the exactIn input floor — even when outcome verification is skipped or degraded.

    Because bridges now go through the simulation, a bridge quote that reverts in simulation returns proceed: false and is dropped (the signing loop falls through to the next quote); only a simulation that cannot run at all (NO_SIM_RPC / SIM_RPC_ERROR / NOT_SIM_CAPABLE) degrades to proceed-without-verification, matching same-chain swaps. This is a new, fail-closed outcome for bridges specifically.

  • #513 55eb953 Thanks @kome12! - Fix trade execute crashing on Solana-source bridge quotes from the Relay aggregator, which return raw uncompiled instructions instead of a ready-to-sign transaction. These are now compiled client-side before signing.

1.41.0

Minor Changes

  • #512 ba42a9c Thanks @kome12! - Validate Solana swap quotes against the original request before signing (local, Privy, and WalletConnect wallets). The CLI now checks that a quote's chain, token pair, amounts, and target wallet match what was requested at quote time and refuses to sign when they don't, bringing Solana in line with the existing EVM checks. --swap-mode exactOut now also requires --max-input on Solana (previously EVM-only), so the maximum spend is bounded by a value you supply rather than one taken from the quote itself.

  • #514 1bc7337 Thanks @kome12! - trade execute and trade limit-order on Solana now statically check the aggregator's compiled instructions before signing, and reject a transaction that grants a token delegate, changes a token account's authority, closes an account with its rent redirected to a stranger, or sets an excessive compute-budget priority fee — closing a class of drain vector a balance-delta simulation alone can't see.

  • #522 820bf05 Thanks @kome12! - Verify a Solana swap's simulated on-chain outcome before signing (local, Privy, and WalletConnect wallets), mirroring the existing EVM balance-delta check. The CLI simulates the aggregator's transaction and confirms the wallet's balance changes match the quote — input spent within your max, expected output received, no other asset drained — refusing to sign on a mismatch or an in-simulation revert. Covered by the existing --no-verify-outcome flag; degrades with a warning (and still signs) when no simulation-capable RPC is available, so an RPC outage never blocks a trade. New env var: NANSEN_SOLANA_SIM_RPC.

Patch Changes

  • #519 55ab7db Thanks @kome12! - trade execute: confirm EVM transactions against the hash derived locally from the signed bytes instead of trusting the broadcaster's reported hash, and fail closed if they disagree. Once a transaction has been broadcast, every uncertain outcome now aborts the whole execute instead of silently trying the next quote (which could broadcast a second transaction): a hash mismatch, a signed transaction we cannot re-derive a hash for, and a receipt-confirmation timeout (distinguished from a genuine on-chain revert) are all fatal across the swap, approval, and revoke paths. Broadcaster hashes are also compared prefix-insensitively, so a bare (0x-less) hash is no longer a false mismatch.

  • #521 977e326 Thanks @aikido-autofix! - Fix potential path traversal in safeQuotesPath by rejecting absolute relative paths (Windows cross-drive escape).

  • #497 223a9d5 Thanks @crazywriter1! - Reject --oid values above 2^53-1 on perp cancel: large Hyperliquid uint64 order IDs would be silently rounded by JS Number, potentially cancelling the wrong order.

1.40.1

Patch Changes

  • #516 48722ef Thanks @kome12! - Fix cross-chain bridges into native SOL being refused at execute time. The quote/intent binding compared the wrapped-SOL mint (how --to SOL resolves) against the System Program address that aggregators use as the native-SOL sentinel and rejected them as different tokens. Both spellings are now treated as the same asset.

1.40.0

Minor Changes

  • #509 430c300 Thanks @kome12! - trade execute now revokes an existing on-chain ERC-20 allowance before re-approving when it is more than 10x the current trade's scoped amount, such as a legacy unlimited approval or an allowance granted by another app. Most trades are unaffected. Opt out with --no-revoke-excessive-allowance.

    After each revoke or reapproval, the CLI reads the resulting allowance back on-chain and fails closed (instead of proceeding to the swap) if it doesn't match what was expected or can't be read.

Patch Changes

  • #498 a964dd1 Thanks @crazywriter1! - Use pending nonce block tag for EVM sends: back-to-back transfers no longer risk reusing the same nonce when mempool transactions are queued.

  • #493 bc89fef Thanks @crazywriter1! - Validate --slippage-bps on limit-order create: values outside 0-10000 now fail with a clear error before any auth/API call.

1.39.0

Minor Changes

  • #495 3306897 Thanks @kome12! - Add EVM swap-outcome verification to trade execute. Before broadcasting a swap on an EVM chain (Base), the CLI now simulates the transaction and confirms the wallet's balance changes match the quote — the input is spent within your maximum, at least the expected output is received, and no other token or NFT leaves the wallet — refusing to sign when they don't. This runs on top of the existing pre-broadcast checks and needs a simulation-capable RPC (NANSEN_BASE_SIM_RPC); when none is available it degrades with a warning rather than blocking the trade. Skip it with --no-verify-outcome. Solana is unaffected.

Patch Changes

  • #495 e8cf217 Thanks @kome12! - Harden swap-outcome verification error handling: a revert reported by the simulation endpoint as a top-level JSON-RPC error (rather than a per-call status) now fails closed (blocks the swap) instead of degrading, and a non-2xx simulation response (e.g. HTTP 401 "Invalid API key") now degrades with the real status and message instead of a misleading "returned no call result" warning.

  • #499 de0bcc5 Thanks @gulshngill! - Fix profiler labels: call /api/v1/profiler/address/labels with its v1 request body — the beta endpoint previously used was removed from the Nansen API. profiler batch --include labels now returns the label array itself instead of the raw {pagination, data} envelope.

  • #506 f407edb Thanks @gulshngill! - Add a canonical MCP setup section to the README — endpoint https://mcp.nansen.ai/ra/mcp, NANSEN-API-KEY auth, per-client setup paths for Claude Code, Claude Tag, and generic or stdio-only clients, plus a pointer to the connection docs for Claude Desktop and Cursor — and point the out-of-credits and low-credit warnings at the credits tab of the billing page, app.nansen.ai/api?tab=api, instead of the bare app.nansen.ai/api.

  • #500 9ccf8a2 Thanks @gulshngill! - Document global pagination options in nansen schema.

1.38.0

Minor Changes

  • #486 b752d81 Thanks @gulshngill! - Add nansen auth status and nansen doctor. auth status is fully offline: it reports whether an API key is configured and where it comes from (env var vs config file, masked), the active base URL, x402 wallet readiness, and OS keychain availability. doctor runs health checks over the whole setup — Node version, config file validity and permissions, wallet storage and password hygiene (flags the insecure .credentials file), keychain availability, Privy env credentials, caches, and telemetry — with an actionable fix per finding, plus a safe unauthenticated connectivity probe (no credits consumed; skip it with --offline). --json returns machine-readable checks.

  • #494 67027e6 Thanks @kome12! - Harden EVM swap signing: scope ERC-20 approvals to the trade amount instead of granting an unlimited allowance, and validate the swap target before signing (reject an empty/zero address, a non-contract target, or a target equal to the token being sold). As a result, ERC-20 sells on Base now include a per-swap approval transaction. Native ETH swaps and all Solana swaps are unaffected. Note: this scopes approvals granted from now on; a pre-existing unlimited approval from an earlier version is not automatically reduced.

    Also tightens the input validation on the quote a swap is signed from. Every approval-signing path (local, Privy, WalletConnect) now shares one encoder that requires a well-formed 20-byte spender, keeps the approved amount bounded (never unlimited) and within the request cap, and produces fixed-width approval calldata. EVM execution now requires complete request intent persisted by the quote command and revalidates each quote against it (chain, wallet, token pair, mode, and amount), so the signed transaction remains bound to what was requested. A same-chain swap whose transaction is a bare ERC-20 transfer/approve rather than a routed swap is refused (bridge routes excluded).

    The swap-target contract check now fails closed: it retries and, if it still can't confirm the target carries contract code, refuses to sign rather than proceeding on an unverified target.

    EVM (Base) exactOut swaps now require an explicit maximum input (spend ceiling) via --max-input in base units of the sell token. The quote persists that maxInputAmount, and the execute path refuses to sign, approve, or broadcast any quote whose input exceeds it, for native and ERC-20 swaps across all three EVM signing paths. Solana exactOut is unaffected and does not require the flag (there is no ERC-20 approval to scope on that path). Quotes already above the cap are dropped at quote time (and, when none fit, a clear MAX_INPUT_EXCEEDED error is returned) rather than saved and rejected only at execute. Relatedly, a quote missing a field the request-intent check needs (sell/buy token address or the bound amount) is now rejected rather than skipped, and the exactOut output binding accepts more-than-requested output (only a shortfall is rejected, since the input is independently capped).

    The execute path also binds the signer to the wallet the quote was built for: it now refuses to sign a quote whose persisted wallet doesn't match the current signer (e.g. the default wallet changed between quote and execute), since the quoted transaction is constructed for a specific sender.

Patch Changes

  • #494 54b9d41 Thanks @kome12! - Fix exactOut --max-input so it bounds the slippage-buffered approval, not the bare quote input. Previously an exactOut ERC-20 quote whose raw input equalled the cap (e.g. 1,000,000 at 3% slippage) passed the max-input filter and was saved, but execution scoped a larger approval (1,030,000) that the approval encoder then rejected for exceeding the cap — bricking the trade across local, Privy, and WalletConnect flows. Both the quote-time filter and the execute-time spend check now measure the same buffered amount the approval encoder does, so a quote that clears the cap can always be signed.

1.37.0

Minor Changes

  • #481 ccaa40b Thanks @kome12! - Add research profiler first-funder command to look up the first wallet that funded an EVM address. The funder is the earliest address to send native gas, resolved across chains, returned with its Nansen label and the funding transaction.

  • #485 b49c758 Thanks @MarcLlopart! - nansen perp order and perp close now print the Hyperliquid order id (oid) and fill (size @ avg price) returned by the exchange, plus a ready-to-run nansen perp cancel command for any resting order — mirroring how spot trading surfaces its quote id. TP/SL bracket legs are labelled (parent / take-profit / stop-loss). Order ids are uint64; an id beyond JavaScript's safe integer range (2^53) is detected and its exact value and cancel hint are withheld rather than shown rounded, so a wrong id is never presented as actionable.

Patch Changes

  • #483 d0d10a2 Thanks @kome12! - Unknown-command errors now detect when a whole multi-word command was passed as a single argument (a common shell-quoting mistake, e.g. nansen "trade --help" or an unquoted variable under zsh) and point at the likely cause instead of a bare "Unknown command".

  • #484 bc5f774 Thanks @kome12! - Write the cost-map and update-check cache files atomically (temp file + rename) so concurrent nansen processes can no longer observe an empty or truncated cache.

  • #465 4105193 Thanks @dobbydobap! - Fix nansen quote --help, nansen trade quote --help, and nansen execute --help to print the trade usage and exit with code 0 instead of erroring with exit code 1.

  • #485 c9aaf58 Thanks @MarcLlopart! - nansen perp order / perp close now emit an anonymous perp_order_completed telemetry event after the Hyperliquid /exchange response is parsed. Perp orders bypass the Nansen API on submit (the CLI signs and posts straight to Hyperliquid), so this client-side event is the only signal that an order was placed. The payload is deliberately minimal — only the trade side and the Hyperliquid order id (omitted when it exceeded JS safe-integer precision); no asset, price, size, or fill detail is sent. The telemetry disclosure (CLI help footer and module docs) names exactly these fields. Honours the existing DO_NOT_TRACK / NANSEN_NO_TELEMETRY opt-out; order rejections remain covered by cli_command_failed.

  • #478 758ce13 Thanks @boleklebovski! - Document the missing trade quote and trade execute options in src/schema.json: --swap-mode, --slippage, --auto-slippage, --max-auto-slippage, --quote, --quote-index and --no-simulate. These options are already implemented and documented for humans, but were absent from the machine-readable schema.

  • #488 f653b37 Thanks @gulshngill! - Warn on logout when NANSEN_API_KEY remains active in the environment.

1.36.2

Patch Changes

  • #479 e2590ed Thanks @gulshngill! - Surface richer API response metadata: the X-Nansen-Credits-Cost header now drives credit reporting (a concise Credits: N (this call) stderr line after each data command, falling back to the cached spec estimate when the header is absent), requestId is hoisted to the top level of the JSON error envelope (including nansen agent failures, which previously dropped it), and error codes now come from the API's stable code field when present — known codes map onto the existing error code enum, unknown ones pass through verbatim instead of being flattened. stdout JSON is unchanged; all new reporting goes to stderr.

1.36.1

Patch Changes

1.36.0

Minor Changes

  • #467 54386c0 Thanks @kome12! - Output shape change: every command failure now serializes through the same error envelope — {success: false, error, code, status, details}. Previously a CommandError printed its structured payload at the top level instead, so errors from trade, limit-order and the API-key flows (NOT_A_TTY, API_KEY_REQUIRED, INVALID_API_KEY, VERIFICATION_FAILED) came back in a different shape from everything else.

    Nothing is lost — the previous top-level payload is preserved verbatim under details — but anything parsing those errors positionally needs to read details instead of the root object. The new perp and bridge commands raise CommandError throughout, so without this they would have been the third distinct error shape in the CLI.

    One deliberate exception: a missing-argument usage banner (MISSING_PARAM, MISSING_ARGS) prints as plain text when stdout is an interactive terminal and no output format was requested, because those messages are multi-line help written to be read and serializing them renders every newline as a literal \n. Piped output, and any run with --pretty, --table, --format csv or --stream, still gets the envelope — so nothing consuming the CLI programmatically sees a different shape.

Patch Changes

  • #467 8ab8bb4 Thanks @kome12! - bridge execute now re-screens the wallet against the compliance blocklist immediately before signing, and fails closed if the check can't be completed — matching what the perp commands already did. Bridge quotes stay valid for an hour and the EVM deposit leg broadcasts straight to a public RPC, so previously nothing re-checked the wallet between the quote and the transaction that moves funds.

    It also refuses to execute a quote with a wallet other than the one the quote was created for. Previously the signing wallet was resolved from --wallet or the current default independently of the quote, so a changed default (or an explicit --wallet) could sign with a different wallet than the one screened.

  • #467 44805e2 Thanks @kome12! - nansen schema now describes the bridge command group — its three subcommands, their options, and the supported routes — so agents driving the CLI off the schema can discover it.

    The mutating perp subcommands (order, cancel, close, leverage, transfer, approve-builder-fee) now declare submitsTo: "https://api.hyperliquid.xyz/exchange" in place of an endpoint, which is where they actually send a signed action, alongside an apiEndpoints list of the Nansen routes each one reads for compliance screening, market metadata and builder-fee status. Read-only subcommands keep their endpoint unchanged.

  • #467 7185359 Thanks @kome12! - nansen bridge supports base -> hyperliquid for deposits, and hyperliquid -> base, hyperliquid -> ethereum, hyperliquid -> arbitrum for withdrawals. Any other combination is rejected at quote time with the supported routes listed.

    The route set is asymmetric because the two directions need different things from the client: a deposit broadcasts an EVM transaction and so needs a locally signable origin chain, while a withdrawal signs a Hyperliquid action and never touches the destination chain.

  • #467 19738dd Thanks @kome12! - EVM transactions are now signed as EIP-1559 (type 2) when the quote supplies fee caps, instead of being flattened into a legacy (type 0) transaction with a single gas price.

    A legacy transaction pays exactly its gasPrice, so once the base fee rises above that value it is not merely slow — it can never be included at that nonce. A type-2 transaction pays base fee plus priority up to its cap, so it tolerates the fee moving between signing and inclusion. This affects trade execute and bridge execute, which share the signer.

    bridge execute also stops discarding the fee fields the bridge quote provides. It previously overwrote them with a bare eth_gasPrice reading, producing a transaction priced at roughly the current base fee with almost no priority fee — which is what it takes to sit unmined on Base. Quoted fees are now kept, with the priority fee raised to a floor that Base will actually schedule and the cap lifted to cover both that and base-fee movement.

    Two related robustness changes: signing now refuses outright when a quote carries no gas information at all, rather than falling back to a 1 wei gas price that produces a permanently unmineable transaction; and the receipt wait is longer, because by the time it runs the transaction is already broadcast, so giving up early reports a failure without undoing anything.

  • #467 f649eea Thanks @kome12! - Add a client-side Hyperliquid action builder (src/hl-action.js), the groundwork for submitting perp trades straight to Hyperliquid instead of round-tripping through the Nansen backend to build them.

    • msgpack encoder that reproduces the reference msgpack.packb output byte-for-byte (insertion-ordered maps, smallest-width ints, utf-8 strings), so an action's connectionId hash matches the known-good path.
    • actionHash + l1Eip712 reproduce the phantom-agent EIP-712 payload (Exchange domain, mainnet source: "a") that the existing signer already knows how to sign.
    • Order-wire assembly for market/limit orders, cancels, closes and leverage updates, including TP/SL (normalTpsl) grouping and the builder-code attachment.
    • Price/size rounding (roundPrice/roundSize) ported with Python-parity banker's rounding, so over-precise values that Hyperliquid would reject are rounded identically to the server path.
    • approveBuilderFee and usdClassTransfer user-signed payload builders.

    Pinned against the live prepare endpoints with golden-vector tests that assert both the built action and its connectionId match byte-for-byte.

  • #467 3bd3909 Thanks @kome12! - Add src/hl-client.js, the single direct-to-Hyperliquid submission path: submitExchange() POSTs a signed action straight to api.hyperliquid.xyz/exchange from the user's machine instead of routing it through the Nansen backend. Reads and market-data stay on the proxy.

    It reproduces the backend proxy's failure handling that it replaces — throwing on a top-level status: "err" and on a per-action error nested in response.data.statuses[].error (a rejected order that Hyperliquid otherwise reports under a top-level "ok") — so a rejected order can never be mistaken for a fill. The submit is deliberately not retried, since each carries a unique nonce and is not idempotent. The HL base URL is overridable via NANSEN_HL_API_URL (for testnet / tests).

  • #467 b5d6946 Thanks @kome12! - Harden perp, swap, and bridge command safety:

    • perp order/close now reject an invalid --side instead of silently opening the opposite direction, and perp leverage rejects an invalid --margin-type instead of silently switching to isolated.
    • Perp numeric args (--size, --price, --leverage, --oid) are validated as positive numbers, with specific error messages instead of a generic usage banner.
    • Perp commands now require an EVM wallet, with a clear error instead of querying for an "undefined" address.
    • trade quote validates --quote-index, --slippage, and --max-auto-slippage, rejecting out-of-range values (e.g. a percent-vs-decimal slippage mix-up).
    • bridge quote now validates --slippage client-side (whole basis points in [0, 10000]), rejecting non-numeric or out-of-range values with a clear message instead of forwarding them to an opaque backend 422 (matching how perp validates --slippage).
    • perp order/close warn before signing when --size (or --price for order) is finer than the asset's Hyperliquid precision, which the exchange silently rounds.
    • perp order/close now report the size and price the order actually executes at (post-rounding, slippage-adjusted for market orders) instead of echoing the raw input, so the printed values match the fill.
    • limit-order list no longer aborts the whole render when one order has a non-integer amount.
    • Quote loaders reject a cross-type quote (a bridge quote sent to trade execute, or a swap quote sent to bridge execute).
    • bridge execute now refuses a quote that has already been executed, preventing an accidental double-bridge on retry.
    • bridge quote accepts human amounts via --amount-unit token|usd (default stays base units), resolving token decimals per chain so the same 5 isn't 100x off between chains (USDC is 6 decimals on EVM, 8 on Hyperliquid). Hyperliquid USDC is floored to the bridge's 6-decimal precision to avoid a round-up-past-balance rejection.
    • perp meta supports --all and --filter <text> so assets past the first 20 (e.g. HYPE) are listable.
    • Deprecated top-level aliases now print a deprecation notice on stderr when run, not only in --help.
    • limit-order rejects a zero-duration or past expiry instead of creating an order that expires immediately.
    • A password with leading/trailing whitespace is no longer mangled when read back from the OS keychain.
    • Nested backend error messages containing an apostrophe are no longer truncated.
  • #467 b577954 Thanks @kome12! - perp and bridge no longer serve any API response from the --cache store, and bridge execute no longer retries its submission.

    • Compliance screening is always a live check. Every mutating command re-screens the signing wallet immediately before signing; with --cache that verdict could previously come from a cache written up to five minutes earlier, which is exactly the window the check exists to close.
    • bridge execute sets retry: false. It proxies to Relay's /authorize and Hyperliquid's /exchange, neither of which is idempotent, so an automatic re-send on a 500 or 502 could submit the same signed action twice.
    • Bridge status polling now observes progress under --cache. The cache key is endpoint plus body, so every poll for a given request id hit the same key and the loop would re-read one stale verdict for the whole TTL.
    • Perp reads (positions, orders, account, meta) and bridge quotes bypass the cache too: they either report live balances to the user or feed a signing decision — close sizes its order from the positions read, and asset ids come from meta.

    bridge execute also refuses to sign a step whose EIP-712 type definition is missing or whose primaryType matches no entry in it. With an empty field list the digest is still well-formed but commits to none of the action's contents, so it would have produced a valid-looking signature over nothing.

  • #467 4c1d3aa Thanks @kome12! - Close three residual safety gaps on the perp/bridge signing paths:

    • perp order now rejects a take-profit or stop-loss price that rounds to zero at the asset's precision, instead of encoding a triggerPx of 0 and resting a dead protective order while the parent position opens unprotected. This extends the existing zero-price/size guard (which only covered the parent leg) to the TP/SL trigger legs.
    • The Privy bridge signing path now refuses to sign an EIP-712 action whose primary type has no field definitions, matching the guard the local signing path already had. An empty type list produces a valid-looking signature that commits to none of the action's contents.
    • The EVM bridge deposit leg resolves its nonce from the signing wallet's own address rather than the server-returned txData.from. The transaction is signed with the local key regardless of from, so the nonce must come from that account — and this stays correct even if a quote omits from.

1.35.0

Minor Changes

  • #469 85b1934 Thanks @gulshngill! - Surface the API's credit and rate-limit response headers.

    Failed calls now report quota state in their error details: an out-of-credits error carries your actual remaining balance, and a rate-limited error carries the limit, what is left, and how long the window needs to drain. Previously the only credit figure the CLI could show was the static per-endpoint estimate published in the API reference — a quote, not what you were charged.

    A warning goes to stderr when your balance will not cover another call of the size just made, so it never interferes with the JSON on stdout.

    Successful responses carry the same numbers under an exported RESPONSE_META symbol, and the client exposes lastResponseMeta. Both are additive: the JSON each command prints is unchanged.

  • #470 8159300 Thanks @gulshngill! - Surface the API's request id.

    Failed calls now carry details.requestId — the value that identifies the call end to end. Quote it when reporting a problem; previously nothing identifying a failed request ever reached the user, which made server errors effectively unreportable. Successful responses expose it alongside the credit and rate-limit figures under the RESPONSE_META symbol.

    Absent on deployments that do not send the header yet, in which case the field is simply omitted.

1.34.0

Minor Changes

  • #459 37e6725 Thanks @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+).

  • #460 aac4bbe Thanks @gulshngill! - Add trader_type, sectors_filter, sm_label_filter, and trader_label_filter filters to nansen research perp screener (ECINT-6680).

    New CLI options:

    • --trader-type <type> — filter by trader type: all, sm, whale, public_figure, high_winrate_hl_perps_trader
    • --sectors-filter <sectors> — comma-separated sector:subcategory pairs, e.g. "Crypto:AI,TradFi:Stocks"
    • --sm-label-filter <labels> — comma-separated Nansen SM labels (applies when trader-type is all or sm)
    • --trader-label-filter <labels> — comma-separated HL perps trader labels (applies when trader-type is all or sm)

1.33.0

Minor Changes

  • #457 8149564 Thanks @gulshngill! - x402 on BNB Smart Chain: support all four stablecoins the API now advertises (U, USD1, USDT, USDC) and add Permit2 payment signing. Payments route on the 402's extra.assetTransferMethod — eip3009 keeps the existing gasless flow (U, USD1), while permit2-exact (USDT, USDC on BSC) signs a Permit2 PermitWitnessTransferFrom against the spender contract advertised in the 402. Permit2 entries are skipped with an actionable message when the wallet hasn't made the one-time approve(Permit2, …) for the token. Post-payment balance warnings now check the exact token paid with (per-token decimals) instead of one hardcoded token per network.

1.32.1

Patch Changes

  • #455 875fabb Thanks @gulshngill! - Support x402 payments with USDT on BNB Smart Chain (eip155:56), which the Nansen API now advertises as a payment option. Payment signing already handled any EVM network generically; this adds BSC to the post-payment balance check with the correct token contract and 18-decimal precision (Base USDC and X Layer USDT0 use 6), plus a bsc entry in the shared RPC registry with a NANSEN_BSC_RPC override.

1.32.0

Minor Changes

  • #451 73600d9 Thanks @kome12! - Add nansen research profiler dex-trades command for DEX trade history

1.31.1

Patch Changes

  • #443 0ee84db Thanks @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.

1.31.0

Minor Changes

  • #437 5ec7bd3 Thanks @gulshngill! - Add nansen research command with 11 subcommands for historical/point-in-time analytics: dex-trades, pnl-leaderboard, token-flow-summary, token-quant-scores, top-holders, who-bought-sold, smart-money-balances, token-screener, wallet-balances, tx-lookup, wallet-transactions. Labels and metrics resolve at the requested date rather than current state — useful for backtesting and historical research.

Patch Changes

  • #440 701dad4 Thanks @kome12! - Fix research historical-token-screener schema to mark --to-date as required (matching CLI and API behavior)

  • #442 6edbb68 Thanks @kome12! - research historical-token-flow-summary now errors immediately when --page or --limit are passed (the endpoint returns a single aggregated row and does not support pagination). research historical-smart-money-balances now errors when --sort or --order-by are passed (the endpoint does not support ordering). Previously both flags were silently dropped.

1.30.2

Patch Changes

1.30.1

Patch Changes

  • #411 26cd863 Thanks @gulshngill! - Add the nansen-limit-orders skill. The skill teaches agents to use the native nansen trade limit-order create|list|cancel|update commands for Solana price-triggered orders, and documents the alert-based settlement-signal fallback (common-token-transfer smart alert on the settlement wallet) for chains without native limit-order support. Builds on the trade limit-order command surface added by #328.

  • #429 511e795 Thanks @gulshngill! - Improve discovery of nansen trade in package metadata, help output, install tips, and agent-facing docs.

1.30.0

Minor Changes

  • #422 10da2f0 Thanks @gulshngill! - Add x402 support for paying with USDT0 on X Layer alongside Base USDC and Solana SPL USDC. The CLI auto-signs the payment using whatever the API advertises in the 402 accepts list — no client-side allowlist, since src/x402-evm.js already reads extra.name, extra.version, and asset generically. New NANSEN_XLAYER_RPC env var overrides the default X Layer RPC, and checkX402Balance() now picks the right token + RPC based on the requirement's network field.

Patch Changes

  • #422 dc9d1c1 Thanks @gulshngill! - Document MPP (Tempo) as a third paid-access rail alongside API key and x402. Adds a nansen-mpp-payment skill, a README section explaining when to reach for the separate tempo CLI, and updates the no-API-key 402 error to mention tempo as a third option.

  • #422 93e6a6d Thanks @gulshngill! - Fix x402 low-balance warning to use the actual stablecoin symbol (USDC or USDT0) returned by checkX402Balance() instead of hardcoding "USDC".

  • #422 8f9397f Thanks @gulshngill! - Fix x402 payment header decoding and WalletConnect payment payload encoding to use UTF-8 instead of Latin-1. Previously the Payment-Required header was decoded with atob(), which corrupted multi-byte UTF-8 chars in fields like extra.name = 'USD₮0'. The corrupted name then signed the wrong EIP-712 domain and the server rejected with invalid_exact_evm_signature. X Layer USDT0 payments now sign correctly; Base USDC was unaffected because 'USD Coin' is pure ASCII.

1.29.0

Minor Changes

  • #423 d10aa57 Thanks @imhta! - Add Relay aggregator support for Base↔Solana cross-chain swaps. Users now see Relay quotes alongside Li.Fi in nansen trade quote --to-chain ..., can execute them through trade execute, and optionally use Relay's gasless path with --gasless (local/Privy wallets only — not WalletConnect). trade bridge-status auto-detects which aggregator produced a tx (via a local tx record) and polls the right backend.

1.28.0

Minor Changes

  • #417 ae6079f Thanks @0xlaveen! - Add trade limit-order commands (create, list, cancel, update) for Jupiter Limit Order V2 on Solana. Supports local, Privy, and WalletConnect wallets.

  • #413 94bd349 Thanks @jake-kennis! - Add top-tokens subcommand to discover top-scoring tokens by Nansen Score. Calls the public endpoint (/api/v1/nansen-score/top-tokens) with optional --market-cap filter.

1.27.1

Patch Changes

  • #408 d1e9787 Thanks @0xlaveen! - Add cross-chain notes to trade help text and document --to-chain constraints in schema.json.

1.27.0

Minor Changes

  • #403 fe53dbe Thanks @marius-reed! - Add prediction market filtering (order_by, volume/liquidity/OI/trader/price/date filters, neg_risk, tags) and address-summary endpoint

Patch Changes

1.26.1

Patch Changes

  • #392 025993d Thanks @TimNooren! - Add gas balance validation: rejects trades when the wallet lacks sufficient native token for gas fees.

1.26.0

Minor Changes

  • #380 12e4e25 Thanks @TimNooren! - Add --amount-unit percent to trade commands, allowing trades as a percentage of wallet balance (e.g. --amount 100 --amount-unit percent to sell all)

Patch Changes

  • #382 d9c87ef Thanks @kome12! - fix: default profiler balance chain to 'all' instead of 'ethereum'

    Previously, nansen profiler balance --address <addr> without --chain defaulted to ethereum, returning empty results for wallets with no ETH mainnet holdings (e.g. Base-only or Solana-only wallets). Now defaults to 'all', letting the API auto-route based on address format.

1.25.1

Patch Changes

  • #367 9fea10a Thanks @kome12! - add --premium-labels flag to tgm/holders, tgm/pnl-leaderboard, tgm/perp-pnl-leaderboard, and perp-leaderboard endpoints

1.25.0

Minor Changes

  • #363 6ae402e Thanks @TimNooren! - Add --amount-unit usd to trade commands — specify swap amounts in USD

Patch Changes

  • #374 0f14803 Thanks @TimNooren! - Fix cross-chain quote display: show adaptive precision for sub-cent bridge fees, "< 1 min" for fast bridges, and echo --to-wallet address in output

  • #366 f358fff Thanks @kome12! - fix(token): replace dead --days param with working --timeframe for token flow-intelligence

    The --days option was accepted but never sent to the API, resulting in always fetching 1d data. This replaces it with --timeframe (enum: 1h | 6h | 12h | 1d | 7d, default 1d) which maps correctly to the API parameter.

1.24.0

Minor Changes

  • #333 c8fe79c Thanks @imhta! - Add cross-chain swap support between Solana and Base via Li.Fi bridge.

    nansen trade quote --chain base --to-chain solana --from ETH --to SOL --amount 0.01 --amount-unit token nansen trade execute --quote <id>

    Bridge status can be checked with nansen trade bridge-status.

Patch Changes

  • #365 56335af Thanks @TimNooren! - Add balance pre-check before quote API calls. Validates sell token balance, auto-adjusts near-full-balance trades (≤2% over), and reserves gas fees for native token swaps (SOL/ETH).

1.23.1

Patch Changes

  • #361 ff22da3 Thanks @TimNooren! - fix(alerts): error when --webhook-secret is passed without --webhook

    Previously, passing --webhook-secret with a non-webhook channel (e.g. --telegram) silently discarded the secret with no warning. The alert was created successfully but without any signing, giving the false impression that the secret was active.

    Now throws an actionable error: "--webhook-secret requires --webhook".

  • #358 70ee712 Thanks @TimNooren! - Add pre-quote trade input validation: rejects same-token swaps, invalid address formats, and non-positive amounts before any network call.

1.23.0

Minor Changes

  • #341 4b60056 Thanks @gulshngill! - Add --webhook <url> and --webhook-secret <secret> flags to alerts create and alerts update.

    Allows alerts to be delivered to any HTTP/HTTPS endpoint via POST, alongside the existing --telegram, --slack, and --discord channels. The optional --webhook-secret enables HMAC payload signing for verification.

Patch Changes

  • #344 3dc09cc Thanks @0xlaveen! - Add nansen-agent-guide skill — routing guide for when to use nansen agent vs direct CLI data commands

  • #347 a243c7a Thanks @kome12! - Add --buy-or-sell option to token who-bought-sold command — allows filtering by buy or sell side (BUY | SELL, defaults to BUY)

1.22.0

Minor Changes

  • #336 c3b1fbd Thanks @kome12! - Add --label option to token flows command to filter by holder segment (top_100_holders, smart_money, public_figure, whale, exchange).

  • #334 83244c6 Thanks @kome12! - Add --include-stablecoins flag to token screener command. Pass --include-stablecoins false to exclude stablecoins from screener results (API default is true). Supports combined usage with --smart-money.

  • #339 27ebcfc Thanks @TimNooren! - Add --amount-unit token flag to trade quote for human-readable amounts

1.21.0

Minor Changes

  • #315 908fa0c Thanks @TimNooren! - Add nansen agent command for the Nansen AI research agent with fast/expert modes, SSE streaming, conversation continuation, and JSON output.

Patch Changes

  • #326 1532ba4 Thanks @TimNooren! - Show API credit cost in research subcommand help text (fetched from OpenAPI spec, cached 24h).

  • #330 a6b9b8f Thanks @0xlaveen! - Suppress misleading PASSWORD_REQUIRED error when --provider privy is specified. Privy wallets don't need a password — only the Privy-specific credentials error is now shown when PRIVY_APP_ID/PRIVY_APP_SECRET are missing.

  • #329 f047833 Thanks @TimNooren! - Limit deprecation warnings and update notices to help output only, keeping stdout/stderr clean for programmatic usage.

  • #332 e9b6de1 Thanks @0xlaveen! - docs: add trading examples and Privy wallet setup to README

1.20.0

Minor Changes

  • #302 3f0a5ab Thanks @arein! - Add post-install onboarding that interactively offers to install the Nansen AI coding skill and run a test query after npm install -g nansen-cli. Non-interactive environments (CI, piped stdin) receive a one-liner tip and are never blocked.

Patch Changes

  • #313 bb4d9e4 Thanks @0xlaveen! - Update API key setup URL from app.nansen.ai/api to app.nansen.ai/auth/agent-setup across CLI help text, error messages, README, and postinstall script.

1.19.0

Minor Changes

  • #306 f685eb8 Thanks @0xlaveen! - Rename 30 skills for clarity and clawhub slug uniqueness. Abbreviations expanded (pm → polymarket, sm prefix added where relevant), ambiguous names made specific (nansen-wallet → nansen-wallet-manager, nansen-profiler → nansen-wallet-profiler, nansen-search → nansen-general-search, nansen-trade → nansen-trading, etc.).

Patch Changes

  • #308 569d7d4 Thanks @kome12! - fix: include src subdirectories in npm package

    The files field in package.json used src/*.js which only matched files directly in src/, causing src/commands/ to be missing from the 1.18.0 publish. Changed to src/**/*.js to include all subdirectories recursively, and added !src/__tests__/** to exclude test files from the package.

1.18.0

Minor Changes

  • #265 c3de691 Thanks @TimNooren! - Add nansen alerts command for managing smart alerts (list, create, update, toggle, delete).

    Supports three alert types: sm-token-flows, common-token-transfer, and smart-contract-call. Named flags (--inflow-1h-min, --chains, --telegram, etc.) let you build alerts without raw JSON; a --data escape hatch is available for full config overrides.

    Also adds a nansen-alerts skill for agent integration.

  • #295 3ddcbde Thanks @kome12! - feat: add nansen web search and nansen web fetch commands (ECINT-6393)

    • nansen web search <query> [query...] — search the web for one or more queries in parallel via /api/v1/search/web-search
    • nansen web fetch <url> [url...] --question <q> — fetch and analyze URL content with AI via /api/v1/search/web-fetch

Patch Changes

  • #293 bcd95a8 Thanks @TimNooren! - Add default values for all required alert data fields to match backend schema

  • #265 c3de691 Thanks @TimNooren! - Fix alerts list filtering (--type, --enabled, --disabled, --chain, --token-address, --limit, --offset).

    Filters were sent as query params but silently ignored by the API. Now applied client-side after fetching all alerts.

  • #301 cda6796 Thanks @kome12! - fix: add missing openclaw metadata to 19 skills

  • #294 8a1cc7b Thanks @yodablocks! - fix: include skills/ directory in published npm package

1.17.0

Minor Changes

  • #279 174a3d6 Thanks @kome12! - Add nansen account command to verify API key and check credit balance

    Users can now run nansen account to confirm their API key is valid and see their current plan and remaining credits — without consuming any credits.

    This calls the new GET /api/v1/account endpoint (ECINT-6365).

  • #234 10a5ced Thanks @kome12! - Reduced schema.json to a minimal format (~66% smaller).

Patch Changes

  • #272 50213c1 Thanks @TimNooren! - fix: show human-readable error when trade fails due to insufficient ETH

    When a wallet has no ETH and a trade is attempted, the raw Ethereum RPC error ("insufficient funds for gas * price + value: ... have 0 want 400000000000000 (supplied gas 600000000)") is now translated into a user-friendly message showing amounts in ETH with a funding hint, e.g. "Insufficient ETH: wallet has 0.000000 ETH but this trade needs ~0.000400 ETH (amount + gas). Send ETH to 0x... before trading."

1.16.1

Patch Changes

  • #249 0c17437 Thanks @0xlaveen! - Add pm to top-level COMMAND_ALIASES so nansen pm <subcommand> works (previously only nansen research pm <subcommand> resolved the alias)

  • #244 6427a9f Thanks @Nicolai1205! - Add 7 new agent skills: nansen-token-search, nansen-sm-trend, nansen-wallet-cluster, nansen-wallet-compare, nansen-token-indicators, nansen-cross-chain-flow, nansen-batch-wallet. All validated against live API.

1.16.0

Minor Changes

  • #196 0c286c2 Thanks @arein! - Add Solana WalletConnect support for trading (quote and execute). Solana wallets like Phantom and Solflare can now sign DEX swap transactions via WalletConnect v2.

1.15.0

Minor Changes

  • #216 5b88241 Thanks @TimNooren! - Unified wallet abstraction: Privy server wallets are first-class citizens.

    • wallet create --provider privy creates EVM + Solana wallets via Privy and stores a local reference
    • All wallet commands (list, show, delete, default, send) work by name regardless of provider
    • Trading (quote + execute) supports Privy wallets with sign-only + Trading API broadcast
    • x402 auto-payment routes through Privy when credentials are configured

Patch Changes

1.14.0

Minor Changes

  • #231 c3968da Thanks @araa47! - Agent-first secure wallet flow — OS keychain persistence, no interactive prompts

    • New src/keychain.js: Password persistence via OS keychain (macOS Keychain / Linux secret-tool), with base64-encoded .credentials file fallback for containers/CI. Zero npm dependencies.
    • Non-interactive by default: All readline prompts removed. Agents get structured JSON errors (PASSWORD_REQUIRED, API_KEY_REQUIRED) with actionable instructions. --human flag re-enables interactive mode.
    • Two-step wallet creation: Agent asks user for password, runs NANSEN_WALLET_PASSWORD=<pw> nansen wallet create. Password auto-persists to keychain — all future operations are passwordless.
    • New commands: wallet secure (migrate to keychain), wallet forget-password (clear from all stores).
    • Bug fixes: Clear passwordHash on last wallet delete, verify password before keychain writes, exit non-zero when keychain migration fails, source-aware error messages.
    • New skill: nansen-wallet-migration for migrating from old ~/.nansen/.env storage to keychain.

1.13.1

Patch Changes

  • #225 051e4a3 Thanks @TimNooren! - Remove "recommended, lower fees" label from Base network in wallet create output

1.13.0

Minor Changes

  • #107 5877c06 Thanks @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.

1.12.0

Minor Changes

  • #207 73ca500 Thanks @TimNooren! - Add --unsafe-no-password flag to wallet create for agent-friendly passwordless wallets.

Patch Changes

  • #212 726c29d Thanks @0xlaveen! - Clarify empty input handling in parseAddressList with explicit early return

  • #218 8c4dd71 Thanks @TimNooren! - fix: nansen changelog --since <version> now correctly filters changeset-format entries (## x.y.z) in addition to Keep a Changelog entries (## [x.y.z])

  • #209 a6dc1ed Thanks @0xlaveen! - fix: prevent --help from executing destructive commands (logout, schema, cache)

1.11.2

Patch Changes

  • #205 dba24aa Thanks @TimNooren! - Add hot wallet and password handling warnings to wallet create output

1.11.1

Patch Changes

  • #194 89225f5 Thanks @TimNooren! - fix: --help on trade subcommands and wallet subcommands now shows full help identical to the no-args case

  • #199 9ae981e Thanks @TimNooren! - fix: replace misleading walletconnect connect command reference in x402 payment error with actionable guidance mentioning both local wallet (nansen wallet create) and external WalletConnect CLI options

1.11.0

Minor Changes

  • #186 feecc50 Thanks @TimNooren! - Trade commands output to stdout instead of stderr; wallet send prints human-readable text instead of JSON

Patch Changes

  • #166 c1034db Thanks @0xlaveen! - fix: pass --page parameter correctly in smart-money, profiler, token, perp, and points commands

  • #137 1214767 Thanks @0xlaveen! - Add missing sort/filters options to profiler schema and fix pnl sort/filters forwarding

1.10.1

Patch Changes

  • #133 4cbeb65 Thanks @0xlaveen! - fix: correct profiler pagination parameter from recordsPerPage to per_page; remove unsupported pagination from pnl-summary; add --limit to labels, historical-balances, counterparties schema

  • #164 ec6ab78 Thanks @DMagowan! - fix: correct --date option marked as required: true when it is optional

    The schema incorrectly marked --date as required: true for three commands:

    • research token flows
    • research token who-bought-sold
    • research profiler transactions

    All three use parseDateOption with a days fallback, so --date is optional — omitting it defaults to a rolling window based on --days. An agent following the schema strictly would unnecessarily refuse to run these commands without a date.

  • #162 4dbe181 Thanks @DMagowan! - fix: surface wallet prerequisite in trade quote help text and schema

    nansen trade quote requires a configured wallet (the trading API builds a transaction specific to the sender address), but this was not communicated until the command failed. Adds a PREREQUISITE section to the usage text and a prerequisites field to the schema so agents can discover this requirement before running the command.

  • #165 92f37ea Thanks @0xlaveen! - Fix trading docs and config to reflect actual supported chains (Base and Solana only)

1.10.0

Minor Changes

  • #125 5a5a80a Thanks @0xlaveen! - Add modular skills/ directory with 7 agent-optimised SKILL.md files (nansen-token, nansen-smart-money, nansen-profiler, nansen-trade, nansen-wallet, nansen-perp, nansen-search) following the linear-cli pattern. Each skill has scoped frontmatter, agent routing descriptions, bash examples, and exit codes. Add skills nudge to nansen --help output.

Patch Changes

  • #122 9a1ada8 Thanks @TimNooren! - nansen research <unknown> and nansen trade <unknown> now exit with code 1 and return {"success":false,...} instead of silently exiting 0.

  • #138 c61881f Thanks @TimNooren! - Fix nansen login --help to show usage instead of erroring. Previously, --help was silently ignored on TTY (showing the interactive prompt) and caused an error on non-TTY. Also fixes the post-login suggested command to use the non-deprecated nansen research token screener path.

  • #129 eeabf89 Thanks @araa47! - Fix token ohlcv sending unsupported pagination/limit params that caused 422 errors

  • #139 e86dc68 Thanks @TimNooren! - Fix API key prompt masking: each keystroke was showing the real character followed by * (e.g. f*o*o*) because the readline interface was active alongside raw mode, causing double output. Moving readline creation into the non-hidden branch eliminates the double-echo and also fixes backspace incorrectly clearing the prompt label.

  • #129 eeabf89 Thanks @araa47! - Fix trade quote crash when no wallet exists — now shows actionable error instead of uncaught exception

  • #126 f3b87e7 Thanks @araa47! - Remove root SKILL.md so npx skills add nansen-ai/nansen-cli correctly discovers all 7 skills in skills/ instead of treating the repo as a single skill.

1.9.3

Patch Changes

  • #118 0bd4c3c Thanks @TimNooren! - Show warning when trade quote price impact exceeds 5%, and show pin command to avoid fallback to worse quotes

1.9.2

Patch Changes

  • #116 7a2b729 Thanks @TimNooren! - Fix usage examples for nansen trade quote to show correct command name instead of deprecated nansen quote

  • #114 37d8c0b Thanks @TimNooren! - Show API key URL in non-interactive login error message

  • #117 55ad922 Thanks @TimNooren! - Add --wallet and WalletConnect documentation to nansen trade help output

1.9.1

Patch Changes

  • #110 82aa780 Thanks @TimNooren! - Fix nansen changelog always showing "CHANGELOG.md not found". Added a files field to package.json to explicitly bundle CHANGELOG.md with the published package. Also excludes src/__tests__/ from the package, reducing package size from ~537 kB to ~269 kB.

1.9.0

Minor Changes

  • #98 2f3f556 Thanks @Codier! - Add symbol shortcuts for common tokens (SOL, ETH, USDC, USDT, etc.) that resolve to canonical addresses per chain. Users can now use --from SOL --to USDC instead of raw contract addresses.

  • #32 08a8d21 Thanks @arein! - Add WalletConnect support for trading, transfers, and x402 auto-payment (EVM only)

Patch Changes

  • #99 9144cba Thanks @Codier! - Show clear error when --amount contains a decimal (e.g. 0.005) instead of base units (lamports, wei). Detected client-side before hitting the API.

  • #100 19559bf Thanks @Codier! - Fix nansen trade help returning blank output. Now prints subcommands, usage, and examples. Also fixes errorOutput ReferenceError in buildCommands scope (affected trade and changelog commands).

  • #93 342c91f Thanks @Codier! - Warn when --from is a wrapped native token (WETH/WBNB) or native sentinel, so AI agents can correct the token before execution fails

1.8.0

Minor Changes

  • #56 d10998a Thanks @askeluv! - Add CHANGELOG.md, nansen changelog command, and post-update "what's new" notice

    • Added CHANGELOG.md following Keep a Changelog format with history back to v1.5.0
    • Added nansen changelog command with --since <version> filtering
    • Added one-time upgrade notice on first run after version update (prints to stderr)
  • #77 46e4660 Thanks @0xlaveen! - Add token-ohlcv endpoint for OHLCV candle data

  • #75 287937e Thanks @TimNooren! - Restructure CLI into research/trade/wallet namespaces

    • Commands reorganized: smart-money, profiler, token, portfolio now live under nansen research
    • New nansen trade namespace for quote and execute
    • New nansen wallet namespace for wallet management
    • Old top-level commands still work with deprecation warnings
  • #61 9af0192 Thanks @askeluv! - Add ENS name resolution for profiler commands. Use .eth names directly in --address flags — resolved automatically via ensideas API with onchain RPC fallback. Works across all profiler subcommands, batch, and trace operations.

All notable changes to the Nansen CLI will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[1.7.0] - 2026-02-24

Added

  • Trading commands — quote and execute for DEX swaps (EVM + Solana)
  • Wallet management — wallet create, list, show, export, default, delete
  • Wallet send — transfer tokens on EVM and Solana (wallet send)
  • x402 auto-payment — automatic payment via Base USDC or Solana SPL USDC
  • Explorer links in transaction output
  • --dry-run flag for wallet send
  • x402 low balance warning
  • AI Agent Access setup docs and improved onboarding flow

Fixed

  • Solana execute crash with OKX quotes
  • x402 auto-pay retry path (3 reference errors)
  • Gas estimation — use API quote.gas as floor
  • Pre-flight simulation moved after approval (industry standard)
  • EVM signing edge cases with pure JS ECDSA
  • Wallet send crashes on amount parsing and silent success
  • Solana confirmation and SPL token transfer account ordering
  • Suppress duplicate JSON output from quote/execute
  • Suppress approval warning for native ETH swaps

Changed

  • Pricing clarity — from $0.01/call, min $0.05 balance
  • Consolidated crypto primitives into shared module

[1.6.0] - 2026-02-14

Added

  • token indicators endpoint
  • profiler search — general entity search command
  • --x402-payment-signature flag for pre-signed payment headers
  • X-Client-Type and X-Client-Version tracking headers on all API requests

Fixed

  • Error JSON now outputs to stdout (not stderr) for consistent agent parsing
  • Config loading — environment variables correctly override file config

[1.5.1] - 2026-02-07

Added

  • Allow API requests without API key when using x402 payment flow

[1.5.0] - 2026-01-31

Baseline version. Changes above are relative to this release.