Skip to content

API: token-dex-trades + token-flows mis-resolve UNI to a Sui address on Ethereum (422) #446

@mangrove-one

Description

@mangrove-one

Summary

POST /api/v1/tgm/dex-trades and POST /api/v1/tgm/flows mis-resolve the symbol UNI to a Sui-format address even when chain is explicitly set to ethereum. Both endpoints then 422 because the resolved address doesn't match the requested chain.

The same symbol resolves correctly on the same Pro plan's /smart-money/historical-holdings endpoint (returns the canonical Ethereum UNI address 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984). So the resolver path on token-dex-trades / token-flows is wrong, not the token mapping itself.

This is the same class of bug previously documented in #143 — symbol resolution works on some endpoints and not on others because they go through different resolver paths.

Reproduction

# Fails — UNI resolved to a Sui address on Ethereum chain
curl -X POST \
  -H "apiKey: $NANSEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"chain": "ethereum", "date_from": "2026-05-28", "date_to": "2026-05-29", "per_page": 2}' \
  "https://api.nansen.ai/api/v1/tgm/dex-trades/UNI"
# Same shape, same symbol — also 422
curl -X POST \
  -H "apiKey: $NANSEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"chain": "ethereum", "date_from": "2026-05-28", "date_to": "2026-05-29", "per_page": 2}' \
  "https://api.nansen.ai/api/v1/tgm/flows/UNI"

Response (422 from both):

{
  "error": "Invalid address format",
  "message": "Address '0xaf9e228fd0292e2a27b4859bc57a2f3a9faedb9341b6307c84fef163e44790cc::uni::uni' appears to be a sui address format but the chain is set to ethereum. Please verify the address is correct for the ethereum chain."
}

That resolved string 0xaf9e228...::uni::uni is the Sui Move-package + type-tag format for the Sui-native UNI token. It should not be returned when the caller passed chain=ethereum.

Expected behavior

Either:

  1. Preferred: token-dex-trades / token-flows should resolve symbol=UNI, chain=ethereum to 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 (the same canonical address smart-money/historical-holdings already returns for the exact same symbol). Then proceed with the actual query.

  2. Acceptable: Reject ambiguous symbols upfront with a clear error pointing to the per-chain disambiguation (e.g. "Symbol UNI exists on multiple chains; please pass the explicit token_address or use the canonical mapping for chain=ethereum: 0x1f98...").

What works (control case)

The same UNI / ethereum pair resolves correctly on /smart-money/historical-holdings:

curl -X POST \
  -H "apiKey: $NANSEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"chains": ["ethereum"], "per_page": 1}' \
  "https://api.nansen.ai/api/v1/smart-money/historical-holdings"

Response includes:

{
  "chain": "ethereum",
  "token_address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
  "token_symbol": "UNI",
  ...
}

So Nansen's data layer knows the correct Ethereum address; only the resolver path on token-dex-trades and token-flows is broken.

WETH on ethereum resolves correctly on both affected endpoints (we use it as our smoke-test symbol now). So whatever resolver picks the Sui mapping for UNI is also failing closed cleanly for non-ambiguous tickers — the bug is specific to symbols that have entries on multiple chains.

Impact

We're an SDK / agent vendor exposing these Nansen endpoints to our customers. We discovered this during live verification of MangroveAI-SDK PR #13 (typed wrappers for the Nansen Pro plan) and mangrove-agent PR #82 (agent's REST + MCP mirror).

Customers can work around it by passing token_address directly, but the symbol shortcut works on every other Nansen Pro endpoint we tested, so the inconsistency is the user-visible friction.

Versions

  • Tested against api.nansen.ai/api/v1/... directly on 2026-05-29.
  • Routed through our Mangrove proxy + SDK; identical 422 from both call paths.
  • nansen-cli not used for repro (we hit the REST API directly), but filing here per the org's API issue conventions (#143, #177 precedents).

Suggested fix scope

Looks like the same resolver-path issue family as #143. Sharing one canonical symbol→address resolver across dex-trades, flows, historical-holdings, and the rest of the Pro plan would fix this class of bug structurally.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions