defmodule Stellar.TxBuild.LedgerKey do @moduledoc """ `LedgerKey` struct definition. """ alias StellarBase.XDR.{LedgerEntryType, LedgerKey} alias Stellar.TxBuild.Ledger.{Account, ClaimableBalance, Data, LiquidityPool, Offer, Trustline} @behaviour Stellar.TxBuild.XDR @type type :: :account | :trustline | :offer | :data | :claimable_balance | :liquidity_pool @type entry :: Account.t() | ClaimableBalance.t() | Data.t() | LiquidityPool.t() | Offer.t() | Trustline.t() @type t :: %__MODULE__{type: type(), entry: entry()} defstruct [:type, :entry] @impl true def new(args, opts \\ []) def new({:account, [account_id: account_id]}, _opts) do case Account.new(account_id) do %Account{} = account -> %__MODULE__{type: :account, entry: account} _error -> {:error, :invalid_account} end end def new({:claimable_balance, [claimable_balance_id: claimable_balance_id]}, _opts) do case ClaimableBalance.new(claimable_balance_id) do %ClaimableBalance{} = claimable_balance -> %__MODULE__{type: :claimable_balance, entry: claimable_balance} _error -> {:error, :invalid_claimable_balance} end end def new({:liquidity_pool, [liquidity_pool_id: liquidity_pool_id]}, _opts) do case LiquidityPool.new(liquidity_pool_id) do %LiquidityPool{} = liquidity_pool -> %__MODULE__{type: :liquidity_pool, entry: liquidity_pool} _error -> {:error, :invalid_liquidity_pool} end end def new({:trustline, trustline}, _opts) do case Trustline.new(trustline) do %Trustline{} = trustline -> %__MODULE__{type: :trustline, entry: trustline} _error -> {:error, :invalid_trustline} end end def new({:offer, offer}, _opts) do case Offer.new(offer) do %Offer{} = offer -> %__MODULE__{type: :offer, entry: offer} _error -> {:error, :invalid_offer} end end def new({:data, data}, _opts) do case Data.new(data) do %Data{} = data -> %__MODULE__{type: :data, entry: data} _error -> {:error, :invalid_data} end end def new(_args, _opts), do: {:error, :invalid_ledger_key} @impl true def to_xdr(%__MODULE__{type: type, entry: %{__struct__: entry_type} = entry}) do ledger_entry_type = ledger_entry_type(type) entry |> entry_type.to_xdr() |> LedgerKey.new(ledger_entry_type) end @spec ledger_entry_type(type :: type()) :: LedgerEntryType.t() defp ledger_entry_type(:account), do: LedgerEntryType.new(:ACCOUNT) defp ledger_entry_type(:trustline), do: LedgerEntryType.new(:TRUSTLINE) defp ledger_entry_type(:offer), do: LedgerEntryType.new(:OFFER) defp ledger_entry_type(:data), do: LedgerEntryType.new(:DATA) defp ledger_entry_type(:claimable_balance), do: LedgerEntryType.new(:CLAIMABLE_BALANCE) defp ledger_entry_type(:liquidity_pool), do: LedgerEntryType.new(:LIQUIDITY_POOL) end