defmodule Stellar.TxBuild.ContractIDPreimage do @moduledoc """ `ContractIDPreimage` struct definition. """ alias StellarBase.XDR.ContractIDPreimage alias StellarBase.XDR.ContractIDPreimageType alias Stellar.TxBuild.{Asset, ContractIDPreimageFromAddress} @behaviour Stellar.TxBuild.XDR @type type :: :from_address | :from_asset @type value :: Asset.t() | ContractIDPreimageFromAddress.t() @type error :: {:error, atom()} @type validation :: {:ok, any()} | error() @type t :: %__MODULE__{ type: type(), value: value() } defstruct [:type, :value] @allowed_types ~w(from_address from_asset)a @impl true def new(value, opts \\ []) def new([{type, value}], _opts) when type in @allowed_types do with {:ok, _value} <- validate_contract_id_preimage({type, value}) do %__MODULE__{type: type, value: value} end end def new(_value, _opts), do: {:error, :invalid_contract_id_preimage} @impl true def to_xdr(%__MODULE__{type: :from_address, value: value}) do type = ContractIDPreimageType.new() value |> ContractIDPreimageFromAddress.to_xdr() |> ContractIDPreimage.new(type) end def to_xdr(%__MODULE__{type: :from_asset, value: value}) do type = ContractIDPreimageType.new(:CONTRACT_ID_PREIMAGE_FROM_ASSET) value |> Asset.to_xdr() |> ContractIDPreimage.new(type) end def to_xdr(_struct), do: {:error, :invalid_struct} @spec validate_contract_id_preimage({type :: atom(), value :: value()}) :: validation() defp validate_contract_id_preimage({:from_asset, %Asset{} = value}), do: {:ok, value} defp validate_contract_id_preimage({:from_address, %ContractIDPreimageFromAddress{} = value}), do: {:ok, value} defp validate_contract_id_preimage({type, _value}), do: {:error, :"invalid_#{type}"} end