View Source Hyperliquid.WebSocket.Manager (hyperliquid v0.4.1)

WebSocket connection and subscription manager.

Manages multiple WebSocket connections, routes subscriptions to appropriate connections, and provides a registry of active subscriptions.

Connection Strategy

All subscriptions share as few connections as possible within Hyperliquid's limits:

  • Shared socket ("shared") — all :shared and :dedicated subscriptions land here. The :dedicated type is legacy; modules may still declare it but the manager treats it identically to :shared.

  • First user socket — when the first :user_grouped subscription is created, it is placed on the shared socket. No extra connection is opened.

  • Per-user sockets ("user:<address>") — each additional unique user gets its own connection so that message routing remains unambiguous (the connection itself is the routing tag; user addresses are not guaranteed in WS responses).

Because the shared socket carries mixed subscription types, the manager filters incoming messages by channel before dispatching to each subscription's callback.

Usage

# Subscribe to allMids (shared socket)
{:ok, sub_id} = Manager.subscribe(Hyperliquid.Api.Subscription.AllMids, %{})

# Subscribe to l2Book — also lands on the shared socket
{:ok, sub_id} = Manager.subscribe(Hyperliquid.Api.Subscription.L2Book, %{
  coin: "BTC", nSigFigs: 5
})

# First user subscription — shares the existing shared socket
{:ok, sub_id} = Manager.subscribe(Hyperliquid.Api.Subscription.UserFills, %{
  user: "0x1234..."
})

# Second user — gets its own socket
{:ok, sub_id} = Manager.subscribe(Hyperliquid.Api.Subscription.UserFills, %{
  user: "0xabcd..."
})

# Unsubscribe
:ok = Manager.unsubscribe(sub_id)

# List active subscriptions
Manager.list_subscriptions()

Architecture

The Manager uses a DynamicSupervisor to manage WebSocket connections. Each connection is a GenServer that handles the actual WebSocket communication. The Manager maintains:

  1. A registry of active subscriptions (ETS table)
  2. A mapping of connection keys to connection PIDs
  3. Connection metadata and per-subscription metrics

Summary

Functions

Returns a specification to start this module under a supervisor.

Get connection info for debugging.

Get metrics for a specific subscription.

Get subscription by ID.

Get metrics for all subscriptions.

List all active subscriptions.

List subscriptions for a specific user.

Start the WebSocket manager.

Subscribe to a WebSocket endpoint.

Unsubscribe from a WebSocket endpoint.

Types

@type connection_type() :: :shared | :dedicated | :user_grouped
@type subscription_id() :: String.t()

Functions

Returns a specification to start this module under a supervisor.

See Supervisor.

@spec connection_info() :: map()

Get connection info for debugging.

Link to this function

get_metrics(subscription_id)

View Source
@spec get_metrics(subscription_id()) :: {:ok, map()} | {:error, :not_found}

Get metrics for a specific subscription.

Parameters

  • subscription_id - The subscription ID

Returns

  • {:ok, metrics} - Subscription metrics
  • {:error, :not_found} - Subscription not found

Metrics

  • :message_count - Total messages received
  • :last_message_at - Timestamp of last message
  • :subscribed_at - When subscription was created
  • :messages_per_minute - Average messages per minute
  • :uptime_seconds - Time since subscription started
Link to this function

get_subscription(subscription_id)

View Source
@spec get_subscription(subscription_id()) ::
  {:ok, Hyperliquid.WebSocket.Manager.Subscription.t()} | {:error, :not_found}

Get subscription by ID.

@spec list_all_metrics() :: [map()]

Get metrics for all subscriptions.

@spec list_subscriptions() :: [Hyperliquid.WebSocket.Manager.Subscription.t()]

List all active subscriptions.

Link to this function

list_user_subscriptions(user_address)

View Source
@spec list_user_subscriptions(String.t()) :: [
  Hyperliquid.WebSocket.Manager.Subscription.t()
]

List subscriptions for a specific user.

Start the WebSocket manager.

Link to this function

subscribe(module, params, callback \\ nil)

View Source
@spec subscribe(module(), map(), function() | nil) ::
  {:ok, subscription_id()} | {:error, term()}

Subscribe to a WebSocket endpoint.

Parameters

  • module - The subscription endpoint module
  • params - Subscription parameters
  • callback - Function to call with incoming messages (optional)

Returns

  • {:ok, subscription_id} - Subscription created
  • {:error, reason} - Failed to subscribe
Link to this function

unsubscribe(subscription_id)

View Source
@spec unsubscribe(subscription_id()) :: :ok | {:error, :not_found}

Unsubscribe from a WebSocket endpoint.

Parameters

  • subscription_id - The subscription ID returned from subscribe/3

Returns

  • :ok - Unsubscribed successfully
  • {:error, :not_found} - Subscription not found