Skip to content

Commit

Permalink
LINT: split Archethic.parse_and_execute_contract_at into 2 functions
Browse files Browse the repository at this point in the history
  • Loading branch information
bchamagne committed Mar 27, 2023
1 parent 9dcc559 commit 4cac2d8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 32 deletions.
22 changes: 13 additions & 9 deletions lib/archethic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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()}
Expand All @@ -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
Expand Down
19 changes: 19 additions & 0 deletions lib/archethic/contracts/interpreter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
53 changes: 30 additions & 23 deletions lib/archethic_web/controllers/api/transaction_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 4cac2d8

Please sign in to comment.