defmodule Stellar.TxBuild.Ledger.ContractData do
@moduledoc """
`ContractData` struct definition.
"""
import Stellar.TxBuild.Validations,
only: [validate_address: 1]
alias Stellar.TxBuild.{SCAddress, SCVal}
alias StellarBase.XDR.{ContractDataDurability, LedgerKeyContractData}
@behaviour Stellar.TxBuild.XDR
@type error :: {:error, atom()}
@type validation :: {:ok, any()} | error()
@type contract :: SCAddress.t()
@type key :: SCVal.t()
@type durability :: :temporary | :persistent
@type t :: %__MODULE__{
contract: contract(),
key: key(),
durability: durability()
}
defstruct [:contract, :key, :durability]
@allowed_durabilities ~w(temporary persistent)a
@impl true
def new(args, opts \\ [])
def new(
[
{:contract, contract},
{:key, key},
{:durability, durability}
],
_opts
)
when durability in @allowed_durabilities do
with {:ok, contract} <- validate_address(contract),
{:ok, key} <- validate_sc_val_ledger_instance(key) do
%__MODULE__{
contract: contract,
key: key,
durability: durability
}
end
end
def new(_value, _opts), do: {:error, :invalid_ledger_key_args}
@impl true
def to_xdr(%__MODULE__{
contract: contract,
key: key,
durability: durability
}) do
key = SCVal.to_xdr(key)
durability = durability_to_xdr(durability)
contract
|> SCAddress.to_xdr()
|> LedgerKeyContractData.new(key, durability)
end
def to_xdr(_struct), do: {:error, :invalid_struct}
@spec validate_sc_val_ledger_instance(key :: key()) :: validation()
defp validate_sc_val_ledger_instance(%SCVal{} = key), do: {:ok, key}
defp validate_sc_val_ledger_instance(_key), do: {:error, :invalid_key}
@spec durability_to_xdr(atom()) :: ContractDataDurability.t()
defp durability_to_xdr(:temporary), do: ContractDataDurability.new(:TEMPORARY)
defp durability_to_xdr(:persistent), do: ContractDataDurability.new(:PERSISTENT)
end