Packages

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

Current section

Files

Jump to
ccxt_client lib ccxt signing hmac_sha512_gate.ex
Raw

lib/ccxt/signing/hmac_sha512_gate.ex

defmodule CCXT.Signing.HmacSha512Gate do
@moduledoc """
HMAC-SHA512 Gate.io-style signing pattern.
Used by: Gate.io
## How it works
1. Hash the body with SHA512 (empty string if no body)
2. Generate timestamp (seconds)
3. Build newline-separated payload: `METHOD\\npath\\nquery\\nbody_hash\\ntimestamp`
4. Sign with HMAC-SHA512, encode as hex
5. Secret used raw (NOT base64 decoded)
## Configuration
signing: %{
pattern: :hmac_sha512_gate,
api_key_header: "KEY",
signature_header: "SIGN",
timestamp_header: "Timestamp",
signing_path_prefix: "/api/v4"
}
"""
@behaviour CCXT.Signing.Behaviour
alias CCXT.Credentials
alias CCXT.Signing
@impl true
@spec sign(Signing.request(), Credentials.t(), Signing.config()) :: Signing.signed_request()
def sign(request, credentials, config) do
timestamp_string = to_string(Signing.timestamp_seconds_from_config(config))
query_string = Signing.urlencode(request.params)
# Gate.io requires hashing even empty body
body = request.body || ""
body_hash = body |> Signing.sha512() |> Signing.encode_hex()
signing_path = Map.get(config, :signing_path_prefix, "/api/v4") <> request.path
method = request.method |> to_string() |> String.upcase()
payload = Enum.join([method, signing_path, query_string, body_hash, timestamp_string], "\n")
signature =
payload
|> Signing.hmac_sha512(credentials.secret)
|> Signing.encode_hex()
url = if query_string == "", do: request.path, else: request.path <> "?" <> query_string
headers = build_headers(credentials, signature, timestamp_string, config)
%{
url: url,
method: request.method,
headers: headers,
body: if(body == "", do: nil, else: body)
}
end
defp build_headers(credentials, signature, timestamp, config) do
api_key_header = Map.get(config, :api_key_header, "KEY")
signature_header = Map.get(config, :signature_header, "SIGN")
timestamp_header = Map.get(config, :timestamp_header, "Timestamp")
[
{api_key_header, credentials.api_key},
{signature_header, signature},
{timestamp_header, timestamp},
{"Content-Type", "application/json"}
]
end
end