defmodule Stellar.TxBuild.SetTrustlineFlags do @moduledoc """ Allows an issuing account to configure various authorization and trustline flags for all trustlines to an asset. """ import Stellar.TxBuild.Validations, only: [ validate_account_id: 1, validate_asset: 1, validate_optional_account: 1 ] alias Stellar.TxBuild.{AccountID, Asset, TrustlineFlags, OptionalAccount} alias StellarBase.XDR.{OperationBody, OperationType, Operations.SetTrustLineFlags} @behaviour Stellar.TxBuild.XDR @type error :: Keyword.t() | atom() @type validation :: {:ok, any()} | {:error, error()} @type t :: %__MODULE__{ trustor: AccountID.t(), asset: Asset.t(), clear_flags: TrustlineFlags.t(), set_flags: TrustlineFlags.t(), source_account: OptionalAccount.t() } defstruct [:trustor, :asset, :clear_flags, :set_flags, :source_account] @impl true def new(args, opts \\ []) def new(args, _opts) when is_list(args) do trustor = Keyword.get(args, :trustor) asset = Keyword.get(args, :asset) clear_flags = Keyword.get(args, :clear_flags) set_flags = Keyword.get(args, :set_flags) source_account = Keyword.get(args, :source_account) with {:ok, trustor} <- validate_account_id({:trustor, trustor}), {:ok, asset} <- validate_asset({:asset, asset}), {:ok, clear_flags} <- validate_trustline_flags({:clear_flags, clear_flags}), {:ok, set_flags} <- validate_trustline_flags({:set_flags, set_flags}), {:ok, source_account} <- validate_optional_account({:source_account, source_account}) do %__MODULE__{ trustor: trustor, asset: asset, clear_flags: clear_flags, set_flags: set_flags, source_account: source_account } end end def new(_args, _opts), do: {:error, :invalid_operation_attributes} @impl true def to_xdr(%__MODULE__{ trustor: trustor, asset: asset, clear_flags: clear_flags, set_flags: set_flags }) do op_type = OperationType.new(:SET_TRUST_LINE_FLAGS) trustor = AccountID.to_xdr(trustor) asset = Asset.to_xdr(asset) clear_flags = TrustlineFlags.to_xdr(clear_flags) set_flags = TrustlineFlags.to_xdr(set_flags) trustor |> SetTrustLineFlags.new( asset, clear_flags, set_flags ) |> OperationBody.new(op_type) end @spec validate_trustline_flags(tuple :: tuple()) :: validation() defp validate_trustline_flags({_field, nil}), do: {:ok, TrustlineFlags.new()} defp validate_trustline_flags({field, value}) do case TrustlineFlags.new(value) do %TrustlineFlags{} -> {:ok, TrustlineFlags.new(value)} {:error, reason} -> {:error, [{field, reason}]} end end end