UNPKG

@kinetiq-research/markets-assets

Version:

Asset metadata (descriptions, oracle references) for Kinetiq markets

85 lines (83 loc) • 4.27 kB
/** * The listings whose canonical url KEEPS its dex prefix, lowercased. * * SanDisk is listed live on BOTH `xyz` and `io`, so `/trade/sndk` names two * markets. The bare url stays with `xyz` — it is the deeper market and the one * already indexed and shared — and the `io` listing takes `/trade/io:sndk` * rather than being unreachable behind whichever listing `getPerpsAsset` * happened to rank first. Both keep the ticker they actually trade under; only * the url disambiguates, because a display name is the exchange's to set and a * renamed SanDisk would be wrong on every surface, not just this one. * * Keys are the FULL `dex:symbol` name, which is also the value this returns — * that is what keeps the function idempotent for a prefixed listing: * re-applying it finds `io:sndk` in here and hands it straight back. */ const PREFIXED_URL_SYMBOLS: ReadonlySet<string> = new Set(['io:sndk']) /** * The canonical name `/trade/[...urlSymbol]` resolves WITHOUT a redirect: the * market's DISPLAY name, lowercased, with no dex prefix at all. * * This is the single definition of that rule, and it exists as its own export * for one reason: every place that needed the rule used to restate it. Call it * rather than interpolating a symbol into a path — `ROUTES.TRADE_SYMBOL` does, * so most callers get it for free. * * WHY NO DEX PREFIX. Urls used to carry one for external dexes (`xyz:PLTR`), * because a ticker could in principle name a listing on more than one dex. In * practice the dexes we surface (main Hyperliquid, our `mkts`, and `xyz`) share * no live ticker, so the prefix bought nothing and cost every reader, every * share link and every bot a piece of Hyperliquid trivia. If a real collision * ever ships, re-introduce the prefix HERE for that one listing — not as a * blanket rule. * * ONE COLLISION HAS SINCE SHIPPED, and it is handled exactly that way — see * `PREFIXED_URL_SYMBOLS`. Everything else still resolves bare. * * Two things that follow from the shape, both of which have already shipped * bugs in the prefixed version of this rule: * * 1. IT IS IDEMPOTENT, AND IT ACCEPTS RAW HYPERLIQUID NAMES. `hyperliquidSymbol` * is prefixed for every HIP-3 dex INCLUDING our own (`mkts:US500`), so * passing one is the common case at the call sites that only have the raw * name to hand; it is stripped here rather than at each of them. * * Idempotence is REQUIRED, not incidental: `resolveCanonicalRedirect` * compares this output against the url it is already on and redirects when * they differ, so an output this function would change again is a url that * redirects forever. That is why the split is on the LAST colon and not the * first — the dex is what precedes the first one, but taking that split * leaves any remaining colon in the result, and a second pass would strip * more. Splitting last is the same answer for every real name (they carry * at most one colon) and is the only one that cannot move twice. * 2. THE URL IS THE DISPLAY NAME, NOT THE SYMBOL. The listing whose symbol is * `CL` displays as `WTIOIL`, so its canonical url is `/trade/wtioil`. * `/trade/cl` still resolves — `getPerpsAsset` matches the raw symbol as a * last resort — but only through a canonical redirect. */ export const toTradeUrlSymbol = ({ dex, symbol, }: { /** * The dex the listing trades on (`''` for main Hyperliquid). Only consulted * to spot a `PREFIXED_URL_SYMBOLS` entry, so callers holding an * already-canonical `tradeUrlSymbol` can leave it off. */ dex?: string /** * The DISPLAY name (override, then live annotation, then clean symbol), or a * raw `dex:`-prefixed Hyperliquid name — the prefix is stripped either way. */ symbol: string }): string => { const colon = symbol.lastIndexOf(':') const bare = symbol.slice(colon + 1).toLowerCase() // The dex the caller named, else the one already carried by `symbol` — which // is what makes a second pass over `io:sndk` land on the same answer. const prefix = ( dex ?? (colon === -1 ? '' : symbol.slice(0, colon)) ).toLowerCase() const prefixed = `${prefix}:${bare}` return PREFIXED_URL_SYMBOLS.has(prefixed) ? prefixed : bare }