defmodule Kadena.Types.MetaData do
@moduledoc """
`MetaData` struct definition.
"""
alias Kadena.Types.ChainID
@behaviour Kadena.Types.Spec
@type creation_time :: number()
@type ttl :: number()
@type gas_limit :: number()
@type gas_price :: number()
@type sender :: String.t()
@type chain_id :: ChainID.t()
@type chain_id_arg :: String.t()
@type values :: creation_time() | ttl() | gas_limit() | gas_price() | sender() | chain_id()
@type validation :: {:ok, values()} | {:error, Keyword.t()}
@type t :: %__MODULE__{
creation_time: creation_time(),
ttl: ttl(),
gas_limit: gas_limit(),
gas_price: gas_price(),
sender: sender(),
chain_id: chain_id()
}
defstruct [:creation_time, :ttl, :gas_limit, :gas_price, :sender, :chain_id]
@impl true
def new(args \\ [])
def new(args) when is_list(args) do
creation_time = Keyword.get(args, :creation_time, 0)
ttl = Keyword.get(args, :ttl, 0)
gas_limit = Keyword.get(args, :gas_limit, 0)
gas_price = Keyword.get(args, :gas_price, 0)
sender = Keyword.get(args, :sender, "")
chain_id = Keyword.get(args, :chain_id, "0")
with {:ok, creation_time} <- validate_creation_time(creation_time),
{:ok, ttl} <- validate_number(:ttl, ttl),
{:ok, gas_limit} <- validate_number(:gas_limit, gas_limit),
{:ok, gas_price} <- validate_number(:gas_price, gas_price),
{:ok, sender} <- validate_sender(sender),
{:ok, chain_id} <- validate_chain_id(chain_id) do
%__MODULE__{
creation_time: creation_time,
ttl: ttl,
gas_limit: gas_limit,
gas_price: gas_price,
sender: sender,
chain_id: chain_id
}
end
end
def new(args) when is_map(args) do
creation_time = Map.get(args, "creationTime", 0)
ttl = Map.get(args, "ttl", 0)
gas_limit = Map.get(args, "gasLimit", 0)
gas_price = Map.get(args, "gasPrice", 0)
sender = Map.get(args, "sender", "")
chain_id = Map.get(args, "chainId", "0")
with {:ok, creation_time} <- validate_creation_time(creation_time),
{:ok, ttl} <- validate_number(:ttl, ttl),
{:ok, gas_limit} <- validate_number(:gas_limit, gas_limit),
{:ok, gas_price} <- validate_number(:gas_price, gas_price),
{:ok, sender} <- validate_sender(sender),
{:ok, chain_id} <- validate_chain_id(chain_id) do
%__MODULE__{
creation_time: creation_time,
ttl: ttl,
gas_limit: gas_limit,
gas_price: gas_price,
sender: sender,
chain_id: chain_id
}
end
end
def new(_args), do: {:error, [args: :invalid]}
@spec validate_creation_time(creation_time :: creation_time()) :: validation()
defp validate_creation_time(creation_time) when is_number(creation_time),
do: {:ok, creation_time}
defp validate_creation_time(_creation_time), do: {:error, [creation_time: :invalid]}
@spec validate_number(field :: atom(), value :: number()) :: validation()
defp validate_number(_field, value) when is_number(value),
do: {:ok, value}
defp validate_number(field, _value), do: {:error, [{field, :invalid}]}
@spec validate_sender(sender :: sender()) :: validation()
defp validate_sender(sender) when is_binary(sender),
do: {:ok, sender}
defp validate_sender(_sender), do: {:error, [sender: :invalid]}
@spec validate_chain_id(chain_id :: chain_id_arg()) :: validation()
defp validate_chain_id(id) do
case ChainID.new(id) do
%ChainID{} = chain_id -> {:ok, chain_id}
_error -> {:error, [chain_id: :invalid]}
end
end
end