Translation between Polymarket CLOB order book payloads and
PaperEx.MarketSnapshot.
A CLOB /book response looks like:
%{
"market" => "0x…", # condition id
"asset_id" => "12345…", # token id
"bids" => [%{"price" => "0.53", "size" => "100"}, …],
"asks" => [%{"price" => "0.55", "size" => "80"}, …],
"timestamp" => "1700000000",
"tick_size" => "0.01",
…
}Prices and sizes arrive as decimal strings; this module parses them
into floats (matching polymarket_clob's float-first policy — see
Decision 6 in the workspace DECISIONS.md).
Sort order
PaperEx.MarketSnapshot.best_bid/best_ask take the list head, so
the head must be the BEST level (bids descending, asks ascending).
The live CLOB /book returns levels best price last (bids
ascending, asks descending), so this module re-sorts explicitly:
bids high→low and asks low→high. The sort is independent of the
venue's ordering, so a re-ordered payload still normalizes
correctly.
Summary
Functions
Builds a PaperEx.MarketSnapshot from a CLOB book body for the
given instrument.
Functions
@spec from_clob_book(map(), PaperEx.Instrument.t()) :: {:ok, PaperEx.MarketSnapshot.t()} | {:error, :invalid_book}
Builds a PaperEx.MarketSnapshot from a CLOB book body for the
given instrument.
Returns {:error, :invalid_book} if the payload is missing the
required "bids" / "asks" keys or if any level fails to parse.