Blockchain explorer for Ethereum based network and a tool for inspecting and analyzing EVM based blockchains.
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.
blockscout/lib/explorer/chain.ex

93 lines
2.6 KiB

defmodule Explorer.Chain do
@moduledoc """
Represents statistics about the chain.
"""
import Ecto.Query
alias Explorer.Block
alias Explorer.Repo
alias Ecto.Adapters.SQL
defstruct [
number: 0, timestamp: nil, average_time: nil, transaction_count: 0,
skipped_blocks: 0, lag: nil, block_velocity: 0,
transaction_velocity: 0
]
@average_time_query """
SELECT coalesce(avg(difference), interval '0 seconds')
FROM (
SELECT timestamp - lag(timestamp) over (order by timestamp) as difference
FROM blocks
ORDER BY number DESC
LIMIT 100
) t
"""
@transaction_count_query """
SELECT count(transactions.id)
FROM transactions
JOIN block_transactions ON block_transactions.transaction_id = transactions.id
JOIN blocks ON blocks.id = block_transactions.block_id
WHERE blocks.timestamp > NOW() - interval '1 day'
"""
@skipped_blocks_query """
SELECT COUNT(missing_number)
FROM generate_series(0, $1, 1) AS missing_number
WHERE missing_number NOT IN (SELECT blocks.number FROM blocks)
"""
@lag_query """
SELECT coalesce(avg(lag), interval '0 seconds')
FROM (
SELECT inserted_at - timestamp AS lag
FROM blocks
WHERE blocks.inserted_at > NOW() - interval '1 hour'
AND blocks.timestamp > NOW() - interval '1 hour'
) t
"""
@block_velocity_query """
SELECT count(blocks.id)
FROM blocks
WHERE blocks.inserted_at > NOW() - interval '1 minute'
"""
@transaction_velocity_query """
SELECT count(transactions.id)
FROM transactions
WHERE transactions.inserted_at > NOW() - interval '1 minute'
"""
def fetch do
last_block = Block |> Block.latest() |> limit(1) |> Repo.one()
latest_block = last_block || Block.null
%Explorer.Chain{
number: latest_block.number,
timestamp: latest_block.timestamp,
average_time: query_duration(@average_time_query),
transaction_count: query_value(@transaction_count_query),
skipped_blocks: query_value(@skipped_blocks_query, [latest_block.number]),
lag: query_duration(@lag_query),
block_velocity: query_value(@block_velocity_query),
transaction_velocity: query_value(@transaction_velocity_query)
}
end
defp query_value(query, args \\ []) do
results = SQL.query!(Repo, query, args)
results.rows |> List.first() |> List.first()
end
defp query_duration(query) do
results = SQL.query!(Repo, query, [])
{:ok, value} = results.rows
|> List.first()
|> List.first()
|> Timex.Ecto.Time.load()
value
end
end