defmodule Stellar.TxBuild.Ledger.Offer do
@moduledoc """
Ledger `Offer` struct definition.
"""
alias StellarBase.XDR.{Int64, Offer}
alias Stellar.TxBuild.AccountID
@behaviour Stellar.TxBuild.XDR
@type seller_id :: String.t()
@type offer_id :: non_neg_integer()
@type validation :: {:ok, any()} | {:error, atom()}
@type t :: %__MODULE__{seller_id: AccountID.t(), offer_id: offer_id()}
defstruct [:seller_id, :offer_id]
@max_offer_id 9_223_372_036_854_775_807
@impl true
def new(args, opts \\ [])
def new(args, _opts) do
seller_id = Keyword.get(args, :seller_id)
offer_id = Keyword.get(args, :offer_id)
with {:ok, seller_id} <- validate_seller(seller_id),
{:ok, offer_id} <- validate_offer_id(offer_id) do
%__MODULE__{seller_id: seller_id, offer_id: offer_id}
end
end
@impl true
def to_xdr(%__MODULE__{seller_id: seller_id, offer_id: offer_id}) do
offer = Int64.new(offer_id)
seller_id
|> AccountID.to_xdr()
|> Offer.new(offer)
end
@spec validate_seller(seller_id :: seller_id()) :: validation()
defp validate_seller(seller_id) do
case AccountID.new(seller_id) do
%AccountID{} = seller_id -> {:ok, seller_id}
_error -> {:error, :invalid_seller}
end
end
@spec validate_offer_id(offer_id :: offer_id()) :: validation()
defp validate_offer_id(offer_id) when is_integer(offer_id) and offer_id <= @max_offer_id,
do: {:ok, offer_id}
defp validate_offer_id(_offer_id), do: {:error, :invalid_offer_id}
end