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 subscription custom.ex
Raw

lib/ccxt/ws/subscription/custom.ex

defmodule CCXT.WS.Subscription.Custom do
@moduledoc """
Escape hatch for exchanges whose subscribe frames don't fit any named
pattern. The module dispatches on `config[:custom_type]`:
| custom_type | Exchange | Shape |
|--------------------|---------------------|-------------------------------------------|
| `"array_format"` | Upbit | `[[%{type, codes}, ...]]` — array of maps |
| `"sendTopicAction"`| Deepcoin | Nested `sendTopicAction` envelope |
| _(default)_ | — fallback | `%{"subscribe" => true, "channels" => […]}` |
`subscribe/2` for Upbit returns a `[map()]` (one envelope per channel);
all others return a single `map()`. Callers must pass `config[:custom_type]`
explicitly — no priority-tier exchange wires this pattern in T94 (custom
DEX exchanges like Hyperliquid/Derive/Lighter are deferred).
"""
@behaviour CCXT.WS.Subscription.Behaviour
@impl true
def subscribe(channels, config) when is_list(channels) do
build(channels, config, "subscribe")
end
@impl true
def unsubscribe(channels, config) when is_list(channels) do
build(channels, config, "unsubscribe")
end
defp build(channels, config, action) do
case Map.get(config, :custom_type) do
"array_format" -> build_array_format(channels, action)
"sendTopicAction" -> build_send_topic_action(channels, action)
_ -> build_default(channels, action)
end
end
# Upbit-style: one envelope per channel.
defp build_array_format(channels, "subscribe") do
Enum.map(channels, fn channel -> %{"type" => "ticker", "codes" => [channel]} end)
end
defp build_array_format(channels, "unsubscribe") do
Enum.map(channels, fn channel ->
%{"type" => "ticker", "codes" => [channel], "isOnlyRealtime" => true}
end)
end
defp build_send_topic_action(channels, action) do
%{"sendTopicAction" => %{"action" => action, "topics" => channels}}
end
defp build_default(channels, "subscribe"), do: %{"subscribe" => true, "channels" => channels}
defp build_default(channels, "unsubscribe"), do: %{"unsubscribe" => true, "channels" => channels}
end