Blockchain explorer for Ethereum based network and a tool for inspecting and analyzing EVM based blockchains.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
blockscout/lib/explorer/importers/internal_transaction_import...

68 lines
1.9 KiB

defmodule Explorer.InternalTransactionImporter do
@moduledoc "Imports a transaction's internal transactions given its hash."
import Ecto.Query
alias Explorer.EthereumexExtensions
alias Explorer.InternalTransaction
alias Explorer.Repo
alias Explorer.Transaction
def import(hash) do
transaction = find_transaction(hash)
hash
|> download_trace
|> extract_attrs
|> persist_internal_transactions(transaction)
end
defp download_trace(hash) do
EthereumexExtensions.trace_transaction(hash)
end
defp find_transaction(hash) do
query = from t in Transaction,
where: fragment("lower(?)", t.hash) == ^String.downcase(hash),
limit: 1
Repo.one!(query)
end
defp extract_attrs(attrs) do
trace = attrs["trace"]
trace |> Enum.with_index() |> Enum.map(&extract_trace/1)
end
def extract_trace({trace, index}) do
%{
index: index,
call_type: trace["action"]["callType"] || trace["type"],
to_address_id: address_id(trace["action"]["to"] || trace["result"]["address"]),
from_address_id: address_id(trace["action"]["from"]),
trace_address: trace["traceAddress"],
value: trace["action"]["value"] |> decode_integer_field,
gas: trace["action"]["gas"] |> decode_integer_field,
gas_used: trace["result"]["gasUsed"] |> decode_integer_field,
input: trace["action"]["input"],
output: trace["result"]["output"],
}
end
defp persist_internal_transactions(traces, transaction) do
Enum.map(traces, fn(trace) ->
trace = Map.merge(trace, %{transaction_id: transaction.id})
%InternalTransaction{}
|> InternalTransaction.changeset(trace)
|> Repo.insert()
end)
end
defp decode_integer_field(hex) do
{"0x", base_16} = String.split_at(hex, 2)
String.to_integer(base_16, 16)
end
defp address_id(hash) do
Explorer.Address.find_or_create_by_hash(hash).id
end
end