Skip to content

Route pairs share a path shape but name the id differently: /tokens/{symbolOrAddress} vs /tokens/{address} #689

Open

Description

@fengtality

Two pairs of routes occupy the same path shape while naming the id differently:

shape routes
/tokens/{} GET /tokens/{symbolOrAddress} · DELETE /tokens/{address}
/pools/{} GET /pools/{tradingPair} · DELETE /pools/{address}

Both routes in each pair are correct and clearly described — this is only about the
parameter name in the same URL position changing meaning with the verb.

Why it matters

A consumer that reasons about routes structurally rather than by exact string cannot tell
these apart. That is not a hypothetical shape of consumer: a client written against
Gateway has to compare by segment shape, because the two sides do not name ids the same
way. hummingbot-api calls tokens/{token_address} and Gateway declares
/tokens/{symbolOrAddress}, so a check that insisted on matching parameter names would
report drift on every call.

Concretely, we hit this building a drift check that verifies both Hummingbot clients
against Gateway's generated OpenAPI spec. Comparing by path shape, the check could not
see Gateway deleting GET /tokens/{symbolOrAddress} outright — the surviving
DELETE /tokens/{address} collapses to the same /tokens/{} and satisfied the call. So
get_token would have started resolving against a route that removes tokens, and the
check would have passed. Same for GET /pools/{tradingPair}.

We fixed it on our side by comparing (method, path-shape) rather than path shape alone,
which is arguably what any such consumer should do. But the ambiguity is real for anything
that reads the route table structurally — generated clients get a parameter whose name
depends on the verb, and proxies or routing tables keyed on path see one resource where
there are two.

Options

  1. Use one parameter name per path. /tokens/{symbolOrAddress} for both, with the
    DELETE documenting that it accepts an address only — or make DELETE accept a symbol
    too, so the parameter genuinely is the same thing. Likewise /pools/{tradingPair}.
    Least disruptive; no path changes, so no client breaks.
  2. Give the reads their own path, e.g. GET /tokens/lookup/{symbolOrAddress} and
    GET /pools/by-pair/{tradingPair}, leaving {address} as the canonical id for
    DELETE. Clearer, but it is a breaking route change.

We would lean toward (1).

Not affected

Neither client is broken today, and no behaviour needs to change in Hummingbot or
hummingbot-api for this. Filing it because the route surface is the right place to fix it,
and because the same pattern will keep catching consumers that read the spec structurally.

The rest of the /tokens surface is unambiguous and worth noting as a counter-example:
GET /tokens/ (local lists, with search), GET /tokens/{symbolOrAddress} (local
lists, one token), GET /tokens/find/{address} (GeckoTerminal) and
POST /tokens/save/{address} (GeckoTerminal, persisted) each have a distinct source and
say so in their description. That is what made it easy to confirm the two clients diverge
for good reasons rather than by accident.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions