From 4cac2d88541cf431d1c5c079956d1ce0b15c107b Mon Sep 17 00:00:00 2001 From: Bastien CHAMAGNE Date: Mon, 27 Mar 2023 15:29:47 +0200 Subject: [PATCH] LINT: split Archethic.parse_and_execute_contract_at into 2 functions --- lib/archethic.ex | 22 ++++---- lib/archethic/contracts/interpreter.ex | 19 +++++++ .../controllers/api/transaction_controller.ex | 53 +++++++++++-------- 3 files changed, 62 insertions(+), 32 deletions(-) diff --git a/lib/archethic.ex b/lib/archethic.ex index e5cd09c44f..e34a572f66 100644 --- a/lib/archethic.ex +++ b/lib/archethic.ex @@ -308,13 +308,21 @@ defmodule Archethic do end end + @doc """ + Parse the given transaction and return a contract + """ + @spec parse_contract(Transaction.t()) :: {:ok, Contract.t()} | {:error, String.t()} + defdelegate parse_contract(contract_tx), + to: Interpreter, + as: :parse_transaction + @doc """ Parse and execute the contract in the given transaction. We assume the contract is parse-able. """ - @spec parse_and_execute_contract_at( + @spec execute_contract( Contract.trigger_type(), - Transaction.t(), + Contract.t(), nil | Transaction.t() ) :: {:ok, nil | Transaction.t()} @@ -323,13 +331,9 @@ defmodule Archethic do | :invalid_transaction_constraints | :invalid_oracle_constraints | :invalid_inherit_constraints} - def parse_and_execute_contract_at( - trigger_type, - contract_tx, - maybe_tx - ) do - Interpreter.execute(trigger_type, Contract.from_transaction!(contract_tx), maybe_tx) - end + defdelegate execute_contract(trigger_type, contract, maybe_tx), + to: Interpreter, + as: :execute @doc """ Retrieve the number of transaction in a transaction chain from the closest nodes diff --git a/lib/archethic/contracts/interpreter.ex b/lib/archethic/contracts/interpreter.ex index cb11b44e5c..bc9e115dbc 100644 --- a/lib/archethic/contracts/interpreter.ex +++ b/lib/archethic/contracts/interpreter.ex @@ -52,6 +52,25 @@ defmodule Archethic.Contracts.Interpreter do result end + @doc """ + Parse a transaction and return a contract. + This return a filled contract structure or an human-readable error. + """ + @spec parse_transaction(Transaction.t()) :: {:ok, Contract.t()} | {:error, String.t()} + def parse_transaction(contract_tx = %Transaction{data: %TransactionData{code: code}}) do + case parse(code) do + {:ok, contract} -> + {:ok, + %Contract{ + contract + | constants: %Constants{contract: Constants.from_transaction(contract_tx)} + }} + + {:error, reason} -> + {:error, reason} + end + end + @doc """ Sanitize code takes care of converting atom to {:atom, bin()}. This way the user cannot create atoms at all. (which is mandatory to avoid atoms-table exhaustion) diff --git a/lib/archethic_web/controllers/api/transaction_controller.ex b/lib/archethic_web/controllers/api/transaction_controller.ex index 5482456f5d..b1f1b1018c 100644 --- a/lib/archethic_web/controllers/api/transaction_controller.ex +++ b/lib/archethic_web/controllers/api/transaction_controller.ex @@ -217,30 +217,37 @@ defmodule ArchethicWeb.API.TransactionController do end defp fetch_recipient_tx_and_simulate(recipient_address, tx) do - case Archethic.search_transaction(recipient_address) do - {:ok, contract_tx} -> - # this endpoint is only used for transaction triggers - case Archethic.parse_and_execute_contract_at(:transaction, contract_tx, tx) do - {:ok, _} -> - # contract may have returned a transaction or not, in both case it's valid - :ok - - {:error, :invalid_triggers_execution} -> - {:error, "Contract does not have a `actions triggered_by: transaction` block."} - - {:error, :invalid_transaction_constraints} -> - {:error, - "Contract refused incoming transaction. Check the `condition transaction` block."} - - {:error, :invalid_oracle_constraints} -> - {:error, "Contract refused incoming transaction. Check the `condition oracle` block."} - - {:error, :invalid_inherit_constraints} -> - {:error, - "Contract refused outcoming transaction. Check the `condition inherit` block."} - end + with {:ok, contract_tx} <- Archethic.search_transaction(recipient_address), + {:ok, contract} <- Archethic.parse_contract(contract_tx), + {:ok, _} <- Archethic.execute_contract(:transaction, contract, tx) do + :ok + else + # search_transaction errors + {:error, :transaction_not_exists} -> + {:error, "There is no transaction at recipient address."} + + {:error, :transaction_invalid} -> + {:error, "The transaction is marked as invalid."} + + {:error, :network_issue} -> + {:error, "Network issue, please try again later."} + + # execute_contract errors + {:error, :invalid_triggers_execution} -> + {:error, "Contract does not have a `actions triggered_by: transaction` block."} + + {:error, :invalid_transaction_constraints} -> + {:error, + "Contract refused incoming transaction. Check the `condition transaction` block."} + + {:error, :invalid_oracle_constraints} -> + {:error, "Contract refused incoming transaction. Check the `condition oracle` block."} + + {:error, :invalid_inherit_constraints} -> + {:error, "Contract refused outcoming transaction. Check the `condition inherit` block."} - {:error, reason} -> + # parse_contract errors + {:error, reason} when is_binary(reason) -> {:error, reason} end end