feat: store average block time in a genserver

pull/1292/head
zachdaniel 6 years ago committed by Luke Imhoff
parent e88fb5c999
commit b02383a80b
  1. 3
      apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
  2. 3
      apps/block_scout_web/lib/block_scout_web/notifier.ex
  3. 7
      apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
  4. 24
      apps/block_scout_web/priv/gettext/default.pot
  5. 24
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  6. 2
      apps/explorer/config/config.exs
  7. 2
      apps/explorer/config/test.exs
  8. 1
      apps/explorer/lib/explorer/application.ex
  9. 26
      apps/explorer/lib/explorer/chain.ex
  10. 106
      apps/explorer/lib/explorer/counters/average_block_time.ex
  11. 2
      apps/explorer/mix.exs
  12. 14
      apps/explorer/test/explorer/chain_test.exs
  13. 64
      apps/explorer/test/explorer/counters/average_block_time_test.exs

@ -4,6 +4,7 @@ defmodule BlockScoutWeb.ChainController do
alias BlockScoutWeb.ChainView alias BlockScoutWeb.ChainView
alias Explorer.{Chain, PagingOptions, Repo} alias Explorer.{Chain, PagingOptions, Repo}
alias Explorer.Chain.{Address, Block, Transaction} alias Explorer.Chain.{Address, Block, Transaction}
alias Explorer.Counters.AverageBlockTime
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
alias Explorer.Market alias Explorer.Market
alias Phoenix.View alias Phoenix.View
@ -17,7 +18,7 @@ defmodule BlockScoutWeb.ChainController do
conn, conn,
"show.html", "show.html",
address_count: Chain.count_addresses_with_balance_from_cache(), address_count: Chain.count_addresses_with_balance_from_cache(),
average_block_time: Chain.average_block_time(), average_block_time: AverageBlockTime.average_block_time(),
exchange_rate: exchange_rate, exchange_rate: exchange_rate,
chart_data_path: market_history_chart_path(conn, :show), chart_data_path: market_history_chart_path(conn, :show),
transaction_estimated_count: transaction_estimated_count, transaction_estimated_count: transaction_estimated_count,

@ -7,6 +7,7 @@ defmodule BlockScoutWeb.Notifier do
alias BlockScoutWeb.Endpoint alias BlockScoutWeb.Endpoint
alias Explorer.{Chain, Market, Repo} alias Explorer.{Chain, Market, Repo}
alias Explorer.Chain.{Address, InternalTransaction, Transaction} alias Explorer.Chain.{Address, InternalTransaction, Transaction}
alias Explorer.Counters.AverageBlockTime
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
def handle_event({:chain_event, :addresses, :realtime, addresses}) do def handle_event({:chain_event, :addresses, :realtime, addresses}) do
@ -109,7 +110,7 @@ defmodule BlockScoutWeb.Notifier do
defp broadcast_block(block) do defp broadcast_block(block) do
preloaded_block = Repo.preload(block, [[miner: :names], :transactions, :rewards]) preloaded_block = Repo.preload(block, [[miner: :names], :transactions, :rewards])
average_block_time = Chain.average_block_time() average_block_time = AverageBlockTime.average_block_time(preloaded_block)
Endpoint.broadcast("blocks:new_block", "new_block", %{ Endpoint.broadcast("blocks:new_block", "new_block", %{
block: preloaded_block, block: preloaded_block,

@ -32,14 +32,19 @@
</div> </div>
</div> </div>
<div class="dashboard-banner-network-stats"> <div class="dashboard-banner-network-stats">
<%= case @average_block_time do %>
<% {:error, :disabled} -> %>
<%= nil %>
<% average_block_time -> %>
<div class="dashboard-banner-network-stats-item"> <div class="dashboard-banner-network-stats-item">
<span class="dashboard-banner-network-stats-label"> <span class="dashboard-banner-network-stats-label">
<%= gettext "Average block time" %> <%= gettext "Average block time" %>
</span> </span>
<span class="dashboard-banner-network-stats-value" data-selector="average-block-time"> <span class="dashboard-banner-network-stats-value" data-selector="average-block-time">
<%= Timex.format_duration(@average_block_time, :humanized) %> <%= Timex.format_duration(average_block_time, :humanized) %>
</span> </span>
</div> </div>
<% end %>
<div class="dashboard-banner-network-stats-item"> <div class="dashboard-banner-network-stats-item">
<span class="dashboard-banner-network-stats-label"> <span class="dashboard-banner-network-stats-label">
<%= gettext "Total transactions" %> <%= gettext "Total transactions" %>

@ -118,7 +118,7 @@ msgid "All"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:37 #: lib/block_scout_web/templates/chain/show.html.eex:41
msgid "Average block time" msgid "Average block time"
msgstr "" msgstr ""
@ -175,7 +175,7 @@ msgid "BlockScout provides analytics data, API, and Smart Contract tools for the
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:67 #: lib/block_scout_web/templates/chain/show.html.eex:72
#: lib/block_scout_web/templates/layout/_topnav.html.eex:16 #: lib/block_scout_web/templates/layout/_topnav.html.eex:16
#: lib/block_scout_web/templates/layout/_topnav.html.eex:20 #: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Blocks" msgid "Blocks"
@ -572,7 +572,7 @@ msgid "More internal transactions have come in"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:91 #: lib/block_scout_web/templates/chain/show.html.eex:96
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:14 #: lib/block_scout_web/templates/pending_transaction/index.html.eex:14
#: lib/block_scout_web/templates/transaction/index.html.eex:14 #: lib/block_scout_web/templates/transaction/index.html.eex:14
msgid "More transactions have come in" msgid "More transactions have come in"
@ -949,7 +949,7 @@ msgid "Total Supply"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:45 #: lib/block_scout_web/templates/chain/show.html.eex:50
msgid "Total transactions" msgid "Total transactions"
msgstr "" msgstr ""
@ -983,7 +983,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:23 #: lib/block_scout_web/templates/block_transaction/index.html.eex:23
#: lib/block_scout_web/templates/block_transaction/index.html.eex:26 #: lib/block_scout_web/templates/block_transaction/index.html.eex:26
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35 #: lib/block_scout_web/templates/block_transaction/index.html.eex:35
#: lib/block_scout_web/templates/chain/show.html.eex:88 #: lib/block_scout_web/templates/chain/show.html.eex:93
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35 #: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/views/address_view.ex:253 #: lib/block_scout_web/views/address_view.ex:253
msgid "Transactions" msgid "Transactions"
@ -1058,12 +1058,12 @@ msgid "Verify & publish"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:66 #: lib/block_scout_web/templates/chain/show.html.eex:71
msgid "View All Blocks →" msgid "View All Blocks →"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:87 #: lib/block_scout_web/templates/chain/show.html.eex:92
msgid "View All Transactions →" msgid "View All Transactions →"
msgstr "" msgstr ""
@ -1103,7 +1103,7 @@ msgid "WEI"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:53 #: lib/block_scout_web/templates/chain/show.html.eex:58
msgid "Wallet addresses" msgid "Wallet addresses"
msgstr "" msgstr ""
@ -1187,8 +1187,8 @@ msgstr ""
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:19 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:19
#: lib/block_scout_web/templates/address_validation/index.html.eex:63 #: lib/block_scout_web/templates/address_validation/index.html.eex:63
#: lib/block_scout_web/templates/address_validation/index.html.eex:82 #: lib/block_scout_web/templates/address_validation/index.html.eex:82
#: lib/block_scout_web/templates/chain/show.html.eex:79 #: lib/block_scout_web/templates/chain/show.html.eex:84
#: lib/block_scout_web/templates/chain/show.html.eex:105 #: lib/block_scout_web/templates/chain/show.html.eex:110
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:24 #: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:24
msgid "Loading..." msgid "Loading..."
msgstr "" msgstr ""
@ -1399,7 +1399,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:26 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:26
#: lib/block_scout_web/templates/address_transaction/index.html.eex:55 #: lib/block_scout_web/templates/address_transaction/index.html.eex:55
#: lib/block_scout_web/templates/address_validation/index.html.eex:70 #: lib/block_scout_web/templates/address_validation/index.html.eex:70
#: lib/block_scout_web/templates/chain/show.html.eex:71 #: lib/block_scout_web/templates/chain/show.html.eex:76
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:23 #: lib/block_scout_web/templates/pending_transaction/index.html.eex:23
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:22 #: lib/block_scout_web/templates/tokens/holder/index.html.eex:22
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20 #: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20
@ -1522,6 +1522,6 @@ msgid "Emission Contract"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:97 #: lib/block_scout_web/templates/chain/show.html.eex:102
msgid "Something went wrong, click to retry." msgid "Something went wrong, click to retry."
msgstr "" msgstr ""

@ -118,7 +118,7 @@ msgid "All"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:37 #: lib/block_scout_web/templates/chain/show.html.eex:41
msgid "Average block time" msgid "Average block time"
msgstr "" msgstr ""
@ -175,7 +175,7 @@ msgid "BlockScout provides analytics data, API, and Smart Contract tools for the
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:67 #: lib/block_scout_web/templates/chain/show.html.eex:72
#: lib/block_scout_web/templates/layout/_topnav.html.eex:16 #: lib/block_scout_web/templates/layout/_topnav.html.eex:16
#: lib/block_scout_web/templates/layout/_topnav.html.eex:20 #: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Blocks" msgid "Blocks"
@ -572,7 +572,7 @@ msgid "More internal transactions have come in"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:91 #: lib/block_scout_web/templates/chain/show.html.eex:96
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:14 #: lib/block_scout_web/templates/pending_transaction/index.html.eex:14
#: lib/block_scout_web/templates/transaction/index.html.eex:14 #: lib/block_scout_web/templates/transaction/index.html.eex:14
msgid "More transactions have come in" msgid "More transactions have come in"
@ -949,7 +949,7 @@ msgid "Total Supply"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:45 #: lib/block_scout_web/templates/chain/show.html.eex:50
msgid "Total transactions" msgid "Total transactions"
msgstr "" msgstr ""
@ -983,7 +983,7 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:23 #: lib/block_scout_web/templates/block_transaction/index.html.eex:23
#: lib/block_scout_web/templates/block_transaction/index.html.eex:26 #: lib/block_scout_web/templates/block_transaction/index.html.eex:26
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35 #: lib/block_scout_web/templates/block_transaction/index.html.eex:35
#: lib/block_scout_web/templates/chain/show.html.eex:88 #: lib/block_scout_web/templates/chain/show.html.eex:93
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35 #: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/views/address_view.ex:253 #: lib/block_scout_web/views/address_view.ex:253
msgid "Transactions" msgid "Transactions"
@ -1058,12 +1058,12 @@ msgid "Verify & publish"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:66 #: lib/block_scout_web/templates/chain/show.html.eex:71
msgid "View All Blocks →" msgid "View All Blocks →"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:87 #: lib/block_scout_web/templates/chain/show.html.eex:92
msgid "View All Transactions →" msgid "View All Transactions →"
msgstr "" msgstr ""
@ -1103,7 +1103,7 @@ msgid "WEI"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:53 #: lib/block_scout_web/templates/chain/show.html.eex:58
msgid "Wallet addresses" msgid "Wallet addresses"
msgstr "" msgstr ""
@ -1187,8 +1187,8 @@ msgstr ""
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:19 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:19
#: lib/block_scout_web/templates/address_validation/index.html.eex:63 #: lib/block_scout_web/templates/address_validation/index.html.eex:63
#: lib/block_scout_web/templates/address_validation/index.html.eex:82 #: lib/block_scout_web/templates/address_validation/index.html.eex:82
#: lib/block_scout_web/templates/chain/show.html.eex:79 #: lib/block_scout_web/templates/chain/show.html.eex:84
#: lib/block_scout_web/templates/chain/show.html.eex:105 #: lib/block_scout_web/templates/chain/show.html.eex:110
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:24 #: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:24
msgid "Loading..." msgid "Loading..."
msgstr "" msgstr ""
@ -1399,7 +1399,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:26 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:26
#: lib/block_scout_web/templates/address_transaction/index.html.eex:55 #: lib/block_scout_web/templates/address_transaction/index.html.eex:55
#: lib/block_scout_web/templates/address_validation/index.html.eex:70 #: lib/block_scout_web/templates/address_validation/index.html.eex:70
#: lib/block_scout_web/templates/chain/show.html.eex:71 #: lib/block_scout_web/templates/chain/show.html.eex:76
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:23 #: lib/block_scout_web/templates/pending_transaction/index.html.eex:23
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:22 #: lib/block_scout_web/templates/tokens/holder/index.html.eex:22
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20 #: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20
@ -1522,6 +1522,6 @@ msgid "Emission Contract"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:97 #: lib/block_scout_web/templates/chain/show.html.eex:102
msgid "Something went wrong, click to retry." msgid "Something went wrong, click to retry."
msgstr "" msgstr ""

@ -11,6 +11,8 @@ config :explorer,
coin: System.get_env("COIN") || "POA", coin: System.get_env("COIN") || "POA",
token_functions_reader_max_retries: 3 token_functions_reader_max_retries: 3
config :explorer, Explorer.Counters.AverageBlockTime, enabled: true
config :explorer, Explorer.Counters.AddressesWithBalanceCounter, enabled: true, enable_consolidation: true config :explorer, Explorer.Counters.AddressesWithBalanceCounter, enabled: true, enable_consolidation: true
config :explorer, Explorer.ExchangeRates, enabled: true, store: :ets config :explorer, Explorer.ExchangeRates, enabled: true, store: :ets

@ -15,6 +15,8 @@ config :explorer, Explorer.ExchangeRates, enabled: false, store: :ets
config :explorer, Explorer.KnownTokens, enabled: false, store: :ets config :explorer, Explorer.KnownTokens, enabled: false, store: :ets
config :explorer, Explorer.Counters.AverageBlockTime, enabled: false
config :explorer, Explorer.Counters.AddressesWithBalanceCounter, enabled: false, enable_consolidation: false config :explorer, Explorer.Counters.AddressesWithBalanceCounter, enabled: false, enable_consolidation: false
config :explorer, Explorer.Market.History.Cataloger, enabled: false config :explorer, Explorer.Market.History.Cataloger, enabled: false

@ -37,6 +37,7 @@ defmodule Explorer.Application do
configure(Explorer.KnownTokens), configure(Explorer.KnownTokens),
configure(Explorer.Market.History.Cataloger), configure(Explorer.Market.History.Cataloger),
configure(Explorer.Counters.AddressesWithBalanceCounter), configure(Explorer.Counters.AddressesWithBalanceCounter),
configure(Explorer.Counters.AverageBlockTime),
configure(Explorer.Validator.MetadataProcessor) configure(Explorer.Validator.MetadataProcessor)
] ]
|> List.flatten() |> List.flatten()

@ -44,7 +44,6 @@ defmodule Explorer.Chain do
alias Explorer.{PagingOptions, Repo} alias Explorer.{PagingOptions, Repo}
alias Dataloader.Ecto, as: DataloaderEcto alias Dataloader.Ecto, as: DataloaderEcto
alias Timex.Duration
@default_paging_options %PagingOptions{page_size: 50} @default_paging_options %PagingOptions{page_size: 50}
@ -287,31 +286,6 @@ defmodule Explorer.Chain do
|> Repo.all() |> Repo.all()
end end
@doc """
The average time it took to mine/validate the last <= 100 `t:Explorer.Chain.Block.t/0`
"""
@spec average_block_time :: %Timex.Duration{}
def average_block_time do
{:ok, %Postgrex.Result{rows: [[%Postgrex.Interval{months: 0, days: days, secs: seconds}]]}} =
SQL.query(
Repo,
"""
SELECT coalesce(avg(difference), interval '0 seconds')
FROM (
SELECT b.timestamp - lag(b.timestamp) over (order by b.timestamp) as difference
FROM (SELECT * FROM blocks ORDER BY number DESC LIMIT 101) b
LIMIT 100 OFFSET 1
) t
""",
[]
)
hours = days * 24
minutes = 0
microseconds = 0
Duration.from_clock({hours, minutes, seconds, microseconds})
end
@doc """ @doc """
The `t:Explorer.Chain.Address.t/0` `balance` in `unit`. The `t:Explorer.Chain.Address.t/0` `balance` in `unit`.
""" """

@ -0,0 +1,106 @@
defmodule Explorer.Counters.AverageBlockTime do
use GenServer
@moduledoc """
Caches the number of token holders of a token.
"""
import Ecto.Query, only: [from: 2]
alias Explorer.Chain.Block
alias Explorer.Repo
alias Timex.Duration
@doc """
Starts a process to periodically update the counter of the token holders.
"""
@spec start_link(term()) :: GenServer.on_start()
def start_link(_) do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
def average_block_time(block \\ nil) do
enabled? =
:explorer
|> Application.fetch_env!(__MODULE__)
|> Keyword.fetch!(:enabled)
if enabled? do
block = if block, do: {block.number, DateTime.to_unix(block.timestamp)}
GenServer.call(__MODULE__, {:average_block_time, block})
else
{:error, :disabled}
end
end
## Server
@impl true
def init(_) do
timestamps_query =
from(block in Block,
limit: 100,
offset: 1,
order_by: [desc: block.number],
select: {block.number, block.timestamp}
)
timestamps =
timestamps_query
|> Repo.all()
|> Enum.map(fn {number, timestamp} ->
{number, DateTime.to_unix(timestamp)}
end)
{:ok, %{timestamps: timestamps, average: average_distance(timestamps)}}
end
@impl true
def handle_call({:average_block_time, nil}, _from, %{average: average} = state), do: {:reply, average, state}
def handle_call({:average_block_time, block}, _from, state) do
state = add_block(state, block)
{:reply, state.average, state}
end
# This is pretty naive, but we'll only ever be sorting 100 dates so I don't think
# complex logic is really necessary here.
defp add_block(%{timestamps: timestamps} = state, block) do
timestamps =
[block | timestamps]
|> Enum.sort_by(fn {number, _} -> number end, &Kernel.>/2)
|> Enum.take(100)
%{state | timestamps: timestamps, average: average_distance(timestamps)}
end
defp average_distance([]), do: Duration.from_seconds(0)
defp average_distance([_]), do: Duration.from_seconds(0)
defp average_distance(timestamps) do
durations = durations(timestamps)
{sum, count} =
Enum.reduce(durations, {0, 0}, fn duration, {sum, count} ->
{sum + duration, count + 1}
end)
average = sum / count
average
|> round()
|> Duration.from_seconds()
end
defp durations(timestamps) do
timestamps
|> Enum.reduce({[], nil}, fn {_, timestamp}, {durations, last_timestamp} ->
if last_timestamp do
duration = last_timestamp - timestamp
{[duration | durations], timestamp}
else
{durations, timestamp}
end
end)
|> elem(0)
end
end

@ -112,7 +112,7 @@ defmodule Explorer.Mixfile do
{:spandex_ecto, "~> 0.4.0"}, {:spandex_ecto, "~> 0.4.0"},
# Attach `:prometheus_ecto` to `:ecto` # Attach `:prometheus_ecto` to `:ecto`
{:telemetry, "~> 0.2.0"}, {:telemetry, "~> 0.2.0"},
# `Timex.Duration` for `Explorer.Chain.average_block_time/0` # `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0`
{:timex, "~> 3.4"} {:timex, "~> 3.4"}
] ]
end end

@ -490,20 +490,6 @@ defmodule Explorer.ChainTest do
end end
end end
describe "average_block_time/0" do
test "without blocks duration is 0" do
assert Chain.average_block_time() == Timex.Duration.parse!("PT0S")
end
test "with blocks is average duration between blocks" do
first_block = insert(:block)
second_block = insert(:block, timestamp: Timex.shift(first_block.timestamp, seconds: 3))
insert(:block, timestamp: Timex.shift(second_block.timestamp, seconds: 9))
assert Chain.average_block_time() == Timex.Duration.parse!("PT6S")
end
end
describe "balance/2" do describe "balance/2" do
test "with Address.t with :wei" do test "with Address.t with :wei" do
assert Chain.balance(%Address{fetched_coin_balance: %Wei{value: Decimal.new(1)}}, :wei) == Decimal.new(1) assert Chain.balance(%Address{fetched_coin_balance: %Wei{value: Decimal.new(1)}}, :wei) == Decimal.new(1)

@ -0,0 +1,64 @@
defmodule Explorer.Counters.AverageBlockTimeTest do
use Explorer.DataCase
alias Explorer.Counters.AverageBlockTime
defp block(number, last, duration), do: %{number: number, timestamp: Timex.shift(last, seconds: duration)}
setup do
start_supervised!(AverageBlockTime)
Application.put_env(:explorer, AverageBlockTime, enabled: true)
on_exit(fn ->
Application.put_env(:explorer, AverageBlockTime, enabled: false)
end)
end
describe "average_block_time/1" do
test "when disabled, it returns an error" do
Application.put_env(:explorer, AverageBlockTime, enabled: false)
assert AverageBlockTime.average_block_time() == {:error, :disabled}
end
test "without blocks duration is 0" do
assert AverageBlockTime.average_block_time() == Timex.Duration.parse!("PT0S")
end
test "with only one block, the duration is 0" do
now = Timex.now()
block = block(0, now, 0)
assert AverageBlockTime.average_block_time(block) == Timex.Duration.parse!("PT0S")
end
test "once there are two blocks, the duration is the average distance between them all" do
now = Timex.now()
block0 = block(0, now, 0)
block1 = block(1, now, 2)
block2 = block(2, now, 6)
AverageBlockTime.average_block_time(block0)
assert AverageBlockTime.average_block_time(block1) == Timex.Duration.parse!("PT2S")
assert AverageBlockTime.average_block_time(block2) == Timex.Duration.parse!("PT3S")
end
test "only the last 100 blocks are considered" do
now = Timex.now()
block0 = block(0, now, 0)
block1 = block(1, now, 2000)
AverageBlockTime.average_block_time(block0)
AverageBlockTime.average_block_time(block1)
for i <- 1..100 do
block = block(i + 1, now, 2000 + i)
AverageBlockTime.average_block_time(block)
end
assert AverageBlockTime.average_block_time() == Timex.Duration.parse!("PT1S")
end
end
end
Loading…
Cancel
Save