diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 08a14ff873..23719cd734 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -125,9 +125,29 @@ defmodule Explorer.Chain do """ @spec address_to_transaction_count(Address.t()) :: non_neg_integer() def address_to_transaction_count(%Address{hash: hash}) do - fetch_transactions() - |> where_address_fields_match(hash) - |> Repo.aggregate(:count, :hash) + {:ok, %{rows: [[result]]}} = + SQL.query( + Repo, + """ + SELECT COUNT(hash) from + ( + SELECT t0."hash" address + FROM "transactions" AS t0 + LEFT OUTER JOIN "internal_transactions" AS i1 ON (i1."transaction_hash" = t0."hash") AND (i1."type" = 'create') + WHERE (i1."created_contract_address_hash" = $1) + + UNION + + SELECT t0."hash" address + FROM "transactions" AS t0 + WHERE (t0."to_address_hash" = $1) + OR (t0."from_address_hash" = $1) + ) AS hash + """, + [hash.bytes] + ) + + result end @doc """ @@ -2652,10 +2672,6 @@ defmodule Explorer.Chain do %{inserted_at: now, updated_at: now} end - defp where_address_fields_match(query, address_hash) do - where_address_fields_match(query, address_hash, nil) - end - defp where_address_fields_match(query, address_hash, :to) do where(query, [t], t.to_address_hash == ^address_hash) end diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index abf28be3c9..c5966f1692 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -22,6 +22,27 @@ defmodule Explorer.ChainTest do assert Chain.address_to_transaction_count(address) == 2 end + + test "with transactions and contract creation address" do + %Transaction{from_address: address} = insert(:transaction) |> Repo.preload(:from_address) + insert(:transaction, to_address: address) + + insert( + :internal_transaction_create, + created_contract_address: address, + index: 0, + transaction: insert(:transaction) + ) + + assert Chain.address_to_transaction_count(address) == 3 + end + + test "doesn't double count addresses when to_address = from_address" do + %Transaction{from_address: address} = insert(:transaction) |> Repo.preload(:from_address) + insert(:transaction, to_address: address, from_address: address) + + assert Chain.address_to_transaction_count(address) == 2 + end end describe "address_to_transactions/2" do