defmodule Stellar.TxBuild.InvokeHostFunction do
@moduledoc """
Performs the following operations:
- Invokes contract functions.
- Upload WASM of the new contracts.
- Deploys new contracts using the uploaded WASM or built-in implementations.
"""
import Stellar.TxBuild.Validations, only: [validate_optional_account: 1]
alias Stellar.TxBuild.{HostFunction, OptionalAccount}
alias StellarBase.XDR.Operations.InvokeHostFunction
alias StellarBase.XDR.{
HostFunctionList100,
OperationBody,
OperationType
}
@behaviour Stellar.TxBuild.XDR
@type functions() :: list(HostFunction.t())
@type validation :: {:ok, any()} | {:error, atom()}
@type t :: %__MODULE__{
functions: functions(),
source_account: OptionalAccount.t()
}
defstruct [:functions, :source_account]
@impl true
def new(functions, opts \\ [])
def new(args, _opts) when is_list(args) do
functions = Keyword.get(args, :functions)
source_account = Keyword.get(args, :source_account)
with {:ok, functions} <- validate_host_function_list(functions),
{:ok, source_account} <- validate_optional_account({:source_account, source_account}) do
%__MODULE__{
functions: functions,
source_account: source_account
}
end
end
def new(_args, _opts), do: {:error, :invalid_operation_attributes}
@impl true
def to_xdr(%__MODULE__{
functions: functions
}) do
op_type = OperationType.new(:INVOKE_HOST_FUNCTION)
functions
|> Enum.map(&HostFunction.to_xdr/1)
|> HostFunctionList100.new()
|> InvokeHostFunction.new()
|> OperationBody.new(op_type)
end
@spec validate_host_function_list(functions :: functions()) :: validation()
defp validate_host_function_list(functions) do
if Enum.all?(functions, &is_host_function?/1),
do: {:ok, functions},
else: {:error, :invalid_host_function_list}
end
@spec is_host_function?(function :: HostFunction.t()) :: boolean()
defp is_host_function?(%HostFunction{}), do: true
defp is_host_function?(_function), do: false
end