# `CCXT.WS.Auth`
[🔗](https://github.com/ZenHive/ccxt_client/blob/main/lib/ccxt/ws/auth.ex#L1)

WebSocket authentication pattern dispatcher.

Parallel of `CCXT.Signing`: a function-head dispatcher that routes a
pattern atom to the matching per-pattern module. Each pattern module
implements the `CCXT.WS.Auth.Behaviour` callbacks.

## Supported Patterns

| Pattern | Exchanges | Notes |
|---------|-----------|-------|
| `:direct_hmac_expiry` | bybit, bitmex, htx family | `GET/realtime{expires}` HMAC-SHA256 |
| `:iso_passphrase` | okx family, kucoin family | Requires `credentials.password` |
| `:jsonrpc_linebreak` | deribit | JSON-RPC `public/auth`, returns `{:ok, %{ttl_ms: _}}` |
| `:sha384_nonce` | bitfinex | `AUTH{nonce}` HMAC-SHA384 |
| `:sha512_newline` | gate, gateio | Gate `spot.login` HMAC-SHA512 |
| `:listen_key` | binance family, aster | REST pre-auth, no WS auth frame |
| `:rest_token` | kraken | REST pre-auth, token injected into subscribe frames |
| `:inline_subscribe` | coinbaseexchange | Auth fields inlined in each subscribe frame |

## Usage

Typical flow from the adapter layer (T94/T95):

    {:ok, pre_auth_data} = CCXT.WS.Auth.pre_auth(pattern, credentials, config, market_type: :spot)
    # caller performs any REST round-trip implied by pre_auth_data

    case CCXT.WS.Auth.build_auth_message(pattern, credentials, config) do
      {:ok, frame}   -> ZenWebsocket.Client.send_message(client, Jason.encode!(frame))
      :no_message    -> :ok   # listen_key / rest_token / inline_subscribe
      {:error, why}  -> {:error, why}
    end

    # After receiving the auth response frame:
    case CCXT.WS.Auth.handle_auth_response(pattern, response, state) do
      :ok                        -> :authenticated
      {:ok, %{ttl_ms: _}} = meta -> schedule_re_auth(meta)
      {:error, reason}           -> {:auth_failed, reason}
    end

Per-exchange configuration (which pattern + which config options + which
channels need inline token injection) lives in `CCXT.WS.Config` entries
added by Task 94.

# `auth_message`

```elixir
@type auth_message() :: map()
```

# `build_result`

```elixir
@type build_result() :: {:ok, auth_message()} | :no_message | {:error, term()}
```

# `config`

```elixir
@type config() :: map()
```

# `pattern`

```elixir
@type pattern() ::
  :direct_hmac_expiry
  | :iso_passphrase
  | :jsonrpc_linebreak
  | :sha384_nonce
  | :sha512_newline
  | :listen_key
  | :rest_token
  | :inline_subscribe
```

# `pre_auth_result`

```elixir
@type pre_auth_result() :: {:ok, map()} | {:error, term()}
```

# `build_auth_message`

```elixir
@spec build_auth_message(pattern(), CCXT.Credentials.t(), config(), keyword()) ::
  build_result()
```

Builds the auth frame for the pattern. Patterns without a standalone auth
frame return `:no_message` — the caller should skip the send step.

# `build_subscribe_auth`

```elixir
@spec build_subscribe_auth(
  pattern(),
  CCXT.Credentials.t(),
  config(),
  String.t() | nil,
  [String.t()] | nil
) :: map() | nil
```

Builds inline auth data to merge into subscribe frames.

`:inline_subscribe` (coinbase) produces per-subscribe HMAC fields.
`:rest_token` (kraken) injects `%{"token" => token}` — the caller must
thread the REST-acquired token through `opts[:token]` since pattern
modules are stateless.

Returns `nil` for all other patterns.

# `handle_auth_response`

```elixir
@spec handle_auth_response(pattern(), map(), map()) ::
  :ok | {:ok, map()} | {:error, term()}
```

Dispatches an auth response to the pattern's classifier.

# `inline_auth?`

```elixir
@spec inline_auth?(pattern()) :: boolean()
```

Returns `true` for patterns that attach auth to each subscribe frame.

# `module_for_pattern`

```elixir
@spec module_for_pattern(pattern()) :: module() | nil
```

Returns the implementing module for a pattern, or `nil` if unknown.

# `patterns`

```elixir
@spec patterns() :: [pattern()]
```

Lists every supported auth pattern atom.

# `pre_auth`

```elixir
@spec pre_auth(pattern(), CCXT.Credentials.t(), config(), keyword()) ::
  pre_auth_result()
```

Performs pattern-specific pre-auth. Patterns that don't require a REST
round-trip return `{:ok, %{}}`.

# `requires_pre_auth?`

```elixir
@spec requires_pre_auth?(pattern()) :: boolean()
```

Returns `true` for patterns that require a REST pre-auth round-trip.

---

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