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.
74 lines
2.1 KiB
74 lines
2.1 KiB
7 years ago
|
defmodule Explorer.ReceiptImporter do
|
||
7 years ago
|
@moduledoc "Imports a transaction receipt given a transaction hash."
|
||
|
|
||
|
import Ecto.Query
|
||
|
import Ethereumex.HttpClient, only: [eth_get_transaction_receipt: 1]
|
||
|
|
||
7 years ago
|
alias Explorer.Address
|
||
7 years ago
|
alias Explorer.Repo
|
||
|
alias Explorer.Transaction
|
||
7 years ago
|
alias Explorer.Receipt
|
||
7 years ago
|
|
||
|
def import(hash) do
|
||
7 years ago
|
transaction = hash |> find_transaction()
|
||
7 years ago
|
hash
|
||
|
|> download_receipt()
|
||
7 years ago
|
|> extract_receipt()
|
||
|
|> Map.put(:transaction_id, transaction.id)
|
||
7 years ago
|
|> save_receipt()
|
||
|
end
|
||
|
|
||
|
@dialyzer {:nowarn_function, download_receipt: 1}
|
||
|
defp download_receipt(hash) do
|
||
|
{:ok, receipt} = eth_get_transaction_receipt(hash)
|
||
7 years ago
|
receipt || %{}
|
||
7 years ago
|
end
|
||
|
|
||
7 years ago
|
defp find_transaction(hash) do
|
||
7 years ago
|
query = from transaction in Transaction,
|
||
|
left_join: receipt in assoc(transaction, :receipt),
|
||
7 years ago
|
where: fragment("lower(?)", transaction.hash) == ^hash,
|
||
7 years ago
|
where: is_nil(receipt.id),
|
||
|
limit: 1
|
||
7 years ago
|
Repo.one(query) || Transaction.null
|
||
7 years ago
|
end
|
||
|
|
||
|
defp save_receipt(receipt) do
|
||
|
unless is_nil(receipt.transaction_id) do
|
||
7 years ago
|
%Receipt{}
|
||
|
|> Receipt.changeset(receipt)
|
||
7 years ago
|
|> Repo.insert()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
defp extract_receipt(receipt) do
|
||
7 years ago
|
logs = receipt["logs"] || []
|
||
7 years ago
|
%{
|
||
|
index: receipt["transactionIndex"] |> decode_integer_field(),
|
||
|
cumulative_gas_used: receipt["cumulativeGasUsed"] |> decode_integer_field(),
|
||
|
gas_used: receipt["gasUsed"] |> decode_integer_field(),
|
||
|
status: receipt["status"] |> decode_integer_field(),
|
||
7 years ago
|
logs: logs |> Enum.map(&extract_log/1)
|
||
|
}
|
||
|
end
|
||
|
|
||
|
defp extract_log(log) do
|
||
|
address = Address.find_or_create_by_hash(log["address"])
|
||
|
%{
|
||
|
address_id: address.id,
|
||
|
index: log["logIndex"] |> decode_integer_field(),
|
||
|
data: log["data"],
|
||
|
type: log["type"],
|
||
|
first_topic: log["topics"] |> Enum.at(0),
|
||
|
second_topic: log["topics"] |> Enum.at(1),
|
||
|
third_topic: log["topics"] |> Enum.at(2),
|
||
|
fourth_topic: log["topics"] |> Enum.at(3),
|
||
7 years ago
|
}
|
||
|
end
|
||
|
|
||
7 years ago
|
defp decode_integer_field("0x" <> hex) when is_binary(hex) do
|
||
|
String.to_integer(hex, 16)
|
||
7 years ago
|
end
|
||
7 years ago
|
defp decode_integer_field(field), do: field
|
||
7 years ago
|
end
|