Current section

Files

Jump to
stellar_sdk lib horizon mapping.ex
Raw

lib/horizon/mapping.ex

defmodule Stellar.Horizon.Mapping do
@moduledoc """
Takes a result map or list of maps from Horizon response and returns a struct
(e.g. `%Horizon.Transaction{}`) or list of structs.
"""
@type attr_type :: :integer | :float | :date_time | struct()
@type attr_value :: String.t() | integer() | float() | boolean() | struct() | list() | nil
@spec build(module :: struct(), attrs :: map()) :: struct()
def build(module, attrs) do
attrs =
module
|> Map.from_struct()
|> Map.keys()
|> (&Map.take(attrs, &1)).()
struct!(module, attrs)
end
@spec parse(module :: struct(), mapping :: Keyword.t()) :: struct()
def parse(module, []), do: module
def parse(module, [{attr, type} | attrs]) do
value = Map.get(module, attr)
parsed_value = do_parse(type, value)
module
|> Map.put(attr, parsed_value)
|> parse(attrs)
end
@spec do_parse(type :: attr_type(), value :: attr_value()) :: attr_value()
defp do_parse(:integer, value) when is_bitstring(value), do: String.to_integer(value)
defp do_parse(:float, value) when is_bitstring(value), do: String.to_float(value)
defp do_parse(:date_time, value) when is_bitstring(value) do
case DateTime.from_iso8601(value) do
{:ok, date_time, _offset} -> date_time
_error -> value
end
end
defp do_parse(%{__struct__: module}, values) when is_list(values) do
Enum.map(values, &module.new(&1))
end
defp do_parse(%{__struct__: module}, value) when not is_nil(value), do: module.new(value)
defp do_parse(_type, value), do: value
end