defmodule CCXT.WS.URLRouting do @moduledoc """ Pure URL resolution for WebSocket endpoints. Given a `%CCXT.Exchange{}`, returns the public or private WS URL appropriate for the current sandbox flag, with `{hostname}` interpolated from `exchange.hostname`. URLs come from `CCXT.WS.Config` today. When ccxt_extract starts emitting `runtime.describe.urls.api.ws` this module will read from the spec instead. """ alias CCXT.Exchange alias CCXT.WS.Config alias CCXT.WS.Helpers @doc """ Public WS URL for the given exchange, or nil if the exchange has no WS config. Honors `exchange.sandbox` — returns the sandbox URL when the flag is true and a sandbox URL is configured. """ @spec public_url(Exchange.t()) :: String.t() | nil def public_url(%Exchange{} = exchange) do resolve(exchange, :public) end @doc """ Private WS URL for the given exchange, or nil if the exchange has no WS config or no private endpoint. """ @spec private_url(Exchange.t()) :: String.t() | nil def private_url(%Exchange{} = exchange) do resolve(exchange, :private) end defp resolve(%Exchange{id: id, sandbox: sandbox, hostname: hostname}, section) do case Config.for_exchange(id) do nil -> nil config -> config |> pick_url(section, sandbox) |> Helpers.interpolate_hostname(hostname) end end defp pick_url(config, :public, true), do: config[:public_url_sandbox] || config[:public_url] defp pick_url(config, :public, false), do: config[:public_url] defp pick_url(config, :private, true), do: config[:private_url_sandbox] || config[:private_url] defp pick_url(config, :private, false), do: config[:private_url] end