# `Bourse.WS.Channels`
[🔗](https://github.com/ZenHive/bourse/blob/main/lib/bourse/ws/channels.ex#L1)

Spec-driven WebSocket channel formatting from `websocket.subscribe.channels`.

Maps unified `watch_*` methods to exchange-native channel strings (or OKX-style
channel objects) using authored template strings.

When a method has no resolvable templates or carries a non-nil
`_unresolved_reason`, pass the pre-formatted channel via `channel:` in opts
(honest pass-through — no guessing).

# `build_error`

```elixir
@type build_error() ::
  :unsupported_method
  | :missing_symbol
  | :no_channel_templates
  | {:unresolved, String.t()}
```

# `channel`

```elixir
@type channel() :: String.t() | map()
```

# `params`

```elixir
@type params() :: %{
  optional(:symbol) =&gt; String.t(),
  optional(:limit) =&gt; non_neg_integer(),
  optional(:timeframe) =&gt; String.t()
}
```

# `subscription_settings`

```elixir
@type subscription_settings() :: {atom() | nil, map()}
```

# `build`

```elixir
@spec build(Bourse.Exchange.t(), atom(), params(), keyword()) ::
  {:ok, channel()} | {:error, build_error()}
```

Builds the exchange-native channel(s) for a unified watch method.

Reads templates from `exchange.spec["websocket"]["subscribe"]["channels"]`.
Returns a single channel value (string or map) suitable for `Bourse.WS.subscribe/3`.

Pass `channel:` in opts to supply a pre-formatted channel when templates are
missing or flagged with `_unresolved_reason`.

# `private?`

```elixir
@spec private?(atom()) :: boolean()
```

Returns whether the unified watch method requires a private WS connection.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
