defmodule Stellar.TxBuild.Claimants do
end
# ClaimPredicate
# ----
# Stellar.TxBuild.Claimant.new(destination: "ABC", predicate: :unconditional)
# Stellar.TxBuild.Claimant.new(destination: "ABC", predicate: conditional: [time: {:relative, 123}])
#
defmodule Stellar.TxBuild.UnconditionalPredicate do
@moduledoc """
"""
@behaviour Stellar.TxBuild.XDR
end
defmodule Stellar.TxBuild.ConditionalPredicate do
@moduledoc """
"""
@behaviour Stellar.TxBuild.XDR
end
defmodule Stellar.TxBuild.Predicate do
@moduledoc """
`Predicate` struct definition.
"""
@type predicate :: :conditional | :unconditional
@type type :: :time | :and | :or | :not
@type t :: %__MODULE__{predicate: predicate(), type: type(), value: any()}
defstruct [:predicate, :type, :value]
def new(:unconditional), do: %__MODULE__{type: :unconditional}
def new(conditional: predicate) do
with {:ok, {type, value}} <- validate_predicate(predicate) do
%__MODULE__{type: :time, value: value}
end
end
def new(_predicate), do: {:error, :invalid_predicate}
defp validate_predicate(time: {type, value}) when type in ~w(relative absolute)a and is_integer(value) do
{:ok, {:time, {type, value}}}
end
defp validate_predicate(and: {cond1, cond2}) do
with {:ok, predicate1} <- new(cond1),
{:ok, predicate2} <- new(cond2) do
{:ok, {:and, {predicate1, predicate2}}}
end
end
defp validate_predicate(or: {cond1, cond2}) do
with {:ok, predicate1} <- new(cond1),
{:ok, predicate2} <- new(cond2) do
{:ok, {:or, {predicate1, predicate2}}}
end
end
defp validate_predicate(not: conditional) do
{:ok, {:and, new(conditional)}}
end
end
defmodule Stellar.TxBuild.Claimant do
@moduledoc """
"""
@behaviour Stellar.TxBuild.XDR
alias Stellar.TxBuild.{AccountID, Predicate}
@type account_id :: String.t()
@type validation :: {:ok, any()} | {:error, atom()}
@type t :: %__MODULE__{destination: account_id(), predicate: Predicate.t()}
defstruct [:destination, :predicate]
def new(args, opts \\ [])
def new(args, _opts) do
destination = Keyword.get(args, :destination)
predicate = Keyword.get(args, :predicate)
with {:ok, destination} <- validate_destionation(destination),
{:ok, predicate} <- validate_predicate(predicate) do
%__MODULE__{destination: destination, predicate: predicate}
end
end
@spec validate_destionation(account_id :: account_id()) :: validation()
defp validate_destionation(account_id) do
case AccountID.new(account_id) do
%AccountID{} = account_id -> {:ok, account_id}
_error -> {:error, :invalid_destination}
end
end
@spec validate_predicate(predicate :: any()) :: validation()
defp validate_predicate(predicate) do
case Predicate.new(predicate) do
%Predicate{} = predicate -> {:ok, predicate}
_error -> {:error, :invalid_predicate}
end
end
# defp validate_predicate({:unconditional, _predicate}), do: validate_predicate(:unconditional)
# defp validate_predicate(:unconditional), do: :unconditional
# defp validate_predicate(_predicate), do: {:error, :invalid_predicate}
end