defmodule Stellar.TxBuild.TransactionEnvelope do @moduledoc """ `TransactionEnvelope` struct definition. """ alias Stellar.TxBuild.{Signature, Transaction, TransactionSignature} alias StellarBase.XDR.{ EnvelopeType, TransactionV1Envelope, TransactionEnvelope } @behaviour Stellar.TxBuild.XDR @type tx_base64 :: String.t() @type signatures :: list(Signature.t()) @type network_passphrase :: String.t() @type t :: %__MODULE__{tx: Transaction.t(), signatures: signatures()} defstruct [:tx, :signatures, :network_passphrase] @impl true def new(args, _opts \\ []) do tx = Keyword.get(args, :tx) signatures = Keyword.get(args, :signatures) network_passphrase = Keyword.get(args, :network_passphrase) %__MODULE__{tx: tx, signatures: signatures, network_passphrase: network_passphrase} end @impl true def to_xdr(%__MODULE__{tx: tx, signatures: signatures, network_passphrase: network_passphrase}) do envelope_type = EnvelopeType.new(:ENVELOPE_TYPE_TX) decorated_signatures = TransactionSignature.sign(tx, signatures, network_passphrase) tx |> Transaction.to_xdr() |> TransactionV1Envelope.new(decorated_signatures) |> TransactionEnvelope.new(envelope_type) end @spec add_signature( tx_base64 :: tx_base64(), signature :: Signature.t(), network_passphrase :: network_passphrase() ) :: TransactionEnvelope.t() def add_signature(tx_base64, %Signature{} = signature, network_passphrase) do with %TransactionEnvelope{envelope: envelope} = tx_envelope_xdr <- from_base64(tx_base64), signatures <- TransactionSignature.sign_xdr(tx_envelope_xdr, signature, network_passphrase) do %{tx_envelope_xdr | envelope: %{envelope | signatures: signatures}} end end @spec to_base64(tx_envelope_xdr :: TransactionEnvelope.t()) :: String.t() def to_base64(%TransactionEnvelope{} = tx_envelope_xdr) do tx_envelope_xdr |> TransactionEnvelope.encode_xdr!() |> Base.encode64() end @spec from_base64(tx_base64 :: tx_base64()) :: TransactionEnvelope.t() def from_base64(tx_base64) do tx_base64 |> Base.decode64!() |> TransactionEnvelope.decode_xdr!() |> elem(0) end end