Packages

Elixir client library for cryptocurrency exchanges — generated from CCXT specs via compile-time macros.

Current section

Files

Jump to
ccxt_client lib ccxt ws auth inline_subscribe.ex
Raw

lib/ccxt/ws/auth/inline_subscribe.ex

defmodule CCXT.WS.Auth.InlineSubscribe do
@moduledoc """
Inline Subscribe auth pattern — coinbaseexchange.
Auth data is attached to each private subscribe frame rather than sent
as a standalone auth message. `build_auth_message/3` therefore returns
`:no_message`; the per-subscribe fields come from `build_subscribe_auth/4`.
## Payload Format (matches CCXT's `coinbaseexchange.authenticate()`)
timestamp_seconds <> "GET" <> "/users/self/verify"
The secret is base64-decoded before HMAC-SHA256 and the signature is
base64-encoded. `credentials.password` (passphrase) is included when set.
## Example Subscribe with Auth (coinbase)
%{
"type" => "subscribe",
"product_ids" => ["BTC-USD"],
"channels" => ["level2"],
"key" => "api_key_here",
"timestamp" => "1699999999",
"signature" => "base64_signature",
"passphrase" => "my_passphrase"
}
"""
@behaviour CCXT.WS.Auth.Behaviour
alias CCXT.Signing
@verify_path "/users/self/verify"
@impl true
def pre_auth(_credentials, _config, _opts), do: {:ok, %{}}
@impl true
def build_auth_message(_credentials, _config, _opts), do: :no_message
@impl true
def handle_auth_response(_response, _state), do: :ok
@impl true
def build_subscribe_auth(credentials, config, _channel, _symbols) do
api_key = credentials.api_key
secret = credentials.secret
passphrase = credentials.password
timestamp = to_string(Signing.timestamp_seconds_from_config(config))
payload = timestamp <> "GET" <> @verify_path
# Coinbase delivers its secret as base64; decode before signing.
secret_binary = Signing.decode_base64(secret)
signature = payload |> Signing.hmac_sha256(secret_binary) |> Signing.encode_base64()
result = %{
"key" => api_key,
"timestamp" => timestamp,
"signature" => signature
}
if passphrase, do: Map.put(result, "passphrase", passphrase), else: result
end
end