Packages

An Elixir client for the Polymarket API.

Current section

Files

Jump to
ex_polymarket lib schemas price_change_event.ex
Raw

lib/schemas/price_change_event.ex

defmodule Polymarket.Schemas.PriceChangeEvent do
@moduledoc """
Price change event.
"""
use TypedEctoSchema
alias Polymarket.Schemas.Coerce
alias Polymarket.Schemas.PriceChange
alias Polymarket.Schemas.PriceChangeEvent
@primary_key false
@derive Jason.Encoder
typed_embedded_schema do
field(:market, :string)
# Unix epoch in milliseconds, delivered as a string (e.g. "1779656681214").
field(:timestamp, :integer)
field(:event_type, :string)
embeds_many(:price_changes, PriceChange)
end
@required [:market, :timestamp, :event_type]
@doc """
Builds a `PriceChangeEvent` from a decoded (atom-keyed) websocket message.
Constructs the struct directly — no `Ecto.Changeset` — for the websocket hot
path. Numeric fields (delivered as JSON strings) are coerced via
`Polymarket.Schemas.Coerce`. Returns `{:error, {:missing_fields, fields}}` when
a required field is absent.
"""
@spec from_attrs(map()) :: {:ok, t()} | {:error, {:missing_fields, [atom()]}}
def from_attrs(attrs) do
%PriceChangeEvent{
market: attrs[:market],
timestamp: Coerce.to_int(attrs[:timestamp]),
event_type: attrs[:event_type],
price_changes: price_changes(attrs[:price_changes])
}
|> Coerce.require_fields(@required)
end
@spec price_changes([map()] | nil) :: [PriceChange.t()]
defp price_changes(nil), do: []
defp price_changes(changes) do
Enum.map(changes, fn change ->
%PriceChange{
asset_id: change[:asset_id],
price: Coerce.to_float(change[:price]),
size: Coerce.to_float(change[:size]),
side: change[:side],
hash: change[:hash],
best_bid: Coerce.to_float(change[:best_bid]),
best_ask: Coerce.to_float(change[:best_ask])
}
end)
end
end