Signing pattern library for exchange authentication.
Provides a unified interface for signing API requests across 100+ cryptocurrency exchanges. Instead of per-exchange signing code, 9 parameterized patterns cover 95%+ of all exchanges:
| Pattern | Exchanges | Description |
|---|---|---|
:hmac_sha256_query | ~40 | Binance-style: sign query string |
:hmac_sha256_headers | ~30 | Bybit-style: sign body, headers |
:hmac_sha256_iso_passphrase | ~10 | OKX-style: ISO timestamp + passphrase |
:hmac_sha256_passphrase_signed | ~3 | KuCoin-style: HMAC-signed passphrase |
:hmac_sha512_nonce | ~3 | Kraken-style: SHA512 + nonce + base64 secret |
:hmac_sha512_gate | 1 | Gate.io-style: SHA512 + newline payload |
:hmac_sha384_payload | ~3 | Bitfinex-style: payload signing |
:deribit | 1 | Custom Authorization header format |
:custom | <5% | Escape hatch for edge cases |
Usage
signed = CCXT.Signing.sign(
:hmac_sha256_headers,
%{method: :get, path: "/v5/account/wallet-balance", body: nil, params: %{}},
credentials,
signing_config
)Custom Signing Patterns
Implement CCXT.Signing.Behaviour and use the :custom pattern:
defmodule MyApp.Signing.MyExchange do
@behaviour CCXT.Signing.Behaviour
@impl true
def sign(request, credentials, config) do
%{url: request.path, method: request.method, headers: [], body: request.body}
end
endSee CCXT.Signing.Behaviour for the full contract.
Summary
Functions
Decodes a Base64-encoded string. Raises on invalid input.
Base64-encodes a binary.
Lowercase hex-encodes a binary.
HMAC-SHA256 of data with secret.
HMAC-SHA384 of data with secret.
HMAC-SHA512 of data with secret.
Returns the signing module for a given pattern.
Returns config[:nonce_override] when set, otherwise invokes fallback.
Fallback is a zero-arity function so callers control nonce semantics
(e.g. :erlang.unique_integer vs System.system_time(:microsecond)).
Checks if a pattern is supported.
Returns the list of supported signing patterns.
SHA-256 hash of data.
SHA-512 hash of data.
Signs a request using the specified pattern and configuration.
Current UTC time as ISO 8601 string, truncated to millisecond precision.
Like timestamp_ms_from_config/1 but rendered as ISO 8601 UTC.
Current UTC time in milliseconds.
Returns config[:timestamp_ms_override] when set, otherwise current wall
time in milliseconds. Used by pattern modules so fixture replay (T65) can
inject the frozen timestamp CCXT JS signed with.
Current UTC time in seconds.
Like timestamp_ms_from_config/1 but in seconds.
URL-encodes params as a sorted query string.
URL-encodes params as a sorted query string without percent-encoding values.
Types
@type config() :: %{ optional(:api_key_header) => String.t(), optional(:timestamp_header) => String.t(), optional(:signature_header) => String.t(), optional(:passphrase_header) => String.t(), optional(:recv_window_header) => String.t(), optional(:recv_window) => non_neg_integer(), optional(:signature_encoding) => :hex | :base64, optional(:custom_module) => module(), optional(atom()) => term() }
@type method() :: :get | :post | :put | :delete
@type pattern() ::
:hmac_sha256_query
| :hmac_sha256_headers
| :hmac_sha256_iso_passphrase
| :hmac_sha256_passphrase_signed
| :hmac_sha512_nonce
| :hmac_sha512_gate
| :hmac_sha384_payload
| :deribit
| :custom
Functions
Decodes a Base64-encoded string. Raises on invalid input.
Base64-encodes a binary.
Lowercase hex-encodes a binary.
HMAC-SHA256 of data with secret.
HMAC-SHA384 of data with secret.
HMAC-SHA512 of data with secret.
Returns the signing module for a given pattern.
Returns config[:nonce_override] when set, otherwise invokes fallback.
Fallback is a zero-arity function so callers control nonce semantics
(e.g. :erlang.unique_integer vs System.system_time(:microsecond)).
Checks if a pattern is supported.
@spec patterns() :: [pattern()]
Returns the list of supported signing patterns.
SHA-256 hash of data.
SHA-512 hash of data.
@spec sign(pattern(), request(), CCXT.Credentials.t(), config()) :: signed_request()
Signs a request using the specified pattern and configuration.
Parameters
pattern- The signing pattern atom (e.g.,:hmac_sha256_headers)request- Map with:method,:path,:body, and:paramscredentials-CCXT.Credentialsstruct with API key and secretconfig- Pattern-specific configuration from the exchange spec
Returns
A signed request map with :url, :method, :headers, and :body.
@spec timestamp_iso8601() :: String.t()
Current UTC time as ISO 8601 string, truncated to millisecond precision.
Like timestamp_ms_from_config/1 but rendered as ISO 8601 UTC.
@spec timestamp_ms() :: non_neg_integer()
Current UTC time in milliseconds.
@spec timestamp_ms_from_config(map()) :: non_neg_integer()
Returns config[:timestamp_ms_override] when set, otherwise current wall
time in milliseconds. Used by pattern modules so fixture replay (T65) can
inject the frozen timestamp CCXT JS signed with.
@spec timestamp_seconds() :: non_neg_integer()
Current UTC time in seconds.
@spec timestamp_seconds_from_config(map()) :: non_neg_integer()
Like timestamp_ms_from_config/1 but in seconds.
URL-encodes params as a sorted query string.
URL-encodes params as a sorted query string without percent-encoding values.