View Source Hyperliquid.Api.SubscriptionEndpoint (hyperliquid v0.2.2)

DSL for defining WebSocket subscription endpoints.

This macro reduces boilerplate while preserving explicit Ecto schemas for event validation and optional storage configuration.

Usage

defmodule Hyperliquid.Api.Subscription.L2Book do
  use Hyperliquid.Api.SubscriptionEndpoint,
    request_type: "l2Book",
    params: [:coin],
    optional_params: [:nSigFigs, :mantissa],
    storage: [
      cache: [enabled: true, key_pattern: "l2book:{{coin}}"]
    ]

  @primary_key false
  embedded_schema do
    field :coin, :string
    field :levels, {:array, {:array, :any}}
    field :time, :integer
  end

  def changeset(event \ %__MODULE__{}, attrs) do
    event
    |> cast(attrs, [:coin, :levels, :time])
  end
end

Generated Functions

  • build_request/1 - Build and validate subscription request
  • __subscription_info__/0 - Returns metadata for the manager
  • __storage_config__/0 - Returns storage configuration
  • generate_subscription_key/1 - Generate unique key for this subscription variant
  • build_cache_key/1 - Generate cache key from event data (if cache enabled)
  • extract_records/1 - Extract records from event for storage (if postgres enabled)

Options

  • :request_type - Required. The subscription type (e.g., "l2Book")
  • :params - List of required parameters as atoms
  • :optional_params - List of optional parameters as atoms
  • :connection_type - Connection routing strategy:
    • :shared - Can share connection with other subscriptions (default)
    • :dedicated - Needs its own connection per parameter variant
    • :user_grouped - Must share connection with other subs for same user
  • :doc - Short description of the subscription
  • :key_fields - Fields to include in subscription key (default: all params)
  • :ws_url - Custom WebSocket URL function (e.g., &Hyperliquid.Config.rpc_ws_url/0)
  • :storage - Storage configuration (see below)

Storage Options

The :storage option accepts a keyword list with the following backends:

Postgres Storage

storage: [
  postgres: [
    enabled: true,
    table: "trades",
    extract: :trades,  # optional: field containing nested records to store
    fields: [:coin, :side, :px]  # optional: only store these fields
  ]
]

Cache Storage

storage: [
  cache: [
    enabled: true,
    ttl: :timer.minutes(5),       # optional TTL
    key_pattern: "l2book:{{coin}}", # template with {{field}} placeholders
    fields: [:coin, :levels]      # optional: only cache these fields
  ]
]

Both backends can be enabled simultaneously.

Partial Storage (fields option)

Use the fields option to save only specific fields from complex events. This is useful for subscriptions like webData2 that contain both user-specific data and market data, where you only want to persist certain parts:

storage: [
  postgres: [
    enabled: true,
    table: "user_snapshots",
    fields: [:user, :clearinghouse_state, :open_orders, :spot_state]
  ]
]

Summary

Functions

Extract specific fields from an event map.

Interpolate a key pattern with event data.

Functions

Link to this function

extract_fields(event, fields)

View Source
@spec extract_fields(map() | struct(), [atom()] | nil) :: map()

Extract specific fields from an event map.

If fields is nil or empty, returns the full event. Supports both atom and string keys, and handles nested structs/embeds.

Examples

iex> extract_fields(%{a: 1, b: 2, c: 3}, [:a, :b])
%{a: 1, b: 2}

iex> extract_fields(%{user: "0x123", data: %{x: 1}}, nil)
%{user: "0x123", data: %{x: 1}}
Link to this function

interpolate_key_pattern(pattern, event_data)

View Source
@spec interpolate_key_pattern(String.t(), map()) :: String.t()

Interpolate a key pattern with event data.

Replaces {{field}} placeholders with actual values from the event.

Examples

iex> interpolate_key_pattern("trades:{{coin}}:{{time}}", %{coin: "BTC", time: 123})
"trades:BTC:123"

iex> interpolate_key_pattern("l2book:{{coin}}", %{"coin" => "ETH"})
"l2book:ETH"