defmodule Xander.Transaction.Response do @moduledoc """ Parses the response from a transaction. Accepts CBOR encoded responses. """ require Logger @type error_reason :: :cannot_decode_non_binary_values | :cbor_function_clause_error | :cbor_match_error | :invalid_format | :invalid_input | :disconnected @type t :: {:ok, :accepted} | {:rejected, any()} | {:error, error_reason} @doc """ Parses the response from a transaction. Accepts CBOR encoded responses. ## Examples # Transaction accepted iex> binary = Xander.Util.plex_encode(CBOR.encode([1])) iex> Xander.Transaction.Response.parse_response(binary) {:ok, :accepted} # Transaction rejected with reason iex> tag = %CBOR.Tag{tag: :bytes, value: "invalid tx"} iex> binary = Xander.Util.plex_encode(CBOR.encode([2, tag])) iex> Xander.Transaction.Response.parse_response(binary) {:rejected, %CBOR.Tag{tag: :bytes, value: "invalid tx"}} # Disconnected from node iex> binary = Xander.Util.plex_encode(CBOR.encode([3])) iex> Xander.Transaction.Response.parse_response(binary) {:error, :disconnected} # Error handling invalid CBOR iex> Xander.Transaction.Response.parse_response(<<0, 1, 2, 3>>) {:error, :invalid_format} # Error handling nil input iex> Xander.Transaction.Response.parse_response(nil) {:error, :invalid_input} """ @spec parse_response(binary() | nil) :: t() def parse_response(cbor_response) do case Xander.Util.plex(cbor_response) do {:ok, %{payload: cbor_response_payload}} -> decode(cbor_response_payload) {:error, reason} -> {:error, reason} end end defp decode(cbor_response_payload) do case CBOR.decode(cbor_response_payload) do {:ok, [1], <<>>} -> {:ok, :accepted} {:ok, [2, failure_reason], <<>>} -> {:rejected, failure_reason} {:ok, [3], <<>>} -> {:error, :disconnected} {:error, error} -> {:error, error} end end end