@ -5,11 +5,11 @@ defmodule Explorer.Chain.Transaction.History.Historian do
require Logger
require Logger
use Explorer.History.Historian
use Explorer.History.Historian
alias Explorer . { Chain , Repo }
alias Explorer.Chain . { Block , Transaction }
alias Explorer.Chain . { Block , Transaction }
alias Explorer.Chain.Events.Publisher
alias Explorer.Chain.Events.Publisher
alias Explorer.Chain.Transaction.History.TransactionStats
alias Explorer.Chain.Transaction.History.TransactionStats
alias Explorer.History.Process , as : HistoryProcess
alias Explorer.History.Process , as : HistoryProcess
alias Explorer.Repo
import Ecto.Query , only : [ from : 2 , subquery : 1 ]
import Ecto.Query , only : [ from : 2 , subquery : 1 ]
@ -19,8 +19,10 @@ defmodule Explorer.Chain.Transaction.History.Historian do
def compile_records ( num_days , records \\ [ ] ) do
def compile_records ( num_days , records \\ [ ] ) do
Logger . info ( " tx/per day chart: collect records for txs per day stats " )
Logger . info ( " tx/per day chart: collect records for txs per day stats " )
if num_days == 0 do
if num_days == 1 do
Logger . info ( " tx/per day chart: records collected #{ inspect ( records ) } " )
Logger . info ( " tx/per day chart: records collected #{ inspect ( records ) } " )
records = [ %{ date : date_today ( ) , number_of_transactions : 0 , gas_used : 0 , total_fee : 0 } | records ]
# base case
# base case
{ :ok , records }
{ :ok , records }
else
else
@ -33,60 +35,92 @@ defmodule Explorer.Chain.Transaction.History.Historian do
Logger . info ( " tx/per day chart: latest date #{ DateTime . to_string ( latest ) } " )
Logger . info ( " tx/per day chart: latest date #{ DateTime . to_string ( latest ) } " )
min_max_block_query =
with { :ok , min_block } <- Chain . timestamp_to_block_number ( earliest , :after ) ,
from ( block in Block ,
{ :ok , max_block } <- Chain . timestamp_to_block_number ( latest , :after ) do
where : block . timestamp >= ^ earliest and block . timestamp <= ^ latest ,
record =
select : { min ( block . number ) , max ( block . number ) }
min_block
)
|> compile_records_in_range ( max_block )
|> Map . put ( :date , day_to_fetch )
{ min_block , max_block } = Repo . one ( min_max_block_query , timeout : :infinity )
Logger . info ( " tx/per day chart: min/max block numbers [ #{ min_block } , #{ max_block } ] " )
if min_block && max_block do
all_transactions_query =
from (
transaction in Transaction ,
where : transaction . block_number >= ^ min_block and transaction . block_number <= ^ max_block
)
query =
from ( transaction in subquery ( all_transactions_query ) ,
join : block in Block ,
on : transaction . block_hash == block . hash ,
where : block . consensus == true ,
select : transaction
)
num_transactions = Repo . aggregate ( query , :count , :hash , timeout : :infinity )
Logger . info ( " tx/per day chart: num of transactions #{ num_transactions } " )
gas_used = Repo . aggregate ( query , :sum , :gas_used , timeout : :infinity )
Logger . info ( " tx/per day chart: total gas used #{ gas_used } " )
total_fee_query =
from ( transaction in subquery ( all_transactions_query ) ,
join : block in Block ,
on : transaction . block_hash == block . hash ,
where : block . consensus == true ,
select : fragment ( " SUM(? * ?) " , transaction . gas_price , transaction . gas_used )
)
total_fee = Repo . one ( total_fee_query , timeout : :infinity )
Logger . info ( " tx/per day chart: total fee #{ total_fee } " )
records = [
records = [
%{ date : day_to_fetch , number_of_transactions : num_transactions , gas_used : gas_used , total_fee : total_fee }
record
| records
| records
]
]
compile_records ( num_days - 1 , records )
compile_records ( num_days - 1 , records )
else
else
records = [ %{ date : day_to_fetch , number_of_transactions : 0 , gas_used : 0 , total_fee : 0 } | records ]
_ ->
compile_records ( num_days - 1 , records )
min_max_block_query =
from ( block in Block ,
where : block . timestamp >= ^ earliest and block . timestamp <= ^ latest ,
select : { min ( block . number ) , max ( block . number ) }
)
{ min_block , max_block } = Repo . one ( min_max_block_query , timeout : :infinity )
if min_block && max_block do
record =
min_block
|> compile_records_in_range ( max_block )
|> Map . put ( :date , day_to_fetch )
records = [
record
| records
]
compile_records ( num_days - 1 , records )
else
records = [ %{ date : day_to_fetch , number_of_transactions : 0 , gas_used : 0 , total_fee : 0 } | records ]
compile_records ( num_days - 1 , records )
end
end
end
end
end
end
end
defp compile_records_in_range ( min_block , max_block ) do
Logger . info ( " tx/per day chart: min/max block numbers [ #{ min_block } , #{ max_block } ] " )
all_transactions_query =
from (
transaction in Transaction ,
where : transaction . block_number >= ^ min_block and transaction . block_number <= ^ max_block
)
all_blocks_query =
from (
block in Block ,
where : block . consensus == true ,
where : block . number >= ^ min_block and block . number <= ^ max_block ,
select : block . number
)
query =
from ( transaction in subquery ( all_transactions_query ) ,
join : block in subquery ( all_blocks_query ) ,
on : transaction . block_number == block . number ,
select : transaction
)
num_transactions = Repo . aggregate ( query , :count , :hash , timeout : :infinity )
Logger . info ( " tx/per day chart: num of transactions #{ num_transactions } " )
gas_used = Repo . aggregate ( query , :sum , :gas_used , timeout : :infinity )
Logger . info ( " tx/per day chart: total gas used #{ gas_used } " )
total_fee_query =
from ( transaction in subquery ( all_transactions_query ) ,
join : block in Block ,
on : transaction . block_hash == block . hash ,
where : block . consensus == true ,
select : fragment ( " SUM(? * ?) " , transaction . gas_price , transaction . gas_used )
)
total_fee = Repo . one ( total_fee_query , timeout : :infinity )
Logger . info ( " tx/per day chart: total fee #{ total_fee } " )
%{ number_of_transactions : num_transactions , gas_used : gas_used , total_fee : total_fee }
end
@impl Historian
@impl Historian
def save_records ( records ) do
def save_records ( records ) do
Logger . info ( " tx/per day chart: save records " )
Logger . info ( " tx/per day chart: save records " )