DeribitEx.Client (deribit_ex v0.1.0)
View SourceUser-friendly client interface for interacting with the Deribit WebSocket API.
This module provides simplified methods for:
- Connecting and disconnecting
- Authentication (public/auth, token exchange, token forking, and logout)
- Utility endpoints (get_time, hello, status, test)
- Session management (heartbeat, cancel on disconnect)
- Subscription management for various Deribit channels
Public Utility Endpoints
# Sync clocks with the server
{:ok, timestamp} = Client.get_time(conn)
# Introduce the client to the server
{:ok, server_info} = Client.hello(conn, "my_bot", "1.0.0")
# Check system status
{:ok, status} = Client.status(conn)
# Simple connectivity test
{:ok, result} = Client.test(conn, "echo_me")
Authentication
# Authenticate with credentials from environment variables
{:ok, conn} = Client.authenticate(conn)
# Exchange token for a different subaccount
{:ok, _} = Client.exchange_token(conn, refresh_token, subject_id)
# Create a named session
{:ok, _} = Client.fork_token(conn, refresh_token, "analytics_session")
# Logout
{:ok, conn} = Client.logout(conn)
Subscriptions
# Subscribe to trades for BTC-PERPETUAL
{:ok, sub_id} = Client.subscribe_to_trades(conn, "BTC-PERPETUAL")
# Subscribe to orderbook with depth=10
{:ok, sub_id} = Client.subscribe_to_orderbook(conn, "BTC-PERPETUAL", "100ms", 10)
Summary
Functions
Authenticate with the Deribit API using client credentials.
Connect to the Deribit WebSocket API.
Get the current server time from the TimeSyncService without making a request.
Disable Cancel on Disconnect (COD) for the specified scope.
Disable heartbeat messages from the Deribit server.
Close the WebSocket connection to the Deribit API.
Enable Cancel on Disconnect (COD) for the current session.
Generate a new access token for switching between subaccounts.
Generate a token for a new named session.
Get the current Cancel on Disconnect (COD) configuration.
Fetch Deribit's current server time (ms since epoch).
Send a hello message to introduce the client to Deribit.
Initialize the Deribit connection with a bootstrap sequence.
Send a custom JSON-RPC request to the Deribit API.
Logout and optionally invalidate tokens.
Parse a JSON-RPC response and extract the result or error.
Enable heartbeat messages from the Deribit server.
Get the system status from Deribit.
Subscribe to a Deribit orderbook channel for a specific instrument.
Subscribe to a Deribit ticker channel for a specific instrument.
Subscribe to a Deribit trades channel for a specific instrument.
Subscribe to user's orders for a specific instrument. Requires authentication.
Subscribe to user's trades for a specific instrument. Requires authentication.
Send a test request to Deribit.
Unsubscribe from specific channels.
Unsubscribe from all channels.
Unsubscribe from private channels.
Functions
Authenticate with the Deribit API using client credentials.
Uses credentials from the environment variables DERIBIT_CLIENT_ID and DERIBIT_CLIENT_SECRET if not provided.
Options
:api_key
- Deribit API key (optional if in environment):secret
- Deribit API secret (optional if in environment)opts
- Additional options passed to the authentication request (e.g., timeout settings)
Examples
# Authenticate using environment variables
{:ok, conn} = Client.authenticate(conn)
# Authenticate with explicit credentials
{:ok, conn} = Client.authenticate(conn, %{
api_key: "your_api_key",
secret: "your_secret"
})
Connect to the Deribit WebSocket API.
Uses environment-specific endpoints (test.deribit.com for dev/test, www.deribit.com for production) unless overridden.
Options
All WebsockexNova.Client options are supported, plus:
:host
- Override the default host (optional):callback_pid
- Process to receive WebSocket events (optional):auth_refresh_threshold
- Seconds before token expiration to refresh (defaults to 180s)- Deribit tokens usually last 900 seconds (15 minutes)
- Recommended refresh threshold is 180-300 seconds before expiration
- Can also be set via DERIBIT_AUTH_REFRESH_THRESHOLD environment variable
- Valid range: 1-899 seconds
- Smaller values risk token expiration during high latency periods
- Larger values cause more frequent token refreshes
- Value of 180s balances reliability with refresh frequency
:rate_limit_mode
- Rate limiting strategy (defaults to :normal):cautious
- Strict limits to avoid 429s completely (60 req/sec):normal
- Balanced approach (120 req/sec):aggressive
- Higher throughput (200 req/sec), might get occasional 429s- Can also be set via DERIBIT_RATE_LIMIT_MODE environment variable
Rate Limiting Behavior
The connection uses a custom adaptive rate limiter that:
- Adjusts rate limits dynamically based on Deribit API responses
- Implements exponential backoff when 429 responses are received
- Prioritizes critical operations like order cancellation
- Gradually recovers request rates after backoff periods
- Emits detailed telemetry for monitoring rate limiting behavior
Examples
# Connect with default options
{:ok, conn} = Client.connect()
# Connect with custom host
{:ok, conn} = Client.connect(%{host: "custom.deribit.com"})
# Connect with callback process
{:ok, conn} = Client.connect(%{callback_pid: self()})
# Connect with custom auth refresh threshold (5 minutes)
{:ok, conn} = Client.connect(%{auth_refresh_threshold: 300})
# Connect with cautious rate limiting
{:ok, conn} = Client.connect(%{rate_limit_mode: :cautious})
Get the current server time from the TimeSyncService without making a request.
This function returns the estimated server time based on the local time and the time delta maintained by the TimeSyncService. It is useful when you need to know the server time without making an additional request to the server.
Parameters
conn
- Connection process PID
Returns
{:ok, server_time_ms}
- The current server time in milliseconds{:error, :no_time_sync}
- If time sync service is not running for this connection
Examples
# Get the current estimated server time
{:ok, server_time} = Client.current_server_time(conn)
@spec disable_cancel_on_disconnect(pid(), String.t(), map() | nil) :: {:ok, String.t()} | {:error, any()}
Disable Cancel on Disconnect (COD) for the specified scope.
Parameters
conn
- Connection process PIDscope
- Scope of the COD setting ("connection" or "account", defaults to "connection")opts
- Optional request options
Returns
{:ok, "ok"}
- Success response indicating COD is disabled{:error, reason}
- If the request fails
Examples
# Disable COD for current connection
{:ok, _} = Client.disable_cancel_on_disconnect(conn)
# Disable COD for the entire account
{:ok, _} = Client.disable_cancel_on_disconnect(conn, "account")
Disable heartbeat messages from the Deribit server.
Parameters
conn
- Connection process PIDopts
- Optional request options
Returns
{:ok, "ok"}
- Success response indicating heartbeat is disabled{:error, reason}
- If the request fails
Examples
# Disable heartbeat
{:ok, _} = Client.disable_heartbeat(conn)
Close the WebSocket connection to the Deribit API.
Parameters
conn
- Connection process PIDreason
- Reason for disconnection (optional)
Examples
# Close with normal reason
:ok = Client.disconnect(conn)
# Close with custom reason
:ok = Client.disconnect(conn, :shutdown)
@spec enable_cancel_on_disconnect(pid(), String.t(), map() | nil) :: {:ok, String.t()} | {:error, any()}
Enable Cancel on Disconnect (COD) for the current session.
When enabled, all orders created during the connection will be automatically cancelled if the connection is closed or interrupted. This is a safety feature to prevent orphaned orders in case of connection issues.
Parameters
conn
- Connection process PIDscope
- Scope of the COD setting ("connection" or "account", defaults to "connection")opts
- Optional request options
Returns
{:ok, "ok"}
- Success response indicating COD is enabled{:error, reason}
- If the request fails
Examples
# Enable COD for current connection only
{:ok, _} = Client.enable_cancel_on_disconnect(conn)
# Enable COD for the entire account
{:ok, _} = Client.enable_cancel_on_disconnect(conn, "account")
@spec exchange_token( pid(), String.t() | nil, integer() | String.t() | nil, map() | nil ) :: {:ok, any()} | {:error, any()}
Generate a new access token for switching between subaccounts.
Uses the refresh token to create a new authentication session for a different subject ID.
Parameters
conn
- Connection process PIDrefresh_token
- Valid refresh token (optional, uses stored token if available)subject_id
- ID of the subaccount to switch toopts
- Additional options for the request (optional)
Examples
# Exchange token to switch to subaccount with ID 10
{:ok, response} = Client.exchange_token(conn, "refresh_token_value", 10)
# Exchange token using a stored refresh token
{:ok, response} = Client.exchange_token(conn, nil, 10)
@spec fork_token(pid(), String.t() | nil, String.t() | atom() | nil, map() | nil) :: {:ok, any()} | {:error, any()}
Generate a token for a new named session.
Uses the refresh token to create a new authentication session with the specified name.
Parameters
conn
- Connection process PIDrefresh_token
- Valid refresh token (optional, uses stored token if available)session_name
- Name for the new sessionopts
- Additional options for the request (optional)
Examples
# Fork token to create a new named session
{:ok, response} = Client.fork_token(conn, "refresh_token_value", "trading_session")
# Fork token using a stored refresh token
{:ok, response} = Client.fork_token(conn, nil, "analytics_session")
Get the current Cancel on Disconnect (COD) configuration.
Parameters
conn
- Connection process PIDopts
- Optional request options
Returns
{:ok, %{"scope" => scope, "enabled" => enabled}}
- The current COD configuration{:error, reason}
- If the request fails
Examples
# Check if COD is enabled for the connection
{:ok, %{"enabled" => true, "scope" => "connection"}} = Client.get_cancel_on_disconnect(conn)
Fetch Deribit's current server time (ms since epoch).
Parameters
conn
– the WebSocket client PIDopts
– optional JSON-RPC options
Returns
{:ok, timestamp}
on success{:error, reason}
on failure
@spec hello(pid(), String.t() | nil, String.t() | nil, map() | nil) :: {:ok, any()} | {:error, any()}
Send a hello message to introduce the client to Deribit.
Used to identify the client to the server and establish the initial session.
Parameters
conn
- Connection process PIDclient_name
- The name of the client (defaults to "market_maker")client_version
- The version of the client (defaults to "1.0.0")opts
- Optional request options
Returns
{:ok, result}
- Success response with server version{:error, reason}
- If the request fails
Examples
# Send hello with default client info
{:ok, server_info} = Client.hello(conn)
# Send hello with custom client info
{:ok, server_info} = Client.hello(conn, "my_trading_bot", "2.1.0")
Initialize the Deribit connection with a bootstrap sequence.
After connecting to Deribit via WebSocket, this function performs a bootstrap sequence to properly initialize the session:
/public/hello
to introduce client name & version/public/get_time
to sync clocks/public/status
to check account status/public/set_heartbeat
to enable heartbeats (minimum 10s)/private/enable_cancel_on_disconnect
with default scope for COD safety (requires authentication first)
The adapter is also set up to automatically handle incoming test_request
messages by responding with /public/test
.
Parameters
conn
- Connection process PIDopts
- Optional bootstrap configuration::client_name
- Custom client name (defaults to "market_maker"):client_version
- Custom client version (defaults to "1.0.0"):heartbeat_interval
- Heartbeat interval in seconds (defaults to 30, minimum 10):cod_scope
- Scope for cancel-on-disconnect (defaults to "connection"):authenticate
- Whether to authenticate before other steps (defaults to true)
Returns
{:ok, bootstrap_results}
- Success with a map of all bootstrap operation results{:error, step, reason}
- First failed operation with the reason
Examples
# Initialize with default settings
{:ok, results} = Client.initialize(conn)
# Custom initialization
{:ok, results} = Client.initialize(conn, %{
client_name: "trading_bot",
client_version: "2.0.0",
heartbeat_interval: 15,
cod_scope: "account"
})
# Skip authentication
{:ok, results} = Client.initialize(conn, %{authenticate: false})
Send a custom JSON-RPC request to the Deribit API.
Parameters
conn
- Connection process PIDmethod
- RPC method name (e.g., "public/get_instruments")params
- Method parameters (map)opts
- Optional request options
Examples
# Get available instruments for BTC
{:ok, response} = Client.json_rpc(conn, "public/get_instruments", %{
currency: "BTC",
kind: "future"
})
Logout and optionally invalidate tokens.
Gracefully closes the session with the Deribit API and optionally invalidates all tokens created in the current session. This is important for secure session management.
This function:
- Sends the private/logout RPC request
- Cleans up authentication state in the adapter
- Automatically closes the WebSocket connection afterwards
The invalidate_token parameter determines whether to invalidate all tokens:
- When set to true (default), all access and refresh tokens become invalid
- When set to false, tokens remain valid but the current session ends
Parameters
conn
- Connection process PIDinvalidate_token
- Whether to invalidate all tokens (default: true)opts
- Additional options for the request (optional)::timeout
- Request timeout in milliseconds (default: 10000)
Returns
{:ok, conn}
- On successful logout, even though the connection is closed{:error, reason}
- If the logout request fails
Notes
- The WebSocket connection is automatically closed after logout
- The adapter state is updated to remove authentication data
- In high-latency environments, the request may timeout
Examples
# Logout and invalidate all tokens
{:ok, conn} = Client.logout(conn)
# Logout without invalidating tokens
{:ok, conn} = Client.logout(conn, false)
# Logout with custom timeout
{:ok, conn} = Client.logout(conn, true, %{timeout: 30000})
Parse a JSON-RPC response and extract the result or error.
This helper function provides consistent handling of JSON-RPC responses, extracting the relevant result or error from the response envelope.
Parameters
response
- The raw response from a JSON-RPC call
Returns
{:ok, result}
- On successful responses{:error, error}
- On error responses
Examples
iex> Client.parse_response(%{"jsonrpc" => "2.0", "id" => 1, "result" => 123})
{:ok, 123}
iex> Client.parse_response(%{"jsonrpc" => "2.0", "id" => 1, "error" => %{"code" => 10001, "message" => "Error"}})
{:error, %{"code" => 10001, "message" => "Error"}}
@spec set_heartbeat(pid(), pos_integer(), map() | nil) :: {:ok, String.t()} | {:error, any()}
Enable heartbeat messages from the Deribit server.
Heartbeats are used to detect stale connections. When enabled, the server will send test_request messages periodically, and the adapter will automatically respond to them.
Parameters
conn
- Connection process PIDinterval
- Heartbeat interval in seconds (min: 10, defaults to 30)opts
- Optional request options
Returns
{:ok, "ok"}
- Success response indicating heartbeat is enabled{:error, reason}
- If the request fails
Examples
# Enable heartbeat with default 30 second interval
{:ok, _} = Client.set_heartbeat(conn)
# Enable heartbeat with custom interval
{:ok, _} = Client.set_heartbeat(conn, 15)
Get the system status from Deribit.
Returns information about the status of the API, including any service disruptions, scheduled maintenance, or important announcements.
Parameters
conn
- Connection process PIDopts
- Optional request options
Returns
{:ok, status}
- The system status information{:error, reason}
- If the request fails
Examples
# Check if the system is operational
{:ok, status} = Client.status(conn)
# Handle possible maintenance mode
case Client.status(conn) do
{:ok, %{"status" => "ok"}} -> # System is operational
{:ok, %{"status" => "maintenance"}} -> # System is in maintenance mode
{:error, reason} -> # Request failed
end
@spec subscribe_to_orderbook( pid(), String.t(), String.t(), integer() | nil, map() | nil ) :: {:ok, any()} | {:error, any()}
Subscribe to a Deribit orderbook channel for a specific instrument.
Parameters
conn
- Connection process PIDinstrument
- Instrument name (e.g., "BTC-PERPETUAL")interval
- Update interval (optional, e.g., "100ms", "raw")depth
- Orderbook depth (optional, default is full orderbook)
Example
{:ok, sub_id} = Client.subscribe_to_orderbook(conn, "BTC-PERPETUAL", "100ms", 10)
@spec subscribe_to_ticker(pid(), String.t(), String.t(), map() | nil) :: {:ok, any()} | {:error, any()}
Subscribe to a Deribit ticker channel for a specific instrument.
Parameters
conn
- Connection process PIDinstrument
- Instrument name (e.g., "BTC-PERPETUAL")interval
- Update interval (optional, e.g., "100ms", "raw")
Example
{:ok, sub_id} = Client.subscribe_to_ticker(conn, "BTC-PERPETUAL", "100ms")
@spec subscribe_to_trades(pid(), String.t(), String.t(), map() | nil) :: {:ok, any()} | {:error, any()}
Subscribe to a Deribit trades channel for a specific instrument.
Parameters
conn
- Connection process PIDinstrument
- Instrument name (e.g., "BTC-PERPETUAL")interval
- Update interval (optional, e.g., "100ms", "raw")
Example
{:ok, sub_id} = Client.subscribe_to_trades(conn, "BTC-PERPETUAL", "100ms")
@spec subscribe_to_user_orders(pid(), String.t(), String.t(), map() | nil) :: {:ok, any()} | {:error, any()}
Subscribe to user's orders for a specific instrument. Requires authentication.
Parameters
conn
- Connection process PIDinstrument
- Instrument name (e.g., "BTC-PERPETUAL")interval
- Update interval (optional, defaults to "raw")
Example
{:ok, sub_id} = Client.subscribe_to_user_orders(conn, "BTC-PERPETUAL")
@spec subscribe_to_user_trades(pid(), String.t(), String.t(), map() | nil) :: {:ok, any()} | {:error, any()}
Subscribe to user's trades for a specific instrument. Requires authentication.
Parameters
conn
- Connection process PIDinstrument
- Instrument name (e.g., "BTC-PERPETUAL")interval
- Update interval (optional, defaults to "raw")
Example
{:ok, sub_id} = Client.subscribe_to_user_trades(conn, "BTC-PERPETUAL")
Send a test request to Deribit.
This endpoint is primarily used to respond to test_request messages sent by the server as part of the heartbeat mechanism. It can also be used as a simple connectivity check.
Parameters
conn
- Connection process PIDexpected_result
- The expected result to be echoed back (optional)opts
- Optional request options
Returns
{:ok, result}
- Success response, echoing back the expected_result if provided{:error, reason}
- If the request fails
Examples
# Simple connectivity test
{:ok, _} = Client.test(conn)
# Test with expected result echo
{:ok, "hello"} = Client.test(conn, "hello")
Unsubscribe from specific channels.
Parameters
conn
- Connection process PIDchannels
- Single channel string or list of channels to unsubscribe fromopts
- Optional request options
Returns
{:ok, result}
- Success response with list of unsubscribed channels{:error, reason}
- If the request fails
Examples
# Unsubscribe from a trades channel
{:ok, _} = Client.unsubscribe(conn, "trades.BTC-PERPETUAL.100ms")
# Unsubscribe from multiple channels at once
{:ok, _} = Client.unsubscribe(conn, [
"trades.BTC-PERPETUAL.100ms",
"ticker.BTC-PERPETUAL.raw"
])
Unsubscribe from all channels.
Parameters
conn
- Connection process PIDopts
- Optional request options
Returns
{:ok, "ok"}
- Success response{:error, reason}
- If the request fails
Examples
# Unsubscribe from all active channels
{:ok, _} = Client.unsubscribe_all(conn)
@spec unsubscribe_private(pid(), String.t() | [String.t()], map() | nil) :: {:ok, map()} | {:error, any()}
Unsubscribe from private channels.
A convenience function that ensures the private/unsubscribe method is used, which is required for channels that need authentication.
Parameters
conn
- Connection process PIDchannels
- Single channel string or list of channels to unsubscribe fromopts
- Optional request options
Returns
{:ok, result}
- Success response with list of unsubscribed channels{:error, reason}
- If the request fails
Examples
# Unsubscribe from a user orders channel
{:ok, _} = Client.unsubscribe_private(conn, "user.orders.BTC-PERPETUAL.raw")
# Unsubscribe from multiple private channels
{:ok, _} = Client.unsubscribe_private(conn, [
"user.orders.BTC-PERPETUAL.raw",
"user.trades.BTC-PERPETUAL.raw"
])