|
|
|
@ -38,6 +38,7 @@ defmodule EthereumJSONRPC do |
|
|
|
|
RequestCoordinator, |
|
|
|
|
Subscription, |
|
|
|
|
Transport, |
|
|
|
|
Utility.CommonHelper, |
|
|
|
|
Utility.EndpointAvailabilityObserver, |
|
|
|
|
Utility.RangesHelper, |
|
|
|
|
Variant |
|
|
|
@ -186,38 +187,53 @@ defmodule EthereumJSONRPC do |
|
|
|
|
[%{required(:block_quantity) => quantity, required(:hash_data) => data()}], |
|
|
|
|
json_rpc_named_arguments |
|
|
|
|
) :: {:ok, FetchedBalances.t()} | {:error, reason :: term} |
|
|
|
|
def fetch_balances(params_list, json_rpc_named_arguments, chunk_size \\ nil) |
|
|
|
|
def fetch_balances(params_list, json_rpc_named_arguments, latest_block_number \\ 0, chunk_size \\ nil) |
|
|
|
|
when is_list(params_list) and is_list(json_rpc_named_arguments) do |
|
|
|
|
filtered_params = |
|
|
|
|
with true <- Application.get_env(:ethereum_jsonrpc, :disable_archive_balances?), |
|
|
|
|
{:ok, max_block_number} <- fetch_block_number_by_tag("latest", json_rpc_named_arguments) do |
|
|
|
|
window = Application.get_env(:ethereum_jsonrpc, :archive_balances_window) |
|
|
|
|
latest_block_number_params = |
|
|
|
|
case latest_block_number do |
|
|
|
|
0 -> fetch_block_number_by_tag("latest", json_rpc_named_arguments) |
|
|
|
|
number -> {:ok, number} |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
params_in_range = |
|
|
|
|
params_list |
|
|
|
|
|> Enum.filter(fn |
|
|
|
|
%{block_quantity: block_quantity} -> |
|
|
|
|
block_quantity |> quantity_to_integer() |> RangesHelper.traceable_block_number?() |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
trace_url_used? = !is_nil(json_rpc_named_arguments[:transport_options][:method_to_url][:eth_getBalance]) |
|
|
|
|
archive_disabled? = Application.get_env(:ethereum_jsonrpc, :disable_archive_balances?) |
|
|
|
|
|
|
|
|
|
{latest_balances_params, archive_balance_params} = |
|
|
|
|
with true <- not trace_url_used? or archive_disabled?, |
|
|
|
|
{:ok, max_block_number} <- latest_block_number_params do |
|
|
|
|
window = Application.get_env(:ethereum_jsonrpc, :archive_balances_window) |
|
|
|
|
|
|
|
|
|
Enum.split_with(params_in_range, fn |
|
|
|
|
%{block_quantity: "latest"} -> true |
|
|
|
|
%{block_quantity: block_quantity} -> quantity_to_integer(block_quantity) > max_block_number - window |
|
|
|
|
_ -> false |
|
|
|
|
end) |
|
|
|
|
else |
|
|
|
|
_ -> params_list |
|
|
|
|
_ -> {params_in_range, []} |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
filtered_params_in_range = |
|
|
|
|
filtered_params |
|
|
|
|
|> Enum.filter(fn |
|
|
|
|
%{block_quantity: block_quantity} -> |
|
|
|
|
block_quantity |> quantity_to_integer() |> RangesHelper.traceable_block_number?() |
|
|
|
|
end) |
|
|
|
|
latest_id_to_params = id_to_params(latest_balances_params) |
|
|
|
|
archive_id_to_params = id_to_params(archive_balance_params) |
|
|
|
|
|
|
|
|
|
id_to_params = id_to_params(filtered_params_in_range) |
|
|
|
|
|
|
|
|
|
with {:ok, responses} <- |
|
|
|
|
id_to_params |
|
|
|
|
|> FetchedBalances.requests() |
|
|
|
|
|> chunk_requests(chunk_size) |
|
|
|
|
|> json_rpc(json_rpc_named_arguments) do |
|
|
|
|
{:ok, FetchedBalances.from_responses(responses, id_to_params)} |
|
|
|
|
with {:ok, latest_responses} <- do_balances_request(latest_id_to_params, chunk_size, json_rpc_named_arguments), |
|
|
|
|
{:ok, archive_responses} <- |
|
|
|
|
maybe_request_archive_balances( |
|
|
|
|
archive_id_to_params, |
|
|
|
|
trace_url_used?, |
|
|
|
|
archive_disabled?, |
|
|
|
|
chunk_size, |
|
|
|
|
json_rpc_named_arguments |
|
|
|
|
) do |
|
|
|
|
latest_fetched_balances = FetchedBalances.from_responses(latest_responses, latest_id_to_params) |
|
|
|
|
archive_fetched_balances = FetchedBalances.from_responses(archive_responses, archive_id_to_params) |
|
|
|
|
{:ok, FetchedBalances.merge(latest_fetched_balances, archive_fetched_balances)} |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
@ -471,6 +487,31 @@ defmodule EthereumJSONRPC do |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp do_balances_request(id_to_params, _chunk_size, _args) when id_to_params == %{}, do: {:ok, []} |
|
|
|
|
|
|
|
|
|
defp do_balances_request(id_to_params, chunk_size, json_rpc_named_arguments) do |
|
|
|
|
id_to_params |
|
|
|
|
|> FetchedBalances.requests() |
|
|
|
|
|> chunk_requests(chunk_size) |
|
|
|
|
|> json_rpc(json_rpc_named_arguments) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp archive_json_rpc_named_arguments(json_rpc_named_arguments) do |
|
|
|
|
CommonHelper.put_in_keyword_nested( |
|
|
|
|
json_rpc_named_arguments, |
|
|
|
|
[:transport_options, :method_to_url, :eth_getBalance], |
|
|
|
|
System.get_env("ETHEREUM_JSONRPC_TRACE_URL") |
|
|
|
|
) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp maybe_request_archive_balances(id_to_params, trace_url_used?, disabled?, chunk_size, json_rpc_named_arguments) do |
|
|
|
|
if not trace_url_used? and not disabled? do |
|
|
|
|
do_balances_request(id_to_params, chunk_size, archive_json_rpc_named_arguments(json_rpc_named_arguments)) |
|
|
|
|
else |
|
|
|
|
{:ok, []} |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp maybe_replace_url(url, _replace_url, EthereumJSONRPC.HTTP), do: url |
|
|
|
|
defp maybe_replace_url(url, replace_url, _), do: EndpointAvailabilityObserver.maybe_replace_url(url, replace_url, :ws) |
|
|
|
|
|
|
|
|
|