defmodule Kadena.Types.Command do @moduledoc """ `Command` struct definition. """ alias Kadena.Types.{PactTransactionHash, Signature} @behaviour Kadena.Types.Spec @type hash :: PactTransactionHash.t() @type sigs :: list(Signature.t()) @type cmd :: String.t() @type raw_cmd :: list() @type value :: hash() | sigs() | cmd() @type validation :: {:ok, value()} | {:error, Keyword.t()} @type t :: %__MODULE__{hash: hash(), sigs: sigs(), cmd: cmd()} defstruct [:hash, :sigs, :cmd] @impl true def new(args) when is_list(args) do hash = Keyword.get(args, :hash) sigs = Keyword.get(args, :sigs) cmd = Keyword.get(args, :cmd) with {:ok, hash} <- validate_hash(hash), {:ok, sigs} <- validate_sigs(sigs), {:ok, cmd} <- validate_cmd(cmd) do %__MODULE__{hash: hash, sigs: sigs, cmd: cmd} end end def new(_args), do: {:error, [command: :not_a_list]} @spec validate_hash(hash :: hash()) :: validation() defp validate_hash(%PactTransactionHash{} = hash), do: {:ok, hash} defp validate_hash(hash) do case PactTransactionHash.new(hash) do %PactTransactionHash{} = hash -> {:ok, hash} {:error, _reason} -> {:error, [hash: :invalid]} end end @spec validate_sigs(sigs :: sigs()) :: validation() defp validate_sigs([]), do: {:ok, []} defp validate_sigs([%Signature{} | _tail] = sigs), do: {:ok, sigs} defp validate_sigs(_hash), do: {:error, [sigs: :invalid]} @spec validate_cmd(cmd :: raw_cmd()) :: validation() defp validate_cmd(cmd) when is_binary(cmd), do: {:ok, cmd} defp validate_cmd(_cmd), do: {:error, [cmd: :not_a_string]} end