From bbd20a85c9f95ebb8656e96ff8df78f888966cf2 Mon Sep 17 00:00:00 2001 From: nikitosing <32202610+nikitosing@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:56:56 +0300 Subject: [PATCH] feat: Add metadata info to tx interpreter request (#10823) * feat: Add metadata info to tx interpreter request * Fix credo --- .../transaction_interpretation.ex | 111 ++++++++++++------ 1 file changed, 73 insertions(+), 38 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/microservice_interfaces/transaction_interpretation.ex b/apps/block_scout_web/lib/block_scout_web/microservice_interfaces/transaction_interpretation.ex index 94a0eb27e6..31a04b6d86 100644 --- a/apps/block_scout_web/lib/block_scout_web/microservice_interfaces/transaction_interpretation.ex +++ b/apps/block_scout_web/lib/block_scout_web/microservice_interfaces/transaction_interpretation.ex @@ -9,6 +9,7 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do alias Explorer.Chain.{Data, InternalTransaction, Log, TokenTransfer, Transaction} alias HTTPoison.Response + import Explorer.MicroserviceInterfaces.Metadata, only: [maybe_preload_metadata: 1] import Explorer.Utility.Microservice, only: [base_url: 2, check_enabled: 2] require Logger @@ -106,13 +107,38 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do defp prepare_request_body(transaction) do transaction = Chain.select_repo(@api_true).preload(transaction, [ - :transaction_actions, :block, to_address: [:scam_badge, :names, :smart_contract], from_address: [:names, :smart_contract], created_contract_address: [:scam_badge, :names, :token, :smart_contract] ]) + token_transfers = transaction |> fetch_token_transfers() |> Enum.reverse() + internal_transactions = transaction |> fetch_internal_transactions() |> Enum.reverse() + logs = transaction |> fetch_logs() |> Enum.reverse() + + [transaction_with_meta | other_elements] = + ([transaction | token_transfers] ++ internal_transactions ++ logs) + |> maybe_preload_metadata() + + %{ + logs: logs_with_meta, + token_transfers: token_transfers_with_meta, + internal_transactions: internal_transactions_with_meta + } = + Enum.reduce(other_elements, %{logs: [], token_transfers: [], internal_transactions: []}, fn element, acc -> + case element do + %InternalTransaction{} -> + Map.put(acc, :internal_transactions, [element | acc.internal_transactions]) + + %TokenTransfer{} -> + Map.put(acc, :token_transfers, [element | acc.token_transfers]) + + %Log{} -> + Map.put(acc, :logs, [element | acc.logs]) + end + end) + skip_sig_provider? = false {decoded_input, _abi_acc, _methods_acc} = Transaction.decoded_input_data(transaction, skip_sig_provider?, @api_true) @@ -120,31 +146,31 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do %{ data: %{ - to: Helper.address_with_info(nil, transaction.to_address, transaction.to_address_hash, true), + to: + Helper.address_with_info(nil, transaction_with_meta.to_address, transaction_with_meta.to_address_hash, true), from: Helper.address_with_info( nil, - transaction.from_address, - transaction.from_address_hash, + transaction_with_meta.from_address, + transaction_with_meta.from_address_hash, true ), - hash: transaction.hash, - type: transaction.type, - value: transaction.value, - method: Transaction.method_name(transaction, Transaction.format_decoded_input(decoded_input)), - status: transaction.status, - actions: TransactionView.transaction_actions(transaction.transaction_actions), - tx_types: TransactionView.tx_types(transaction), - raw_input: transaction.input, + hash: transaction_with_meta.hash, + type: transaction_with_meta.type, + value: transaction_with_meta.value, + method: Transaction.method_name(transaction_with_meta, Transaction.format_decoded_input(decoded_input)), + status: transaction_with_meta.status, + tx_types: TransactionView.tx_types(transaction_with_meta), + raw_input: transaction_with_meta.input, decoded_input: decoded_input_data, - token_transfers: prepare_token_transfers(transaction, decoded_input), - internal_transactions: prepare_internal_transactions(transaction) + token_transfers: prepare_token_transfers(token_transfers_with_meta, decoded_input), + internal_transactions: prepare_internal_transactions(internal_transactions_with_meta, transaction_with_meta) }, - logs_data: %{items: prepare_logs(transaction)} + logs_data: %{items: prepare_logs(logs_with_meta, transaction_with_meta)} } end - defp prepare_token_transfers(transaction, decoded_input) do + defp fetch_token_transfers(transaction) do full_options = [ necessity_by_association: %{ @@ -158,10 +184,14 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do |> Chain.transaction_to_token_transfers(full_options) |> Chain.flat_1155_batch_token_transfers() |> Enum.take(@items_limit) + end + + defp prepare_token_transfers(token_transfers, decoded_input) do + token_transfers |> Enum.map(&TransactionView.prepare_token_transfer(&1, nil, decoded_input)) end - defp prepare_internal_transactions(transaction) do + defp fetch_internal_transactions(transaction) do full_options = @internal_transaction_necessity_by_association |> Keyword.merge(@api_true) @@ -169,9 +199,35 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do transaction.hash |> InternalTransaction.transaction_to_internal_transactions(full_options) |> Enum.take(@items_limit) + end + + defp prepare_internal_transactions(internal_transactions, transaction) do + internal_transactions |> Enum.map(&TransactionView.prepare_internal_transaction(&1, transaction.block)) end + defp fetch_logs(transaction) do + full_options = + [ + necessity_by_association: %{ + [address: [:names, :smart_contract, :proxy_implementations]] => :optional + } + ] + |> Keyword.merge(@api_true) + + transaction.hash + |> Chain.transaction_to_logs(full_options) + |> Enum.take(@items_limit) + end + + defp prepare_logs(logs, transaction) do + decoded_logs = TransactionView.decode_logs(logs, false) + + logs + |> Enum.zip(decoded_logs) + |> Enum.map(fn {log, decoded_log} -> TransactionView.prepare_log(log, transaction.hash, decoded_log, true) end) + end + defp user_op_to_logs_and_token_transfers(user_op, decoded_input) do log_options = [ @@ -213,27 +269,6 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do {prepared_logs, prepared_token_transfers} end - defp prepare_logs(transaction) do - full_options = - [ - necessity_by_association: %{ - [address: [:names, :smart_contract, :proxy_implementations]] => :optional - } - ] - |> Keyword.merge(@api_true) - - logs = - transaction.hash - |> Chain.transaction_to_logs(full_options) - |> Enum.take(@items_limit) - - decoded_logs = TransactionView.decode_logs(logs, false) - - logs - |> Enum.zip(decoded_logs) - |> Enum.map(fn {log, decoded_log} -> TransactionView.prepare_log(log, transaction.hash, decoded_log, true) end) - end - defp preload_template_variables({:ok, %{"success" => true, "data" => %{"summaries" => summaries} = data}}) do summaries_updated = Enum.map(summaries, fn %{"summary_template_variables" => summary_template_variables} = summary ->