|
|
@ -8,10 +8,6 @@ defmodule EthereumJSONRPC.Parity do |
|
|
|
alias EthereumJSONRPC.Parity.{FetchedBeneficiaries, Traces} |
|
|
|
alias EthereumJSONRPC.Parity.{FetchedBeneficiaries, Traces} |
|
|
|
alias EthereumJSONRPC.{Transaction, Transactions} |
|
|
|
alias EthereumJSONRPC.{Transaction, Transactions} |
|
|
|
|
|
|
|
|
|
|
|
alias Explorer.Chain |
|
|
|
|
|
|
|
alias Explorer.Chain.{Data, Wei} |
|
|
|
|
|
|
|
alias Explorer.Chain.InternalTransaction.{CallType, Type} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@behaviour EthereumJSONRPC.Variant |
|
|
|
@behaviour EthereumJSONRPC.Variant |
|
|
|
|
|
|
|
|
|
|
|
@impl EthereumJSONRPC.Variant |
|
|
|
@impl EthereumJSONRPC.Variant |
|
|
@ -53,6 +49,24 @@ defmodule EthereumJSONRPC.Parity do |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@impl EthereumJSONRPC.Variant |
|
|
|
|
|
|
|
def fetch_first_trace(transactions_params, json_rpc_named_arguments) when is_list(transactions_params) do |
|
|
|
|
|
|
|
id_to_params = id_to_params(transactions_params) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with {:ok, responses} <- |
|
|
|
|
|
|
|
id_to_params |
|
|
|
|
|
|
|
|> trace_replay_transaction_requests() |
|
|
|
|
|
|
|
|> json_rpc(json_rpc_named_arguments) do |
|
|
|
|
|
|
|
{:ok, [first_trace]} = trace_replay_transaction_responses_to_first_trace_params(responses, id_to_params) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
%{block_hash: block_hash} = |
|
|
|
|
|
|
|
transactions_params |
|
|
|
|
|
|
|
|> Enum.at(0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, [%{first_trace: first_trace, block_hash: block_hash, json_rpc_named_arguments: json_rpc_named_arguments}]} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
@doc """ |
|
|
|
@doc """ |
|
|
|
Fetches the pending transactions from the Parity node. |
|
|
|
Fetches the pending transactions from the Parity node. |
|
|
|
|
|
|
|
|
|
|
@ -172,138 +186,7 @@ defmodule EthereumJSONRPC.Parity do |
|
|
|
request(%{id: id, method: "trace_replayBlockTransactions", params: [integer_to_quantity(block_number), ["trace"]]}) |
|
|
|
request(%{id: id, method: "trace_replayBlockTransactions", params: [integer_to_quantity(block_number), ["trace"]]}) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
@doc """ |
|
|
|
def trace_replay_transaction_responses_to_first_trace_params(responses, id_to_params) |
|
|
|
Fetches the first trace from the Parity trace URL. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
@impl EthereumJSONRPC.Variant |
|
|
|
|
|
|
|
def fetch_first_trace(transactions_params, json_rpc_named_arguments) when is_list(transactions_params) do |
|
|
|
|
|
|
|
id_to_params = id_to_params(transactions_params) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with {:ok, responses} <- |
|
|
|
|
|
|
|
id_to_params |
|
|
|
|
|
|
|
|> trace_replay_transaction_requests() |
|
|
|
|
|
|
|
|> json_rpc(json_rpc_named_arguments) do |
|
|
|
|
|
|
|
{:ok, [first_trace]} = trace_replay_transaction_responses_to_first_trace_params(responses, id_to_params) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
%{block_hash: block_hash} = |
|
|
|
|
|
|
|
transactions_params |
|
|
|
|
|
|
|
|> Enum.at(0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, to_address_hash} = |
|
|
|
|
|
|
|
if Map.has_key?(first_trace, :to_address_hash) do |
|
|
|
|
|
|
|
Chain.string_to_address_hash(first_trace.to_address_hash) |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{:ok, nil} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, from_address_hash} = Chain.string_to_address_hash(first_trace.from_address_hash) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, created_contract_address_hash} = |
|
|
|
|
|
|
|
if Map.has_key?(first_trace, :created_contract_address_hash) do |
|
|
|
|
|
|
|
Chain.string_to_address_hash(first_trace.created_contract_address_hash) |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{:ok, nil} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, transaction_hash} = Chain.string_to_transaction_hash(first_trace.transaction_hash) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, call_type} = |
|
|
|
|
|
|
|
if Map.has_key?(first_trace, :call_type) do |
|
|
|
|
|
|
|
CallType.load(first_trace.call_type) |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{:ok, nil} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, type} = Type.load(first_trace.type) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, input} = |
|
|
|
|
|
|
|
if Map.has_key?(first_trace, :input) do |
|
|
|
|
|
|
|
Data.cast(first_trace.input) |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{:ok, nil} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, output} = |
|
|
|
|
|
|
|
if Map.has_key?(first_trace, :output) do |
|
|
|
|
|
|
|
Data.cast(first_trace.output) |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{:ok, nil} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, created_contract_code} = |
|
|
|
|
|
|
|
if Map.has_key?(first_trace, :created_contract_code) do |
|
|
|
|
|
|
|
Data.cast(first_trace.created_contract_code) |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{:ok, nil} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, init} = |
|
|
|
|
|
|
|
if Map.has_key?(first_trace, :init) do |
|
|
|
|
|
|
|
Data.cast(first_trace.init) |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{:ok, nil} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
block_index = |
|
|
|
|
|
|
|
get_block_index(%{ |
|
|
|
|
|
|
|
transaction_index: first_trace.transaction_index, |
|
|
|
|
|
|
|
transaction_hash: first_trace.transaction_hash, |
|
|
|
|
|
|
|
block_number: first_trace.block_number, |
|
|
|
|
|
|
|
json_rpc_named_arguments: json_rpc_named_arguments |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value = %Wei{value: Decimal.new(first_trace.value)} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
first_trace_formatted = |
|
|
|
|
|
|
|
first_trace |
|
|
|
|
|
|
|
|> Map.merge(%{ |
|
|
|
|
|
|
|
block_index: block_index, |
|
|
|
|
|
|
|
block_hash: block_hash, |
|
|
|
|
|
|
|
call_type: call_type, |
|
|
|
|
|
|
|
to_address_hash: to_address_hash, |
|
|
|
|
|
|
|
created_contract_address_hash: created_contract_address_hash, |
|
|
|
|
|
|
|
from_address_hash: from_address_hash, |
|
|
|
|
|
|
|
input: input, |
|
|
|
|
|
|
|
output: output, |
|
|
|
|
|
|
|
created_contract_code: created_contract_code, |
|
|
|
|
|
|
|
init: init, |
|
|
|
|
|
|
|
transaction_hash: transaction_hash, |
|
|
|
|
|
|
|
type: type, |
|
|
|
|
|
|
|
value: value |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{:ok, [first_trace_formatted]} |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defp get_block_index(%{ |
|
|
|
|
|
|
|
transaction_index: transaction_index, |
|
|
|
|
|
|
|
transaction_hash: transaction_hash, |
|
|
|
|
|
|
|
block_number: block_number, |
|
|
|
|
|
|
|
json_rpc_named_arguments: json_rpc_named_arguments |
|
|
|
|
|
|
|
}) do |
|
|
|
|
|
|
|
if transaction_index == 0 do |
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{:ok, traces} = fetch_block_internal_transactions([block_number], json_rpc_named_arguments) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sorted_traces = |
|
|
|
|
|
|
|
traces |
|
|
|
|
|
|
|
|> Enum.sort_by(&{&1.transaction_index, &1.index}) |
|
|
|
|
|
|
|
|> Enum.with_index() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{_, block_index} = |
|
|
|
|
|
|
|
sorted_traces |
|
|
|
|
|
|
|
|> Enum.find(fn {trace, _} -> |
|
|
|
|
|
|
|
trace.transaction_index == transaction_index && |
|
|
|
|
|
|
|
trace.transaction_hash == transaction_hash |
|
|
|
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
block_index |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defp trace_replay_transaction_responses_to_first_trace_params(responses, id_to_params) |
|
|
|
|
|
|
|
when is_list(responses) and is_map(id_to_params) do |
|
|
|
when is_list(responses) and is_map(id_to_params) do |
|
|
|
with {:ok, traces} <- trace_replay_transaction_responses_to_first_trace(responses, id_to_params) do |
|
|
|
with {:ok, traces} <- trace_replay_transaction_responses_to_first_trace(responses, id_to_params) do |
|
|
|
params = |
|
|
|
params = |
|
|
|