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

Per-exchange WebSocket configuration.

Effective config merges v4.1.0 `websocket.*` spec slices (heartbeat, auth,
urls when emitted) with hand-maintained bases in `Bourse.WS.SpecConfig` for
subscription patterns, URL fallbacks, and auth pattern detail.

Ten runtime venues have hand bases. Coinbase Exchange is the sole registered
runtime/config divergence because its WebSocket transport is not configured.
Spec-resolved heartbeat/auth overrides hand values where
`unresolved_reason` is nil.

## Entry shape

    %{
      public_url: String.t() | nil,
      public_url_sandbox: String.t() | nil,
      market_url: String.t() | nil,
      market_url_sandbox: String.t() | nil,
      private_url: String.t() | nil,
      private_url_sandbox: String.t() | nil,
      heartbeat: %{type: :ping | :deribit | :custom, interval: pos_integer() | nil, optional(:payload) => term()},
      subscription_pattern: atom(),
      subscription_config: map(),
      auth_pattern: atom() | nil,
      auth_config: map(),
      optional(:auth_sections) => [:public | :private]
    }

See `Bourse.WS.SpecConfig` for hand-base details and known URL limitations.

# `for_exchange`

```elixir
@spec for_exchange(String.t() | Bourse.Exchange.t()) :: map() | nil
```

Returns the WS config map for the given exchange id or struct, or nil if it
has no configured WebSocket transport.

When passed a `%Bourse.Exchange{}`, merges using the lean `exchange.spec`.

# `missing_config_error`

```elixir
@spec missing_config_error(String.t()) ::
  {:error, :websocket_not_configured | :unsupported_exchange}
```

Error for a missing WS config.

A runtime-supported venue without a hand base is `:websocket_not_configured`.
A venue outside runtime support is `:unsupported_exchange`.

# `registered_divergences`

```elixir
@spec registered_divergences() :: %{required(String.t()) =&gt; :websocket_not_configured}
```

Returns runtime exchanges intentionally lacking a WS config and the reason for each gap.

# `supported?`

```elixir
@spec supported?(String.t()) :: boolean()
```

Returns true if this exchange has a WS config entry.

# `supported_exchanges`

```elixir
@spec supported_exchanges() :: [String.t()]
```

Returns all supported exchange ids.

---

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