From 04ae37f0701a5594a5101d0788201b476a3174e3 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 19 Jun 2019 13:20:39 +0300 Subject: [PATCH 01/52] fix response without request id --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex index 1c52a6e6c9..df8e2d53ce 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex @@ -75,9 +75,13 @@ defmodule EthereumJSONRPC.Block do end def from_response(%{id: id, result: block}, id_to_params) when is_map(id_to_params) do - true = Map.has_key?(id_to_params, id) + if Map.has_key?(id_to_params, id) do + {:ok, block} + else + Logger.warn(["id #{id} not found in #{inspect(id_to_params)}"]) - {:ok, block} + {:error, %{code: 404, message: "id #{id} not found in result", result: id_to_params}} + end end def from_response(%{id: id, error: error}, id_to_params) when is_map(id_to_params) do From 40ee6b0307f6aef159ae049a77bf0a23b4130a19 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 19 Jun 2019 13:23:29 +0300 Subject: [PATCH 02/52] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb0a5f0898..655c06fd79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ - [#2173](https://github.com/poanetwork/blockscout/pull/2173) - handle correctly empty transactions - [#2174](https://github.com/poanetwork/blockscout/pull/2174) - fix reward channel joining - [#2186](https://github.com/poanetwork/blockscout/pull/2186) - fix net version test +- [#2196](https://github.com/poanetwork/blockscout/pull/2196) - fix response without request id ### Chore - [#2127](https://github.com/poanetwork/blockscout/pull/2127) - use previouse chromedriver version From a5f18824bc64605f1e957f2e80b45a25adf22747 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 19 Jun 2019 13:24:50 +0300 Subject: [PATCH 03/52] require logger --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex index df8e2d53ce..cdb586c89f 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex @@ -4,6 +4,8 @@ defmodule EthereumJSONRPC.Block do and [`eth_getBlockByNumber`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber). """ + require Logger + import EthereumJSONRPC, only: [quantity_to_integer: 1, timestamp_to_datetime: 1] alias EthereumJSONRPC.{Transactions, Uncles} From 381316f9df2881e07cfa2653a9acbfac3bf76972 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 19 Jun 2019 14:21:51 +0300 Subject: [PATCH 04/52] fix Nethermind json rpc errors --- .../lib/ethereum_jsonrpc/block.ex | 20 +++++++++++-------- .../lib/ethereum_jsonrpc/transaction.ex | 4 ++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex index cdb586c89f..bac26b1497 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex @@ -4,8 +4,6 @@ defmodule EthereumJSONRPC.Block do and [`eth_getBlockByNumber`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber). """ - require Logger - import EthereumJSONRPC, only: [quantity_to_integer: 1, timestamp_to_datetime: 1] alias EthereumJSONRPC.{Transactions, Uncles} @@ -77,13 +75,16 @@ defmodule EthereumJSONRPC.Block do end def from_response(%{id: id, result: block}, id_to_params) when is_map(id_to_params) do - if Map.has_key?(id_to_params, id) do - {:ok, block} - else - Logger.warn(["id #{id} not found in #{inspect(id_to_params)}"]) + id = + if is_binary(id) do + quantity_to_integer(id) + else + id + end + + true = Map.has_key?(id_to_params, id) - {:error, %{code: 404, message: "id #{id} not found in result", result: id_to_params}} - end + {:ok, block} end def from_response(%{id: id, error: error}, id_to_params) when is_map(id_to_params) do @@ -447,6 +448,9 @@ defmodule EthereumJSONRPC.Block do {key, quantity_to_integer(quantity)} end + # we don't need transaction hashes because we fetch full transactions + defp entry_to_elixir({"transactionHashes" = key, _}), do: {key, nil} + # Size and totalDifficulty may be `nil` for uncle blocks defp entry_to_elixir({key, nil}) when key in ~w(size totalDifficulty) do {key, nil} diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex index d59c1fb349..f021bfa153 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/transaction.ex @@ -322,6 +322,10 @@ defmodule EthereumJSONRPC.Transaction do when key in ~w(blockHash condition creates from hash input jsonrpc publicKey raw to txType), do: {key, value} + # specific to Nethermind client + defp entry_to_elixir({"data", value}), + do: {"input", value} + defp entry_to_elixir({key, quantity}) when key in ~w(gas gasPrice nonce r s standardV v value) and quantity != nil do {key, quantity_to_integer(quantity)} end From e580792b405ed0cedf01d1a369e775d9cced2320 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 19 Jun 2019 14:26:51 +0300 Subject: [PATCH 05/52] update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 655c06fd79..4a88575126 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,7 @@ - [#2173](https://github.com/poanetwork/blockscout/pull/2173) - handle correctly empty transactions - [#2174](https://github.com/poanetwork/blockscout/pull/2174) - fix reward channel joining - [#2186](https://github.com/poanetwork/blockscout/pull/2186) - fix net version test -- [#2196](https://github.com/poanetwork/blockscout/pull/2196) - fix response without request id +- [#2196](https://github.com/poanetwork/blockscout/pull/2196) - Nethermind client fixes ### Chore - [#2127](https://github.com/poanetwork/blockscout/pull/2127) - use previouse chromedriver version From b594c3c8af86e6feafa463b9133cf08d9d9c85f2 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 19 Jun 2019 14:42:31 +0300 Subject: [PATCH 06/52] fix more Nethermind errors --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex | 7 ------- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex | 10 ++++++++++ apps/indexer/lib/indexer/transform/blocks.ex | 3 +++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex index bac26b1497..c3c72c4fb8 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex @@ -75,13 +75,6 @@ defmodule EthereumJSONRPC.Block do end def from_response(%{id: id, result: block}, id_to_params) when is_map(id_to_params) do - id = - if is_binary(id) do - quantity_to_integer(id) - else - id - end - true = Map.has_key?(id_to_params, id) {:ok, block} diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex index ded7304364..f660da4ab4 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex @@ -7,6 +7,8 @@ defmodule EthereumJSONRPC.HTTP do require Logger + import EthereumJSONRPC, only: [quantity_to_integer: 1] + @behaviour Transport @doc """ @@ -131,6 +133,14 @@ defmodule EthereumJSONRPC.HTTP do # restrict response to only those fields supported by the JSON-RPC 2.0 standard, which means that level of keys is # validated, so we can indicate that with switch to atom keys. defp standardize_response(%{"jsonrpc" => "2.0" = jsonrpc, "id" => id} = unstandardized) do + # Nethermind return string ids + id = + if is_binary(id) do + quantity_to_integer(id) + else + id + end + standardized = %{jsonrpc: jsonrpc, id: id} case unstandardized do diff --git a/apps/indexer/lib/indexer/transform/blocks.ex b/apps/indexer/lib/indexer/transform/blocks.ex index c55c9a9974..8d506a413d 100644 --- a/apps/indexer/lib/indexer/transform/blocks.ex +++ b/apps/indexer/lib/indexer/transform/blocks.ex @@ -65,6 +65,9 @@ defmodule Indexer.Transform.Blocks do decode(rest) end + # specific to Nethermind + defp decode("0"), do: 0 + defp decode(data) do Base.decode16!(data, case: :mixed) end From 3ff500e9d7e85a0a0aeb3cb13a91631280907504 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 20 Jun 2019 11:48:13 +0300 Subject: [PATCH 07/52] ignore nethermind field for an error --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex index 7bc96509b4..4b8fdfb7f7 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex @@ -294,6 +294,12 @@ defmodule EthereumJSONRPC.Receipt do :ignore end + # Nethermind field + defp entry_to_elixir({"error", _}) do + :ignore + end + + defp entry_to_elixir({key, value}) do {:error, {:unknown_key, %{key: key, value: value}}} end From 156bd82649f6c64b6063fa21fc07ed48f30ebb25 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 25 Jun 2019 12:53:51 +0300 Subject: [PATCH 08/52] fix rsk total_supply --- apps/explorer/lib/explorer/chain/supply/rsk.ex | 11 ++++------- .../test/explorer/chain/supply/rsk_test.exs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/supply/rsk.ex b/apps/explorer/lib/explorer/chain/supply/rsk.ex index 09a02252a2..ec55c94e95 100644 --- a/apps/explorer/lib/explorer/chain/supply/rsk.ex +++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex @@ -9,11 +9,12 @@ defmodule Explorer.Chain.Supply.RSK do alias Explorer.Chain.Address.CoinBalance alias Explorer.Chain.{Block, Wei} - alias Explorer.ExchangeRates.Token - alias Explorer.{Market, Repo} + alias Explorer.Repo def market_cap(exchange_rate) do - circulating() * exchange_rate.usd_value + ether = Wei.to(circulating(), :ether) + + Decimal.mult(ether, exchange_rate.usd_value) end @doc "Equivalent to getting the circulating value " @@ -96,8 +97,4 @@ defmodule Explorer.Chain.Supply.RSK do def total do 21_000_000 end - - def exchange_rate do - Market.get_exchange_rate(Explorer.coin()) || Token.null() - end end diff --git a/apps/explorer/test/explorer/chain/supply/rsk_test.exs b/apps/explorer/test/explorer/chain/supply/rsk_test.exs index 40aa0a831b..db87fd3e2b 100644 --- a/apps/explorer/test/explorer/chain/supply/rsk_test.exs +++ b/apps/explorer/test/explorer/chain/supply/rsk_test.exs @@ -3,6 +3,7 @@ defmodule Explorer.Chain.Supply.RSKTest do alias Explorer.Chain.Supply.RSK alias Explorer.Chain.Wei + alias Explorer.ExchangeRates.Token @coin_address "0x0000000000000000000000000000000001000006" @@ -15,6 +16,18 @@ defmodule Explorer.Chain.Supply.RSKTest do assert RSK.total() == 21_000_000 end + describe "market_cap/1" do + test "calculates market_cap" do + address = insert(:address, hash: @coin_address) + insert(:block, number: 0) + insert(:fetched_balance, value: 10_000_000_000_000_000_000, address_hash: address.hash, block_number: 0) + + exchange_rate = %{Token.null() | usd_value: Decimal.new(10)} + + assert RSK.market_cap(exchange_rate) == Decimal.new(100) + end + end + describe "circulating/0" do test "with no balance" do assert RSK.circulating() == wei!(0) From 651ce9790eab181ee6751fa4d077aad5a9c01b37 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 25 Jun 2019 12:55:40 +0300 Subject: [PATCH 09/52] add CHANGELOG entry --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b671d7539..aa181456a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,8 @@ - [#2173](https://github.com/poanetwork/blockscout/pull/2173) - handle correctly empty transactions - [#2174](https://github.com/poanetwork/blockscout/pull/2174) - fix reward channel joining - [#2186](https://github.com/poanetwork/blockscout/pull/2186) - fix net version test -- [#2167](https://github.com/poanetwork/blockscout/pull/2168) - feat: document eth rpc api mimicking endpoints +- [#2167](https://github.com/poanetwork/blockscout/pull/2168) - feat: document eth rpc api mimicking endpoints +- [#2237](https://github.com/poanetwork/blockscout/pull/2237) - fix rsk total_supply ### Chore - [#2127](https://github.com/poanetwork/blockscout/pull/2127) - use previouse chromedriver version From 9f3e8eec89197404100516722dcff60501caddfc Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 27 Jun 2019 12:12:18 +0300 Subject: [PATCH 10/52] fix rsk marketcap --- apps/explorer/lib/explorer/chain/supply/rsk.ex | 5 ++++- apps/explorer/test/explorer/chain/supply/rsk_test.exs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/supply/rsk.ex b/apps/explorer/lib/explorer/chain/supply/rsk.ex index ec55c94e95..365eaf3685 100644 --- a/apps/explorer/lib/explorer/chain/supply/rsk.ex +++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex @@ -12,7 +12,10 @@ defmodule Explorer.Chain.Supply.RSK do alias Explorer.Repo def market_cap(exchange_rate) do - ether = Wei.to(circulating(), :ether) + ether = + circulating() + |> Wei.to(:ether) + |> Decimal.div(Decimal.new(1_000)) Decimal.mult(ether, exchange_rate.usd_value) end diff --git a/apps/explorer/test/explorer/chain/supply/rsk_test.exs b/apps/explorer/test/explorer/chain/supply/rsk_test.exs index db87fd3e2b..b8a1e7f705 100644 --- a/apps/explorer/test/explorer/chain/supply/rsk_test.exs +++ b/apps/explorer/test/explorer/chain/supply/rsk_test.exs @@ -20,7 +20,7 @@ defmodule Explorer.Chain.Supply.RSKTest do test "calculates market_cap" do address = insert(:address, hash: @coin_address) insert(:block, number: 0) - insert(:fetched_balance, value: 10_000_000_000_000_000_000, address_hash: address.hash, block_number: 0) + insert(:fetched_balance, value: 10_000_000_000_000_000_000_000, address_hash: address.hash, block_number: 0) exchange_rate = %{Token.null() | usd_value: Decimal.new(10)} From eaed589d5d5971dca21a871dde37c68b46da3930 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 27 Jun 2019 12:36:06 +0300 Subject: [PATCH 11/52] increase by 2 decimals --- apps/explorer/lib/explorer/chain/supply/rsk.ex | 2 +- apps/explorer/test/explorer/chain/supply/rsk_test.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/supply/rsk.ex b/apps/explorer/lib/explorer/chain/supply/rsk.ex index 365eaf3685..6cefb9814f 100644 --- a/apps/explorer/lib/explorer/chain/supply/rsk.ex +++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex @@ -15,7 +15,7 @@ defmodule Explorer.Chain.Supply.RSK do ether = circulating() |> Wei.to(:ether) - |> Decimal.div(Decimal.new(1_000)) + |> Decimal.div(Decimal.new(100_000)) Decimal.mult(ether, exchange_rate.usd_value) end diff --git a/apps/explorer/test/explorer/chain/supply/rsk_test.exs b/apps/explorer/test/explorer/chain/supply/rsk_test.exs index b8a1e7f705..b3b87b7d49 100644 --- a/apps/explorer/test/explorer/chain/supply/rsk_test.exs +++ b/apps/explorer/test/explorer/chain/supply/rsk_test.exs @@ -20,7 +20,7 @@ defmodule Explorer.Chain.Supply.RSKTest do test "calculates market_cap" do address = insert(:address, hash: @coin_address) insert(:block, number: 0) - insert(:fetched_balance, value: 10_000_000_000_000_000_000_000, address_hash: address.hash, block_number: 0) + insert(:fetched_balance, value: 1_000_000_000_000_000_000_000_000, address_hash: address.hash, block_number: 0) exchange_rate = %{Token.null() | usd_value: Decimal.new(10)} From cd7227e8df9c9e079e0e6629c1ef26b4978defc9 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 1 Jul 2019 12:38:42 +0300 Subject: [PATCH 12/52] fix circulating value --- apps/explorer/lib/explorer/application.ex | 13 ++-- .../explorer/lib/explorer/chain/supply/rsk.ex | 71 ++++++++++++++----- .../test/explorer/chain/supply/rsk_test.exs | 37 +++------- 3 files changed, 71 insertions(+), 50 deletions(-) diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index 724e4f41a1..4c2e9f79ba 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -7,6 +7,7 @@ defmodule Explorer.Application do alias Explorer.Admin alias Explorer.Chain.{BlockCountCache, BlockNumberCache, BlocksCache, NetVersionCache, TransactionCountCache} + alias Explorer.Chain.Supply.RSK alias Explorer.Market.MarketHistoryCache alias Explorer.Repo.PrometheusLogger @@ -34,7 +35,8 @@ defmodule Explorer.Application do {BlockCountCache, []}, con_cache_child_spec(BlocksCache.cache_name()), con_cache_child_spec(NetVersionCache.cache_name()), - con_cache_child_spec(MarketHistoryCache.cache_name()) + con_cache_child_spec(MarketHistoryCache.cache_name()), + con_cache_child_spec(RSK.cache_name(), ttl_check_interval: :timer.minutes(1), global_ttl: :timer.minutes(30)) ] children = base_children ++ configurable_children() @@ -83,14 +85,13 @@ defmodule Explorer.Application do ] end - defp con_cache_child_spec(name) do + defp con_cache_child_spec(name, params \\ [ttl_check_interval: false]) do + params = Keyword.put(params, :name, name) + Supervisor.child_spec( { ConCache, - [ - name: name, - ttl_check_interval: false - ] + params }, id: {ConCache, name} ) diff --git a/apps/explorer/lib/explorer/chain/supply/rsk.ex b/apps/explorer/lib/explorer/chain/supply/rsk.ex index 6cefb9814f..7d6fa87312 100644 --- a/apps/explorer/lib/explorer/chain/supply/rsk.ex +++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex @@ -6,18 +6,20 @@ defmodule Explorer.Chain.Supply.RSK do use Explorer.Chain.Supply import Ecto.Query, only: [from: 2] + import EthereumJSONRPC, only: [integer_to_quantity: 1] + alias EthereumJSONRPC.FetchedBalances alias Explorer.Chain.Address.CoinBalance - alias Explorer.Chain.{Block, Wei} + alias Explorer.Chain.{Block, BlockNumberCache, Wei} alias Explorer.Repo + @cache_name :rsk_balance + @balance_key :balance + def market_cap(exchange_rate) do - ether = - circulating() - |> Wei.to(:ether) - |> Decimal.div(Decimal.new(100_000)) + btc = circulating() - Decimal.mult(ether, exchange_rate.usd_value) + Decimal.mult(btc, exchange_rate.usd_value) end @doc "Equivalent to getting the circulating value " @@ -78,18 +80,51 @@ defmodule Explorer.Chain.Supply.RSK do end def circulating do - query = - from(balance in CoinBalance, - join: block in Block, - on: block.number == balance.block_number, - where: block.consensus == true, - where: balance.address_hash == ^"0x0000000000000000000000000000000001000006", - order_by: [desc: block.timestamp], - limit: 1, - select: balance.value - ) + value = ConCache.get(@cache_name, @balance_key) + + if is_nil(value) do + updated_value = fetch_circulating_value() + + ConCache.put(@cache_name, @balance_key, updated_value) + + updated_value + else + value + end + end - Repo.one(query) || wei!(0) + def cache_name, do: @cache_name + + defp fetch_circulating_value do + max_number = BlockNumberCache.max_number() + + params = [ + %{block_quantity: integer_to_quantity(max_number), hash_data: "0x0000000000000000000000000000000001000006"} + ] + + json_rpc_named_argumens = Application.get_env(:explorer, :json_rpc_named_arguments) + + case EthereumJSONRPC.fetch_balances(params, json_rpc_named_argumens) do + {:ok, + %FetchedBalances{ + errors: [], + params_list: [ + %{ + address_hash: "0x0000000000000000000000000000000001000006", + value: value + } + ] + }} -> + sub = + value + |> Decimal.new() + |> Decimal.div(Decimal.new(1_000_000_000_000_000_000)) + + Decimal.sub(total(), sub) + + _ -> + Decimal.new(0) + end end defp wei!(value) do @@ -98,6 +133,6 @@ defmodule Explorer.Chain.Supply.RSK do end def total do - 21_000_000 + Decimal.new(21_000_000) end end diff --git a/apps/explorer/test/explorer/chain/supply/rsk_test.exs b/apps/explorer/test/explorer/chain/supply/rsk_test.exs index b3b87b7d49..d22ed8fc02 100644 --- a/apps/explorer/test/explorer/chain/supply/rsk_test.exs +++ b/apps/explorer/test/explorer/chain/supply/rsk_test.exs @@ -1,45 +1,30 @@ defmodule Explorer.Chain.Supply.RSKTest do use Explorer.DataCase + import Mox + alias Explorer.Chain.Supply.RSK alias Explorer.Chain.Wei alias Explorer.ExchangeRates.Token @coin_address "0x0000000000000000000000000000000001000006" - defp wei!(value) do - {:ok, wei} = Wei.cast(value) - wei - end - test "total is 21_000_000" do - assert RSK.total() == 21_000_000 + assert Decimal.equal?(RSK.total(), Decimal.new(21_000_000)) end describe "market_cap/1" do + @tag :no_parity + @tag :no_geth test "calculates market_cap" do - address = insert(:address, hash: @coin_address) - insert(:block, number: 0) - insert(:fetched_balance, value: 1_000_000_000_000_000_000_000_000, address_hash: address.hash, block_number: 0) + EthereumJSONRPC.Mox + |> expect(:json_rpc, fn [%{id: id, method: "eth_getBalance"}], _options -> + {:ok, [%{id: id, result: "20999999999900000000000000"}]} + end) - exchange_rate = %{Token.null() | usd_value: Decimal.new(10)} - - assert RSK.market_cap(exchange_rate) == Decimal.new(100) - end - end - - describe "circulating/0" do - test "with no balance" do - assert RSK.circulating() == wei!(0) - end - - test "with a balance" do - address = insert(:address, hash: @coin_address) - insert(:block, number: 0) - - insert(:fetched_balance, value: 10, address_hash: address.hash, block_number: 0) + exchange_rate = %{Token.null() | usd_value: Decimal.new(1_000_000)} - assert RSK.circulating() == wei!(10) + assert Decimal.equal?(RSK.market_cap(exchange_rate), Decimal.new(100.0000)) end end From 181d0b6f252ea2938cb2371356a8276e3ace8f9e Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 1 Jul 2019 12:39:38 +0300 Subject: [PATCH 13/52] add rescue clause --- apps/explorer/lib/explorer/chain/supply/rsk.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/explorer/lib/explorer/chain/supply/rsk.ex b/apps/explorer/lib/explorer/chain/supply/rsk.ex index 7d6fa87312..305ff50429 100644 --- a/apps/explorer/lib/explorer/chain/supply/rsk.ex +++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex @@ -125,6 +125,8 @@ defmodule Explorer.Chain.Supply.RSK do _ -> Decimal.new(0) end + rescue + _ -> Decimal.new(0) end defp wei!(value) do From c3997a1d8a9a191decc898ef4a7c8ad5bed18f63 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 1 Jul 2019 14:24:01 +0300 Subject: [PATCH 14/52] fix supply for days --- .../explorer/lib/explorer/chain/supply/rsk.ex | 4 +-- .../test/explorer/chain/supply/rsk_test.exs | 31 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/supply/rsk.ex b/apps/explorer/lib/explorer/chain/supply/rsk.ex index 305ff50429..37d04598ff 100644 --- a/apps/explorer/lib/explorer/chain/supply/rsk.ex +++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex @@ -68,10 +68,10 @@ defmodule Explorer.Chain.Supply.RSK do case Map.get(by_day, date) do nil -> - {Map.put(days, date, last), last} + {Map.put(days, date, Decimal.sub(total(), last)), last} value -> - {Map.put(days, date, value.value), value.value} + {Map.put(days, date, Decimal.sub(total(), value.value)), value.value} end end) |> elem(0) diff --git a/apps/explorer/test/explorer/chain/supply/rsk_test.exs b/apps/explorer/test/explorer/chain/supply/rsk_test.exs index d22ed8fc02..9504ce5df4 100644 --- a/apps/explorer/test/explorer/chain/supply/rsk_test.exs +++ b/apps/explorer/test/explorer/chain/supply/rsk_test.exs @@ -4,7 +4,6 @@ defmodule Explorer.Chain.Supply.RSKTest do import Mox alias Explorer.Chain.Supply.RSK - alias Explorer.Chain.Wei alias Explorer.ExchangeRates.Token @coin_address "0x0000000000000000000000000000000001000006" @@ -45,9 +44,9 @@ defmodule Explorer.Chain.Supply.RSKTest do assert RSK.supply_for_days(2) == {:ok, %{ - date(now, days: -2) => dec(0), - date(now, days: -1) => dec(0), - date(now) => dec(0) + date(now, days: -2) => dec(21_000_000), + date(now, days: -1) => dec(21_000_000), + date(now) => dec(21_000_000) }} end @@ -62,9 +61,9 @@ defmodule Explorer.Chain.Supply.RSKTest do assert RSK.supply_for_days(2) == {:ok, %{ - date(now, days: -2) => dec(10), - date(now, days: -1) => dec(10), - date(now) => dec(10) + date(now, days: -2) => dec(20_999_990), + date(now, days: -1) => dec(20_999_990), + date(now) => dec(20_999_990) }} end @@ -82,9 +81,9 @@ defmodule Explorer.Chain.Supply.RSKTest do assert RSK.supply_for_days(2) == {:ok, %{ - date(now, days: -2) => dec(10), - date(now, days: -1) => dec(20), - date(now) => dec(20) + date(now, days: -2) => dec(20_999_990), + date(now, days: -1) => dec(20_999_980), + date(now) => dec(20_999_980) }} end @@ -105,9 +104,9 @@ defmodule Explorer.Chain.Supply.RSKTest do assert RSK.supply_for_days(2) == {:ok, %{ - date(now, days: -2) => dec(10), - date(now, days: -1) => dec(20), - date(now) => dec(20) + date(now, days: -2) => dec(20_999_990), + date(now, days: -1) => dec(20_999_980), + date(now) => dec(20_999_980) }} end @@ -128,9 +127,9 @@ defmodule Explorer.Chain.Supply.RSKTest do assert RSK.supply_for_days(2) == {:ok, %{ - date(now, days: -2) => dec(10), - date(now, days: -1) => dec(20), - date(now) => dec(30) + date(now, days: -2) => dec(20_999_990), + date(now, days: -1) => dec(20_999_980), + date(now) => dec(20_999_970) }} end end From dd6c27ff9fd2c3364a8e4eb062f2e914edf4eac5 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 2 Jul 2019 10:54:44 +0300 Subject: [PATCH 15/52] fix value conversion --- .../explorer/lib/explorer/chain/supply/rsk.ex | 31 ++++++++++++------- .../test/explorer/chain/supply/rsk_test.exs | 21 +++++++------ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/supply/rsk.ex b/apps/explorer/lib/explorer/chain/supply/rsk.ex index 37d04598ff..bc4171e45f 100644 --- a/apps/explorer/lib/explorer/chain/supply/rsk.ex +++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex @@ -66,13 +66,16 @@ defmodule Explorer.Chain.Supply.RSK do |> Timex.shift(days: i) |> Timex.to_date() - case Map.get(by_day, date) do - nil -> - {Map.put(days, date, Decimal.sub(total(), last)), last} + cur_value = + case Map.get(by_day, date) do + nil -> + last - value -> - {Map.put(days, date, Decimal.sub(total(), value.value)), value.value} - end + value -> + value.value + end + + {Map.put(days, date, calculate_value(cur_value)), cur_value} end) |> elem(0) @@ -115,12 +118,7 @@ defmodule Explorer.Chain.Supply.RSK do } ] }} -> - sub = - value - |> Decimal.new() - |> Decimal.div(Decimal.new(1_000_000_000_000_000_000)) - - Decimal.sub(total(), sub) + calculate_value(value) _ -> Decimal.new(0) @@ -137,4 +135,13 @@ defmodule Explorer.Chain.Supply.RSK do def total do Decimal.new(21_000_000) end + + defp calculate_value(val) do + sub = + val + |> Decimal.new() + |> Decimal.div(Decimal.new(1_000_000_000_000_000_000)) + + Decimal.sub(total(), sub) + end end diff --git a/apps/explorer/test/explorer/chain/supply/rsk_test.exs b/apps/explorer/test/explorer/chain/supply/rsk_test.exs index 9504ce5df4..71d3a530bb 100644 --- a/apps/explorer/test/explorer/chain/supply/rsk_test.exs +++ b/apps/explorer/test/explorer/chain/supply/rsk_test.exs @@ -7,6 +7,7 @@ defmodule Explorer.Chain.Supply.RSKTest do alias Explorer.ExchangeRates.Token @coin_address "0x0000000000000000000000000000000001000006" + @mult 1_000_000_000_000_000_000 test "total is 21_000_000" do assert Decimal.equal?(RSK.total(), Decimal.new(21_000_000)) @@ -56,7 +57,7 @@ defmodule Explorer.Chain.Supply.RSKTest do insert(:block, number: 0, timestamp: Timex.shift(now, days: -10)) - insert(:fetched_balance, value: 10, address_hash: address.hash, block_number: 0) + insert(:fetched_balance, value: 10 * @mult, address_hash: address.hash, block_number: 0) assert RSK.supply_for_days(2) == {:ok, @@ -74,9 +75,9 @@ defmodule Explorer.Chain.Supply.RSKTest do insert(:block, number: 0, timestamp: Timex.shift(now, days: -10)) insert(:block, number: 1, timestamp: Timex.shift(now, days: -1)) - insert(:fetched_balance, value: 10, address_hash: address.hash, block_number: 0) + insert(:fetched_balance, value: 10 * @mult, address_hash: address.hash, block_number: 0) - insert(:fetched_balance, value: 20, address_hash: address.hash, block_number: 1) + insert(:fetched_balance, value: 20 * @mult, address_hash: address.hash, block_number: 1) assert RSK.supply_for_days(2) == {:ok, @@ -95,11 +96,11 @@ defmodule Explorer.Chain.Supply.RSKTest do insert(:block, number: 1, timestamp: Timex.shift(now, days: -2)) insert(:block, number: 2, timestamp: Timex.shift(now, days: -1)) - insert(:fetched_balance, value: 5, address_hash: address.hash, block_number: 0) + insert(:fetched_balance, value: 5 * @mult, address_hash: address.hash, block_number: 0) - insert(:fetched_balance, value: 10, address_hash: address.hash, block_number: 1) + insert(:fetched_balance, value: 10 * @mult, address_hash: address.hash, block_number: 1) - insert(:fetched_balance, value: 20, address_hash: address.hash, block_number: 2) + insert(:fetched_balance, value: 20 * @mult, address_hash: address.hash, block_number: 2) assert RSK.supply_for_days(2) == {:ok, @@ -119,10 +120,10 @@ defmodule Explorer.Chain.Supply.RSKTest do insert(:block, number: 2, timestamp: Timex.shift(now, days: -1)) insert(:block, number: 3, timestamp: now) - insert(:fetched_balance, value: 5, address_hash: address.hash, block_number: 0) - insert(:fetched_balance, value: 10, address_hash: address.hash, block_number: 1) - insert(:fetched_balance, value: 20, address_hash: address.hash, block_number: 2) - insert(:fetched_balance, value: 30, address_hash: address.hash, block_number: 3) + insert(:fetched_balance, value: 5 * @mult, address_hash: address.hash, block_number: 0) + insert(:fetched_balance, value: 10 * @mult, address_hash: address.hash, block_number: 1) + insert(:fetched_balance, value: 20 * @mult, address_hash: address.hash, block_number: 2) + insert(:fetched_balance, value: 30 * @mult, address_hash: address.hash, block_number: 3) assert RSK.supply_for_days(2) == {:ok, From 9e31ab6b13ee5e84c28661d2644e13a655de8e93 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 3 Jul 2019 11:06:32 +0300 Subject: [PATCH 16/52] handle empty availablesupply in web scokets --- apps/block_scout_web/assets/js/pages/chain.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/js/pages/chain.js b/apps/block_scout_web/assets/js/pages/chain.js index 00f92523ec..f4cd0e6628 100644 --- a/apps/block_scout_web/assets/js/pages/chain.js +++ b/apps/block_scout_web/assets/js/pages/chain.js @@ -142,7 +142,7 @@ const elements = { chart = createMarketHistoryChart($el[0]) }, render ($el, state, oldState) { - if (!chart || (oldState.availableSupply === state.availableSupply && oldState.marketHistoryData === state.marketHistoryData)) return + if (!chart || (oldState.availableSupply === state.availableSupply && oldState.marketHistoryData === state.marketHistoryData) || !state.availableSupply) return chart.update(state.availableSupply, state.marketHistoryData) } }, From bef66e846fa5714174538f15295bd98e0c39b4b1 Mon Sep 17 00:00:00 2001 From: pasqu4le Date: Tue, 2 Jul 2019 14:29:36 +0200 Subject: [PATCH 17/52] Add transactions cache Problem: due to the unsatisfying performance of the main page some ETS-based cache has been deemed necessary. In this particular case one for the most recent collated transactions. Solution: implementation of said transactions cache --- CHANGELOG.md | 1 + .../recent_transactions_controller.ex | 2 +- .../block_scout_web/test/support/conn_case.ex | 3 + .../test/support/feature_case.ex | 3 + apps/explorer/lib/explorer/application.ex | 14 +- apps/explorer/lib/explorer/chain.ex | 23 ++- .../chain/import/runner/transactions.ex | 3 +- .../lib/explorer/chain/transactions_cache.ex | 143 ++++++++++++++++++ .../chain/transactions_cache_test.exs | 95 ++++++++++++ apps/explorer/test/support/data_case.ex | 2 + apps/indexer/lib/indexer/block/fetcher.ex | 7 +- 11 files changed, 288 insertions(+), 8 deletions(-) create mode 100644 apps/explorer/lib/explorer/chain/transactions_cache.ex create mode 100644 apps/explorer/test/explorer/chain/transactions_cache_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 289f674be3..d56ddd37a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Current ### Features +- [#2283](https://github.com/poanetwork/blockscout/pull/2283) - Add transactions cache - [#2182](https://github.com/poanetwork/blockscout/pull/2182) - add market history cache - [#2109](https://github.com/poanetwork/blockscout/pull/2109) - use bigger updates instead of `Multi` transactions in BlocksTransactionsMismatch - [#2075](https://github.com/poanetwork/blockscout/pull/2075) - add blocks cache diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex index 4f66597bcb..b001093c6e 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex @@ -12,7 +12,7 @@ defmodule BlockScoutWeb.RecentTransactionsController do necessity_by_association: %{ :block => :required, [created_contract_address: :names] => :optional, - [from_address: :names] => :required, + [from_address: :names] => :optional, [to_address: :names] => :optional }, paging_options: %PagingOptions{page_size: 5} diff --git a/apps/block_scout_web/test/support/conn_case.ex b/apps/block_scout_web/test/support/conn_case.ex index 6c3f24d89a..d0b9b066a1 100644 --- a/apps/block_scout_web/test/support/conn_case.ex +++ b/apps/block_scout_web/test/support/conn_case.ex @@ -38,6 +38,9 @@ defmodule BlockScoutWeb.ConnCase do Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()}) end + Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()}) + Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()}) + {:ok, conn: Phoenix.ConnTest.build_conn()} end end diff --git a/apps/block_scout_web/test/support/feature_case.ex b/apps/block_scout_web/test/support/feature_case.ex index cf9d64cdc5..b9e6f000d7 100644 --- a/apps/block_scout_web/test/support/feature_case.ex +++ b/apps/block_scout_web/test/support/feature_case.ex @@ -27,6 +27,9 @@ defmodule BlockScoutWeb.FeatureCase do Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()}) end + Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()}) + Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()}) + metadata = Phoenix.Ecto.SQL.Sandbox.metadata_for(Explorer.Repo, self()) {:ok, session} = Wallaby.start_session(metadata: metadata) session = Wallaby.Browser.resize_window(session, 1200, 800) diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index 724e4f41a1..bb1108f17d 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -6,7 +6,16 @@ defmodule Explorer.Application do use Application alias Explorer.Admin - alias Explorer.Chain.{BlockCountCache, BlockNumberCache, BlocksCache, NetVersionCache, TransactionCountCache} + + alias Explorer.Chain.{ + BlockCountCache, + BlockNumberCache, + BlocksCache, + NetVersionCache, + TransactionCountCache, + TransactionsCache + } + alias Explorer.Market.MarketHistoryCache alias Explorer.Repo.PrometheusLogger @@ -34,7 +43,8 @@ defmodule Explorer.Application do {BlockCountCache, []}, con_cache_child_spec(BlocksCache.cache_name()), con_cache_child_spec(NetVersionCache.cache_name()), - con_cache_child_spec(MarketHistoryCache.cache_name()) + con_cache_child_spec(MarketHistoryCache.cache_name()), + con_cache_child_spec(TransactionsCache.cache_name()) ] children = base_children ++ configurable_children() diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index c6fe89ab49..62ff70afb8 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -46,6 +46,7 @@ defmodule Explorer.Chain do TokenTransfer, Transaction, TransactionCountCache, + TransactionsCache, Wei } @@ -1948,9 +1949,27 @@ defmodule Explorer.Chain do @spec recent_collated_transactions([paging_options | necessity_by_association_option]) :: [Transaction.t()] def recent_collated_transactions(options \\ []) when is_list(options) do necessity_by_association = Keyword.get(options, :necessity_by_association, %{}) + paging_options = Keyword.get(options, :paging_options, @default_paging_options) - options - |> Keyword.get(:paging_options, @default_paging_options) + if is_nil(paging_options.key) do + paging_options.page_size + |> TransactionsCache.take_enough() + |> case do + nil -> + transactions = fetch_recent_collated_transactions(paging_options, necessity_by_association) + TransactionsCache.update(transactions) + transactions + + transactions -> + transactions + end + else + fetch_recent_collated_transactions(paging_options, necessity_by_association) + end + end + + def fetch_recent_collated_transactions(paging_options, necessity_by_association) do + paging_options |> fetch_transactions() |> where([transaction], not is_nil(transaction.block_number) and not is_nil(transaction.index)) |> join_associations(necessity_by_association) diff --git a/apps/explorer/lib/explorer/chain/import/runner/transactions.ex b/apps/explorer/lib/explorer/chain/import/runner/transactions.ex index 1a9fcc497d..2c36d7c7e5 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/transactions.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/transactions.ex @@ -90,8 +90,7 @@ defmodule Explorer.Chain.Import.Runner.Transactions do conflict_target: :hash, on_conflict: on_conflict, for: Transaction, - returning: - ~w(block_number index hash internal_transactions_indexed_at block_hash old_block_hash nonce from_address_hash created_contract_address_hash)a, + returning: true, timeout: timeout, timestamps: timestamps ) diff --git a/apps/explorer/lib/explorer/chain/transactions_cache.ex b/apps/explorer/lib/explorer/chain/transactions_cache.ex new file mode 100644 index 0000000000..3859561295 --- /dev/null +++ b/apps/explorer/lib/explorer/chain/transactions_cache.ex @@ -0,0 +1,143 @@ +defmodule Explorer.Chain.TransactionsCache do + @moduledoc """ + Caches the latest imported transactions + """ + + alias Explorer.Chain.Transaction + alias Explorer.Repo + + @transactions_ids_key "transactions_ids" + @cache_name :transactions + @max_size 51 + @preloads [ + :block, + created_contract_address: :names, + from_address: :names, + to_address: :names, + token_transfers: :token, + token_transfers: :from_address, + token_transfers: :to_address + ] + + @spec cache_name :: atom() + def cache_name, do: @cache_name + + @doc """ + Fetches a transaction from its id ({block_number, index}), returns nil if not found + """ + @spec get({non_neg_integer(), non_neg_integer()}) :: Transaction.t() | nil + def get(id), do: ConCache.get(@cache_name, id) + + @doc """ + Return the current number of transactions stored + """ + @spec size :: non_neg_integer() + def size, do: Enum.count(transactions_ids()) + + @doc """ + Checks if there are enough transactions stored + """ + @spec enough?(non_neg_integer()) :: boolean() + def enough?(amount) do + amount <= size() + end + + @doc """ + Checks if the number of transactions stored is already the max allowed + """ + @spec full? :: boolean() + def full? do + @max_size <= size() + end + + @doc "Returns the list ids of the transactions currently stored" + @spec transactions_ids :: [{non_neg_integer(), non_neg_integer()}] + def transactions_ids do + ConCache.get(@cache_name, @transactions_ids_key) || [] + end + + @doc "Returns all the stored transactions" + @spec all :: [Transaction.t()] + def all, do: Enum.map(transactions_ids(), &get(&1)) + + @doc "Returns the `n` most recent transactions stored" + @spec take(integer()) :: [Transaction.t()] + def take(amount) do + transactions_ids() + |> Enum.take(amount) + |> Enum.map(&get(&1)) + end + + @doc """ + Returns the `n` most recent transactions, unless there are not as many stored, + in which case returns `nil` + """ + @spec take_enough(integer()) :: [Transaction.t()] | nil + def take_enough(amount) do + if enough?(amount), do: take(amount) + end + + @doc """ + Adds a transaction (or a list of transactions). + If the cache is already full, the transaction will be only stored if it can take + the place of a less recent one. + NOTE: each transaction is inserted atomically + """ + @spec update([Transaction.t()] | Transaction.t() | nil) :: :ok + def update(transactions) when is_nil(transactions), do: :ok + + def update(transactions) when is_list(transactions) do + Enum.map(transactions, &update(&1)) + end + + def update(transaction) do + ConCache.isolated(@cache_name, @transactions_ids_key, fn -> + transaction_id = {transaction.block_number, transaction.index} + ids = transactions_ids() + + if full?() do + {init, [min]} = Enum.split(ids, -1) + + cond do + transaction_id < min -> + :ok + + transaction_id > min -> + insert_transaction(transaction_id, transaction, init) + ConCache.delete(@cache_name, min) + + transaction_id == min -> + put_transaction(transaction_id, transaction) + end + else + insert_transaction(transaction_id, transaction, ids) + end + end) + end + + defp insert_transaction(transaction_id, transaction, ids) do + put_transaction(transaction_id, transaction) + + ConCache.put(@cache_name, @transactions_ids_key, insert_sorted(transaction_id, ids)) + end + + defp put_transaction(transaction_id, transaction) do + full_transaction = Repo.preload(transaction, @preloads) + + ConCache.put(@cache_name, transaction_id, full_transaction) + end + + defp insert_sorted(id, ids) do + case ids do + [] -> + [id] + + [head | tail] -> + cond do + head > id -> [head | insert_sorted(id, tail)] + head < id -> [id | ids] + head == id -> ids + end + end + end +end diff --git a/apps/explorer/test/explorer/chain/transactions_cache_test.exs b/apps/explorer/test/explorer/chain/transactions_cache_test.exs new file mode 100644 index 0000000000..a72055c276 --- /dev/null +++ b/apps/explorer/test/explorer/chain/transactions_cache_test.exs @@ -0,0 +1,95 @@ +defmodule Explorer.Chain.TransactionsCacheTest do + use Explorer.DataCase + + alias Explorer.Chain.TransactionsCache + alias Explorer.Repo + + @size 51 + + describe "update/1" do + test "adds a new value to a new cache with preloads" do + transaction = insert(:transaction) |> preload_all() + + TransactionsCache.update(transaction) + + assert TransactionsCache.take(1) == [transaction] + end + + test "adds several elements, removing the oldest when necessary" do + transactions = + 1..@size + |> Enum.map(fn n -> + block = insert(:block, number: n) + insert(:transaction) |> with_block(block) + end) + + TransactionsCache.update(transactions) + + assert TransactionsCache.all() == Enum.reverse(preload_all(transactions)) + + more_transactions = + (@size + 1)..(@size + 10) + |> Enum.map(fn n -> + block = insert(:block, number: n) + insert(:transaction) |> with_block(block) + end) + + TransactionsCache.update(more_transactions) + + kept_transactions = + Enum.reverse(transactions ++ more_transactions) + |> Enum.take(@size) + |> preload_all() + + assert TransactionsCache.take(@size) == kept_transactions + end + + test "does not add a transaction too old when full" do + transactions = + 10..(@size + 9) + |> Enum.map(fn n -> + block = insert(:block, number: n) + insert(:transaction) |> with_block(block) + end) + + TransactionsCache.update(transactions) + + loaded_transactions = Enum.reverse(preload_all(transactions)) + assert TransactionsCache.all() == loaded_transactions + + block = insert(:block, number: 1) + insert(:transaction) |> with_block(block) |> TransactionsCache.update() + + assert TransactionsCache.all() == loaded_transactions + end + + test "adds intermediate transactions" do + blocks = 1..10 |> Map.new(fn n -> {n, insert(:block, number: n)} end) + + insert(:transaction) |> with_block(blocks[1]) |> TransactionsCache.update() + insert(:transaction) |> with_block(blocks[10]) |> TransactionsCache.update() + + assert TransactionsCache.size() == 2 + + insert(:transaction) |> with_block(blocks[5]) |> TransactionsCache.update() + + assert TransactionsCache.size() == 3 + end + end + + defp preload_all(transactions) when is_list(transactions) do + Enum.map(transactions, &preload_all(&1)) + end + + defp preload_all(transaction) do + Repo.preload(transaction, [ + :block, + created_contract_address: :names, + from_address: :names, + to_address: :names, + token_transfers: :token, + token_transfers: :from_address, + token_transfers: :to_address + ]) + end +end diff --git a/apps/explorer/test/support/data_case.ex b/apps/explorer/test/support/data_case.ex index c201932cef..2ec7cde365 100644 --- a/apps/explorer/test/support/data_case.ex +++ b/apps/explorer/test/support/data_case.ex @@ -42,6 +42,8 @@ defmodule Explorer.DataCase do Explorer.Chain.BlockNumberCache.setup() Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()}) Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.BlocksCache.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()}) + Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.TransactionsCache.cache_name()}) :ok end diff --git a/apps/indexer/lib/indexer/block/fetcher.ex b/apps/indexer/lib/indexer/block/fetcher.ex index 4d4cd978ec..b436d61e03 100644 --- a/apps/indexer/lib/indexer/block/fetcher.ex +++ b/apps/indexer/lib/indexer/block/fetcher.ex @@ -11,7 +11,7 @@ defmodule Indexer.Block.Fetcher do alias EthereumJSONRPC.{Blocks, FetchedBeneficiaries} alias Explorer.Chain - alias Explorer.Chain.{Address, Block, BlockNumberCache, BlocksCache, Hash, Import, Transaction} + alias Explorer.Chain.{Address, Block, BlockNumberCache, BlocksCache, Hash, Import, Transaction, TransactionsCache} alias Indexer.Block.Fetcher.Receipts alias Indexer.Fetcher.{ @@ -173,6 +173,7 @@ defmodule Indexer.Block.Fetcher do ) do result = {:ok, %{inserted: inserted, errors: blocks_errors}} update_block_cache(inserted[:blocks]) + update_transactions_cache(inserted[:transactions]) result else {step, {:error, reason}} -> {:error, {step, reason}} @@ -189,6 +190,10 @@ defmodule Indexer.Block.Fetcher do BlocksCache.update_blocks(blocks) end + defp update_transactions_cache(transactions) do + TransactionsCache.update(transactions) + end + def import( %__MODULE__{broadcast: broadcast, callback_module: callback_module} = state, options From 247a22dbdde207a20b45bdc4794aaef73d4c616c Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 3 Jul 2019 13:11:53 +0300 Subject: [PATCH 18/52] mix format --- apps/explorer/lib/explorer/application.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index d87ce09854..5a6aa1795b 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -15,8 +15,8 @@ defmodule Explorer.Application do TransactionCountCache, TransactionsCache } - alias Explorer.Chain.Supply.RSK + alias Explorer.Chain.Supply.RSK alias Explorer.Market.MarketHistoryCache alias Explorer.Repo.PrometheusLogger From 60e9309f1e0952e6144fb33ac36be0468ece1955 Mon Sep 17 00:00:00 2001 From: maxgrapps Date: Wed, 3 Jul 2019 13:14:09 +0300 Subject: [PATCH 19/52] banner stats issues on sm resolutions, transactions title issue --- .../assets/css/components/_card.scss | 6 ++++ .../css/components/_dashboard-banner.scss | 29 ++++++++++++++++++- .../templates/chain/show.html.eex | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/_card.scss b/apps/block_scout_web/assets/css/components/_card.scss index 6e50100f0d..63a8f4a852 100644 --- a/apps/block_scout_web/assets/css/components/_card.scss +++ b/apps/block_scout_web/assets/css/components/_card.scss @@ -42,6 +42,12 @@ $card-tab-icon-color-active: #20b760 !default; line-height: 1.2rem; margin-bottom: 2rem; + &.lg-card-title { + @media (max-width: 374px) { + font-size: 13px; + } + } + &.margin-bottom-md { margin-bottom: 25px; } diff --git a/apps/block_scout_web/assets/css/components/_dashboard-banner.scss b/apps/block_scout_web/assets/css/components/_dashboard-banner.scss index ade21afea5..ecde4e882b 100644 --- a/apps/block_scout_web/assets/css/components/_dashboard-banner.scss +++ b/apps/block_scout_web/assets/css/components/_dashboard-banner.scss @@ -80,6 +80,12 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa flex-direction: row; } + @media (max-width: 599px) { + padding-top: 0; + padding-bottom: 0; + flex-direction: column; + } + &::before { border-radius: 2px; content: ""; @@ -107,6 +113,11 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa line-height: 1.2; margin: 0 0 5px; + @media (max-width: 374px) { + position: relative; + top: -2px; + } + @include media-breakpoint-down(md) { margin: 0 5px 0 0; } @@ -140,13 +151,16 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa height: auto; justify-content: flex-start; margin-left: 0; - margin-top: 15px; max-width: 100%; padding: 20px 0 20px 20px; width: 250px; box-shadow: 0 0 35px 0 rgba(0, 0, 0, 0.2); } + @include media-breakpoint-down(lg) { + margin-top: 15px; + } + @include media-breakpoint-down(sm) { width: 100%; } @@ -186,4 +200,17 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa } @include stats-item($dashboard-stats-item-border-color, $dashboard-stats-item-label-color, $dashboard-stats-item-value-color); + + .dashboard-banner-network-stats-item { + @media (max-width: 374px) { + padding-left: calc(0.6rem + 4px); + padding-right: 0.5rem; + } + } + + .dashboard-banner-network-stats-value { + @media (max-width: 374px) { + font-size: 0.9rem; + } + } } \ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex index 17bd9c4afe..0c29001697 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex @@ -105,7 +105,7 @@
<%= link(gettext("View All Transactions"), to: transaction_path(BlockScoutWeb.Endpoint, :index), class: "btn-line float-right") %> -

<%= gettext "Transactions" %>

+

<%= gettext "Transactions" %>

<%= gettext "More transactions have come in" %> From f91351dbc9bc6962c3bb117f411a52e3b7035271 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Wed, 3 Jul 2019 13:18:19 +0300 Subject: [PATCH 20/52] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d56ddd37a9..26c4fff461 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - [#2266](https://github.com/poanetwork/blockscout/pull/2266) - allow excluding uncles from average block time calculation ### Fixes +- [#2286](https://github.com/poanetwork/blockscout/pull/2286) - banner stats issues on sm resolutions, transactions title issue - [#2284](https://github.com/poanetwork/blockscout/pull/2284) - add 404 status for not existing pages - [#2244](https://github.com/poanetwork/blockscout/pull/2244) - fix internal transactions failing to be indexed because of constraint - [#2281](https://github.com/poanetwork/blockscout/pull/2281) - typo issues, dropdown issues From 23d6b2aa103780bc1bccf251d71b2c6b1405e566 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 3 Jul 2019 16:06:19 +0300 Subject: [PATCH 21/52] Update CHANGELOG.md Bump version --- CHANGELOG.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e15b08af0c..ede02ddea1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,14 @@ ## Current + +### Features + +### Fixes + +### Chore + + +## 2.0.1-beta + ### Features - [#2283](https://github.com/poanetwork/blockscout/pull/2283) - Add transactions cache - [#2182](https://github.com/poanetwork/blockscout/pull/2182) - add market history cache @@ -81,8 +91,6 @@ - [#2118](https://github.com/poanetwork/blockscout/pull/2118) - show only the last decompiled contract - [#2256](https://github.com/poanetwork/blockscout/pull/2256) - use the latest version of chromedriver -### Chore - ## 2.0.0-beta ### Features From 0bb7685cae81d5c74af8fc662e96338897e37f70 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 3 Jul 2019 17:55:55 +0300 Subject: [PATCH 22/52] Optional websockets for dev environment --- apps/indexer/config/dev/geth.exs | 2 +- apps/indexer/config/dev/parity.exs | 2 +- apps/indexer/config/dev/rsk.exs | 2 +- apps/indexer/config/prod/geth.exs | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/indexer/config/dev/geth.exs b/apps/indexer/config/dev/geth.exs index cf1113119d..b6ff92888c 100644 --- a/apps/indexer/config/dev/geth.exs +++ b/apps/indexer/config/dev/geth.exs @@ -14,7 +14,7 @@ config :indexer, subscribe_named_arguments: [ transport: EthereumJSONRPC.WebSocket, transport_options: [ - web_socket: EthereumJSONRPC.WebSocket.WebSocketClient, + web_socket: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || EthereumJSONRPC.WebSocket.WebSocketClient, url: System.get_env("ETHEREUM_JSONRPC_WS_URL") || "wss://mainnet.infura.io/ws/8lTvJTKmHPCHazkneJsY" ] ] diff --git a/apps/indexer/config/dev/parity.exs b/apps/indexer/config/dev/parity.exs index d6e300f077..7a5b31a424 100644 --- a/apps/indexer/config/dev/parity.exs +++ b/apps/indexer/config/dev/parity.exs @@ -34,7 +34,7 @@ config :indexer, # ] # ], subscribe_named_arguments: [ - transport: EthereumJSONRPC.WebSocket, + transport: System.get_env("ETHEREUM_JSONRPC_WS_URL") && EthereumJSONRPC.WebSocket, transport_options: [ web_socket: EthereumJSONRPC.WebSocket.WebSocketClient, url: System.get_env("ETHEREUM_JSONRPC_WS_URL") || "ws://localhost:8546" diff --git a/apps/indexer/config/dev/rsk.exs b/apps/indexer/config/dev/rsk.exs index 21138634f5..3f7399e892 100644 --- a/apps/indexer/config/dev/rsk.exs +++ b/apps/indexer/config/dev/rsk.exs @@ -19,7 +19,7 @@ config :indexer, variant: EthereumJSONRPC.RSK ], subscribe_named_arguments: [ - transport: EthereumJSONRPC.WebSocket, + transport: System.get_env("ETHEREUM_JSONRPC_WS_URL") && EthereumJSONRPC.WebSocket, transport_options: [ web_socket: EthereumJSONRPC.WebSocket.WebSocketClient, url: System.get_env("ETHEREUM_JSONRPC_WS_URL") || "ws://localhost:8546" diff --git a/apps/indexer/config/prod/geth.exs b/apps/indexer/config/prod/geth.exs index 859d94319c..7493135e29 100644 --- a/apps/indexer/config/prod/geth.exs +++ b/apps/indexer/config/prod/geth.exs @@ -6,7 +6,7 @@ config :indexer, transport: EthereumJSONRPC.HTTP, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, - url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY", + url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL"), http_options: [recv_timeout: :timer.minutes(10), timeout: :timer.minutes(10), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Geth @@ -14,7 +14,7 @@ config :indexer, subscribe_named_arguments: [ transport: EthereumJSONRPC.WebSocket, transport_options: [ - web_socket: EthereumJSONRPC.WebSocket.WebSocketClient, - url: System.get_env("ETHEREUM_JSONRPC_WS_URL") || "wss://mainnet.infura.io/ws/8lTvJTKmHPCHazkneJsY" + web_socket: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || EthereumJSONRPC.WebSocket.WebSocketClient, + url: System.get_env("ETHEREUM_JSONRPC_WS_URL") ] ] From 165ee31da968e51cf6ffe37b49dc4017910eff4d Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 3 Jul 2019 18:01:57 +0300 Subject: [PATCH 23/52] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ede02ddea1..f97a44fa02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixes ### Chore +- [#2289](https://github.com/poanetwork/blockscout/pull/2289) - Optional websockets for dev environment ## 2.0.1-beta From f7fc61c868021a10ce88c7fb5fd7d233de477251 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 3 Jul 2019 18:12:51 +0300 Subject: [PATCH 24/52] Revoke changes for Geth --- apps/indexer/config/dev/geth.exs | 2 +- apps/indexer/config/prod/geth.exs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/indexer/config/dev/geth.exs b/apps/indexer/config/dev/geth.exs index b6ff92888c..cf1113119d 100644 --- a/apps/indexer/config/dev/geth.exs +++ b/apps/indexer/config/dev/geth.exs @@ -14,7 +14,7 @@ config :indexer, subscribe_named_arguments: [ transport: EthereumJSONRPC.WebSocket, transport_options: [ - web_socket: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || EthereumJSONRPC.WebSocket.WebSocketClient, + web_socket: EthereumJSONRPC.WebSocket.WebSocketClient, url: System.get_env("ETHEREUM_JSONRPC_WS_URL") || "wss://mainnet.infura.io/ws/8lTvJTKmHPCHazkneJsY" ] ] diff --git a/apps/indexer/config/prod/geth.exs b/apps/indexer/config/prod/geth.exs index 7493135e29..859d94319c 100644 --- a/apps/indexer/config/prod/geth.exs +++ b/apps/indexer/config/prod/geth.exs @@ -6,7 +6,7 @@ config :indexer, transport: EthereumJSONRPC.HTTP, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, - url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL"), + url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY", http_options: [recv_timeout: :timer.minutes(10), timeout: :timer.minutes(10), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Geth @@ -14,7 +14,7 @@ config :indexer, subscribe_named_arguments: [ transport: EthereumJSONRPC.WebSocket, transport_options: [ - web_socket: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || EthereumJSONRPC.WebSocket.WebSocketClient, - url: System.get_env("ETHEREUM_JSONRPC_WS_URL") + web_socket: EthereumJSONRPC.WebSocket.WebSocketClient, + url: System.get_env("ETHEREUM_JSONRPC_WS_URL") || "wss://mainnet.infura.io/ws/8lTvJTKmHPCHazkneJsY" ] ] From 7e38684d2a40846516e4701b35178d3530d2d1e1 Mon Sep 17 00:00:00 2001 From: pasqu4le Date: Wed, 3 Jul 2019 17:46:29 +0200 Subject: [PATCH 25/52] Add eth_get_balance.json to AddressView render Problem: the eth_get_balance endpoint fails returning a 500 error when the URL is correct. Solution: turns out a clause for render eth_get_balance.json went missing (probably during a rebase) and so it was enough to rewrite it. --- CHANGELOG.md | 1 + .../lib/block_scout_web/views/api/rpc/address_view.ex | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59f05eab72..ec2b1c0fdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - [#2266](https://github.com/poanetwork/blockscout/pull/2266) - allow excluding uncles from average block time calculation ### Fixes +- [#2290](https://github.com/poanetwork/blockscout/pull/2290) - Add eth_get_balance.json to AddressView's render - [#2284](https://github.com/poanetwork/blockscout/pull/2284) - add 404 status for not existing pages - [#2244](https://github.com/poanetwork/blockscout/pull/2244) - fix internal transactions failing to be indexed because of constraint - [#2281](https://github.com/poanetwork/blockscout/pull/2281) - typo issues, dropdown issues diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/rpc/address_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/rpc/address_view.ex index 248dc942c7..01f54dd46d 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/api/rpc/address_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/api/rpc/address_view.ex @@ -51,6 +51,10 @@ defmodule BlockScoutWeb.API.RPC.AddressView do RPCView.render("show.json", data: data) end + def render("eth_get_balance.json", %{balance: balance}) do + EthRPCView.render("show.json", %{result: balance, id: 0}) + end + def render("eth_get_balance_error.json", %{error: message}) do EthRPCView.render("error.json", %{error: message, id: 0}) end From 55ef11254d4f7ab0bb93962b592cba8a0dd088ad Mon Sep 17 00:00:00 2001 From: maxgrapps Date: Wed, 3 Jul 2019 19:35:47 +0300 Subject: [PATCH 26/52] dashboard fix for md resolution, transactions load fix --- .../css/components/_dashboard-banner.scss | 14 +++++++++---- .../assets/css/components/_tile.scss | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/_dashboard-banner.scss b/apps/block_scout_web/assets/css/components/_dashboard-banner.scss index ecde4e882b..33d104a9fd 100644 --- a/apps/block_scout_web/assets/css/components/_dashboard-banner.scss +++ b/apps/block_scout_web/assets/css/components/_dashboard-banner.scss @@ -146,6 +146,11 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa width: 750px; position: relative; + @include media-breakpoint-down(lg) { + margin-top: 15px; + width: 550px; + } + @include media-breakpoint-down(md) { border-top-right-radius: 10px; height: auto; @@ -157,10 +162,6 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa box-shadow: 0 0 35px 0 rgba(0, 0, 0, 0.2); } - @include media-breakpoint-down(lg) { - margin-top: 15px; - } - @include media-breakpoint-down(sm) { width: 100%; } @@ -189,6 +190,11 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; + @include media-breakpoint-down(lg) { + grid-template-columns: 1fr 1fr; + row-gap: 20px; + } + @include media-breakpoint-down(md) { grid-template-columns: 1fr; row-gap: 20px; diff --git a/apps/block_scout_web/assets/css/components/_tile.scss b/apps/block_scout_web/assets/css/components/_tile.scss index 68b873334c..8965715727 100644 --- a/apps/block_scout_web/assets/css/components/_tile.scss +++ b/apps/block_scout_web/assets/css/components/_tile.scss @@ -272,6 +272,7 @@ $tile-body-a-color: #5959d8 !default; } &.tile-type-block { + max-width: 100%; .tile-title { font-weight: 700; line-height: 1.2; @@ -330,3 +331,23 @@ $tile-body-a-color: #5959d8 !default; } } } + +.card-chain-blocks { + .card-body { + .col-lg-3 { + @include media-breakpoint-down(lg) { + padding-left: 6px; + padding-right: 6px; + } + .tile-type-block { + overflow: hidden; + } + } + .row { + @include media-breakpoint-down(lg) { + margin-left: -6px; + margin-right: -6px; + } + } + } +} From 356d152513688a200decd3f0e2bb6f62c3733650 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Wed, 3 Jul 2019 19:38:15 +0300 Subject: [PATCH 27/52] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ede02ddea1..e205646d4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - [#2266](https://github.com/poanetwork/blockscout/pull/2266) - allow excluding uncles from average block time calculation ### Fixes +- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix - [#2286](https://github.com/poanetwork/blockscout/pull/2286) - banner stats issues on sm resolutions, transactions title issue - [#2284](https://github.com/poanetwork/blockscout/pull/2284) - add 404 status for not existing pages - [#2244](https://github.com/poanetwork/blockscout/pull/2244) - fix internal transactions failing to be indexed because of constraint From b0c351f22d5f99ae7d6f31e5102800e780ca09f7 Mon Sep 17 00:00:00 2001 From: maxgrapps Date: Thu, 4 Jul 2019 12:10:14 +0300 Subject: [PATCH 28/52] block details row fix --- .../assets/css/components/_card.scss | 15 +++++++++++++++ .../templates/block/overview.html.eex | 8 ++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/_card.scss b/apps/block_scout_web/assets/css/components/_card.scss index 63a8f4a852..6ae655fcf9 100644 --- a/apps/block_scout_web/assets/css/components/_card.scss +++ b/apps/block_scout_web/assets/css/components/_card.scss @@ -14,6 +14,21 @@ $card-tab-icon-color-active: #20b760 !default; border: none; box-shadow: 0 0 30px 0 rgba(202, 199, 226, 0.5); margin-bottom: $common-container-margin; + + .block-details-row { + flex-direction: row; + @include media-breakpoint-down(sm) { + flex-direction: column; + } + + .block-detail-el { + & + .block-detail-el { + @include media-breakpoint-down(sm) { + margin-top: 6px; + } + } + } + } } .card-background-1 { diff --git a/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex index 23985be4f6..24b2d9e61a 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex @@ -16,17 +16,17 @@ <%= link(@block, to: block_path(BlockScoutWeb.Endpoint, :show, @block.number)) %> <% end %> -
+
- <%= gettext "%{count} Transactions", count: @block_transaction_count %> + <%= gettext "%{count} Transactions", count: @block_transaction_count %> <%= if @block.size do %> - <%= Cldr.Unit.new(:byte, @block.size) |> cldr_unit_to_string!() %> + <%= Cldr.Unit.new(:byte, @block.size) |> cldr_unit_to_string!() %> <% end %> - +

From 39f19401c38e1eed23686ada77c7f14e9102143c Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 12:11:52 +0300 Subject: [PATCH 29/52] add healthy block period checking query --- .../controllers/api/v1/health_controller.ex | 9 +++++++ apps/explorer/config/config.exs | 3 ++- apps/explorer/lib/explorer/chain.ex | 26 +++++++++++++++++++ apps/explorer/test/explorer/chain_test.exs | 18 +++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex new file mode 100644 index 0000000000..abacc3c67b --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex @@ -0,0 +1,9 @@ +defmodule BlockScoutWeb.API.V1.HealthController do + use BlockScoutWeb, :controller + + alias Explorer.Chain + + def last_block_status(conn, _) do + # Chain.last_block_status() + end +end diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index d834d23384..c63fe3e24c 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -14,7 +14,8 @@ config :explorer, System.get_env("ALLOWED_EVM_VERSIONS") || "homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg", include_uncles_in_average_block_time: - if(System.get_env("UNCLES_IN_AVERAGE_BLOCK_TIME") == "false", do: false, else: true) + if(System.get_env("UNCLES_IN_AVERAGE_BLOCK_TIME") == "false", do: false, else: true), + healthy_blocks_period: System.get_env("HEALTHY_BLOCKS_PERIOD") || :timer.minutes(5) config :explorer, Explorer.Counters.AverageBlockTime, enabled: true diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 62ff70afb8..d2d53046e2 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1769,6 +1769,32 @@ defmodule Explorer.Chain do Repo.one!(query) end + @spec last_block_status() :: {:ok, non_neg_integer()} | {:error, non_neg_integer | nil} + def last_block_status do + query = + from(block in Block, + select: {block.number, block.timestamp}, + where: block.consensus == true, + order_by: [desc: block.number], + limit: 1 + ) + + case Repo.one(query) do + nil -> + {:error, :no_blocks} + + {_number, timestamp} -> + now = DateTime.utc_now() + last_block_period = DateTime.diff(now, timestamp, :millisecond) + + if last_block_period > Application.get_env(:explorer, :healthy_blocks_period) do + {:error, last_block_period} + else + {:ok, last_block_period} + end + end + end + @doc """ Calculates the ranges of missing consensus blocks in `range`. diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 91a4bff8db..2e28d9d269 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -50,6 +50,24 @@ defmodule Explorer.ChainTest do end end + describe "last_block_status/0" do + test "return no_blocks errors if db is empty" do + assert {:error, :no_blocks} = Chain.last_block_status() + end + + test "returns {:ok, last_block_period} if block is in healthy period" do + insert(:block, consensus: true) + + assert {:ok, _} = Chain.last_block_status() + end + + test "return {:ok, last_block_period} if block is not in healthy period" do + insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50)) + + assert {:error, _} = Chain.last_block_status() + end + end + describe "address_to_logs/2" do test "fetches logs" do address = insert(:address) From d9d273ddf89d7d013e2d87eb5dadb54fc569f793 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 4 Jul 2019 12:13:59 +0300 Subject: [PATCH 30/52] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e205646d4a..834204deae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ - [#2266](https://github.com/poanetwork/blockscout/pull/2266) - allow excluding uncles from average block time calculation ### Fixes -- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix +- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix - [#2286](https://github.com/poanetwork/blockscout/pull/2286) - banner stats issues on sm resolutions, transactions title issue - [#2284](https://github.com/poanetwork/blockscout/pull/2284) - add 404 status for not existing pages - [#2244](https://github.com/poanetwork/blockscout/pull/2244) - fix internal transactions failing to be indexed because of constraint From 1dea7349e78458d2de22a39436dbc2a439bb8f1c Mon Sep 17 00:00:00 2001 From: maxgrapps Date: Thu, 4 Jul 2019 13:34:43 +0300 Subject: [PATCH 31/52] addresses tiles changes to table --- .../assets/css/components/_stakes_table.scss | 19 +++++ .../templates/address/_tile.html.eex | 84 ++++++++----------- .../templates/address/index.html.eex | 47 +++++++++-- apps/block_scout_web/priv/gettext/default.pot | 4 +- 4 files changed, 99 insertions(+), 55 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/_stakes_table.scss b/apps/block_scout_web/assets/css/components/_stakes_table.scss index 0bbf59e69c..79cdc20b38 100644 --- a/apps/block_scout_web/assets/css/components/_stakes_table.scss +++ b/apps/block_scout_web/assets/css/components/_stakes_table.scss @@ -7,6 +7,25 @@ $stakes-table-cell-separation: 25px !default; width: 100%; } +.addresses-table-container { + margin-left: -30px; + margin-right: -30px; + .stakes-table-container { + table { + width: 100%; + th:first-child { + padding-left: 25px; + } + td:first-child { + padding-left: 25px; + } + } + } + .color-lighten { + color: #828ba0; + } +} + .stakes-table { min-width: fit-content; width: 100%; diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex index c2e62e2004..9680faa2a8 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex @@ -1,51 +1,39 @@ -
-
- -
+ + - + <%= @index %> -
- -
-
-
- <%= @address |> BlockScoutWeb.AddressView.address_partial_selector(nil, nil) |> BlockScoutWeb.RenderHelpers.render_partial() %> - - - - <%= @tx_count %> - <%= gettext "Transactions sent" %> - <% if validator?(@address) do %> - - <%= @validation_count %> - <%= gettext "Validations" %> - <% end %> - -
- - -
- - <%= balance(@address) %> -
- - - data-usd-exchange-rate="<%= @exchange_rate.usd_value %>"> - <% end %> - - - - <%= if @total_supply do %> - (<%= balance_percentage(@address, @total_supply) %>) - <% end %> - -
-
-
-
-
-
+ + + <%= @address |> BlockScoutWeb.AddressView.address_partial_selector(nil, nil) |> BlockScoutWeb.RenderHelpers.render_partial() %> + + + <%= balance(@address) %> + + + data-usd-exchange-rate="<%= @exchange_rate.usd_value %>"> + <% end %> + + + + + <%= if @total_supply do %> + (<%= balance_percentage(@address, @total_supply) %>) + <% end %> + + + + + <%= @tx_count %> + <%= gettext "Transactions sent" %> + <% if validator?(@address) do %> + + <%= @validation_count %> + <%= gettext "Validations" %> + <% end %> + + + diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex index 47d7f2457b..3aaab46ad5 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex @@ -3,11 +3,48 @@

<%= gettext "Addresses" %>

- <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> - -
- - <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %> + +
+
+ + + + + + + + + + + + + +
+
+   +
+
+
+ Address +
+
+
+ Balance +
+
+
+ Percentage +
+
+
+ Txn Count +
+
+
+
+ + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index c263d8a6ce..41aa7bf553 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -877,7 +877,7 @@ msgid "Transactions" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/_tile.html.eex:19 +#: lib/block_scout_web/templates/address/_tile.html.eex:31 msgid "Transactions sent" msgstr "" @@ -923,7 +923,7 @@ msgid "Validated Transactions" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/_tile.html.eex:23 +#: lib/block_scout_web/templates/address/_tile.html.eex:35 msgid "Validations" msgstr "" From 7087e5b4d84a2a362b050e72ab471ffcae35e6be Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 4 Jul 2019 13:36:40 +0300 Subject: [PATCH 32/52] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 834204deae..8bc9536424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ - [#2266](https://github.com/poanetwork/blockscout/pull/2266) - allow excluding uncles from average block time calculation ### Fixes -- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix +- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue - [#2286](https://github.com/poanetwork/blockscout/pull/2286) - banner stats issues on sm resolutions, transactions title issue - [#2284](https://github.com/poanetwork/blockscout/pull/2284) - add 404 status for not existing pages - [#2244](https://github.com/poanetwork/blockscout/pull/2244) - fix internal transactions failing to be indexed because of constraint From 36b2eb001da8390ca0a2ad9b823e0a057e72acbb Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 13:39:50 +0300 Subject: [PATCH 33/52] add health endpoint --- .../controllers/api/v1/health_controller.ex | 43 +++++++++++++++- .../lib/block_scout_web/router.ex | 2 + .../api/v1/health_controller_test.exs | 50 +++++++++++++++++++ apps/explorer/lib/explorer/chain.ex | 6 +-- apps/explorer/test/explorer/chain_test.exs | 4 +- 5 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex index abacc3c67b..2abf592f3e 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex @@ -4,6 +4,47 @@ defmodule BlockScoutWeb.API.V1.HealthController do alias Explorer.Chain def last_block_status(conn, _) do - # Chain.last_block_status() + status = Chain.last_block_status() + + case status do + {:ok, _, _} -> send_resp(conn, :ok, result(status)) + _ -> send_resp(conn, :internal_server_error, result(status)) + end + end + + def result({:ok, number, timestamp}) do + %{ + "healthy" => true, + "data" => %{ + "latest_block_number" => to_string(number), + "latest_block_inserted_at" => to_string(timestamp) + } + } + |> Jason.encode!() + end + + def result({:error, number, timestamp}) do + %{ + "healthy" => false, + "error_code" => 5001, + "error_title" => "blocks fetching is stuck", + "error_description" => + "There are no new blocks in the DB for the last 5 mins. Check the healthiness of Ethereum archive node or the Blockscout DB instance", + "data" => %{ + "latest_block_number" => to_string(number), + "latest_block_inserted_at" => to_string(timestamp) + } + } + |> Jason.encode!() + end + + def result({:error, :no_blocks}) do + %{ + "healthy" => false, + "error_code" => 5002, + "error_title" => "no blocks in db", + "error_description" => "There are no blocks in the DB" + } + |> Jason.encode!() end end diff --git a/apps/block_scout_web/lib/block_scout_web/router.ex b/apps/block_scout_web/lib/block_scout_web/router.ex index 3a0b76b8ae..a535d81d00 100644 --- a/apps/block_scout_web/lib/block_scout_web/router.ex +++ b/apps/block_scout_web/lib/block_scout_web/router.ex @@ -23,6 +23,8 @@ defmodule BlockScoutWeb.Router do get("/supply", SupplyController, :supply) + get("/health/last_block_status", HealthController, :last_block_status) + resources("/decompiled_smart_contract", DecompiledSmartContractController, only: [:create]) resources("/verified_smart_contracts", VerifiedSmartContractController, only: [:create]) end diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs new file mode 100644 index 0000000000..8acab7cc52 --- /dev/null +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs @@ -0,0 +1,50 @@ +defmodule BlockScoutWeb.API.V1.HealthControllerTest do + use BlockScoutWeb.ConnCase + + describe "GET last_block_status/0" do + test "returns error when there are no blocks in db", %{conn: conn} do + request = get(conn, api_v1_health_path(conn, :last_block_status)) + + assert request.status == 500 + + assert request.resp_body == + "{\"error_code\":5002,\"error_description\":\"There are no blocks in the DB\",\"error_title\":\"no blocks in db\",\"healthy\":false}" + end + + test "returns error when last block is stale", %{conn: conn} do + insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50)) + + request = get(conn, api_v1_health_path(conn, :last_block_status)) + + assert request.status == 500 + + assert %{ + "healthy" => false, + "error_code" => 5001, + "error_title" => "blocks fetching is stuck", + "error_description" => + "There are no new blocks in the DB for the last 5 mins. Check the healthiness of Ethereum archive node or the Blockscout DB instance", + "data" => %{ + "latest_block_number" => _, + "latest_block_inserted_at" => _ + } + } = Poison.decode!(request.resp_body) + end + + test "returns ok when last block is not stale", %{conn: conn} do + insert(:block, consensus: true, timestamp: DateTime.utc_now()) + + request = get(conn, api_v1_health_path(conn, :last_block_status)) + + assert request.status == 200 + + assert %{ + "healthy" => true, + "data" => %{ + "latest_block_number" => _, + "latest_block_inserted_at" => _ + } + } = Poison.decode!(request.resp_body) + end + end +end diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index d2d53046e2..1b73d6edc7 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1783,14 +1783,14 @@ defmodule Explorer.Chain do nil -> {:error, :no_blocks} - {_number, timestamp} -> + {number, timestamp} -> now = DateTime.utc_now() last_block_period = DateTime.diff(now, timestamp, :millisecond) if last_block_period > Application.get_env(:explorer, :healthy_blocks_period) do - {:error, last_block_period} + {:error, number, timestamp} else - {:ok, last_block_period} + {:ok, number, timestamp} end end end diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 2e28d9d269..cfb8b5ab14 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -58,13 +58,13 @@ defmodule Explorer.ChainTest do test "returns {:ok, last_block_period} if block is in healthy period" do insert(:block, consensus: true) - assert {:ok, _} = Chain.last_block_status() + assert {:ok, _, _} = Chain.last_block_status() end test "return {:ok, last_block_period} if block is not in healthy period" do insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50)) - assert {:error, _} = Chain.last_block_status() + assert {:error, _, _} = Chain.last_block_status() end end From 64df8f03ac404d3f5a45da342208514ad767db82 Mon Sep 17 00:00:00 2001 From: maxgrapps Date: Thu, 4 Jul 2019 13:48:33 +0300 Subject: [PATCH 34/52] address overview card title size on sm resolutions --- .../lib/block_scout_web/templates/address/overview.html.eex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex index 76387a9662..e6178a4e72 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex @@ -4,7 +4,7 @@
-

+

<%= address_title(@address) %> <%= gettext "Details" %> From fd752eb92a57a797c83533dc91a645df4e6946d3 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 13:59:39 +0300 Subject: [PATCH 35/52] fix dialyzer --- .../controllers/api/v1/health_controller.ex | 23 ++++++++++--------- apps/explorer/lib/explorer/chain.ex | 1 - 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex index 2abf592f3e..d935d15012 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex @@ -8,7 +8,8 @@ defmodule BlockScoutWeb.API.V1.HealthController do case status do {:ok, _, _} -> send_resp(conn, :ok, result(status)) - _ -> send_resp(conn, :internal_server_error, result(status)) + {:error, _} -> send_resp(conn, :internal_server_error, result(status)) + {:error, _, _} -> send_resp(conn, :internal_server_error, result(status)) end end @@ -23,6 +24,16 @@ defmodule BlockScoutWeb.API.V1.HealthController do |> Jason.encode!() end + def result({:error, :no_blocks}) do + %{ + "healthy" => false, + "error_code" => 5002, + "error_title" => "no blocks in db", + "error_description" => "There are no blocks in the DB" + } + |> Jason.encode!() + end + def result({:error, number, timestamp}) do %{ "healthy" => false, @@ -37,14 +48,4 @@ defmodule BlockScoutWeb.API.V1.HealthController do } |> Jason.encode!() end - - def result({:error, :no_blocks}) do - %{ - "healthy" => false, - "error_code" => 5002, - "error_title" => "no blocks in db", - "error_description" => "There are no blocks in the DB" - } - |> Jason.encode!() - end end diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 1b73d6edc7..fcad694a58 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1769,7 +1769,6 @@ defmodule Explorer.Chain do Repo.one!(query) end - @spec last_block_status() :: {:ok, non_neg_integer()} | {:error, non_neg_integer | nil} def last_block_status do query = from(block in Block, From a5f44f292e2d59f24d80bec97b9a29652503e84b Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 14:01:17 +0300 Subject: [PATCH 36/52] add CHANGELOG entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ede02ddea1..8f52fd6dbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +[#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint + ### Fixes ### Chore From b4387c27013a6efe9a95d71c6a01ce4592b2a943 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 15:04:14 +0300 Subject: [PATCH 37/52] support chainId in integer format --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex | 4 +++- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex index 71994da56c..3e1188eef9 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex @@ -358,7 +358,9 @@ defmodule EthereumJSONRPC do String.to_integer(hexadecimal_digits, 16) end - def quantity_to_integer(string) do + def quantity_to_integer(integer) when is_integer(integer), do: integer + + def quantity_to_integer(string) when is_binary(string) do case Integer.parse(string) do {integer, ""} -> integer _ -> :error diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex index 4b8fdfb7f7..cf1a74954a 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipt.ex @@ -299,7 +299,6 @@ defmodule EthereumJSONRPC.Receipt do :ignore end - defp entry_to_elixir({key, value}) do {:error, {:unknown_key, %{key: key, value: value}}} end From 9bbec7b2cd72033032324892670ca365d6f8fd73 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Thu, 4 Jul 2019 15:14:45 +0300 Subject: [PATCH 38/52] Remove changes, that fixed on Nethermind side --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex | 3 --- apps/indexer/lib/indexer/transform/blocks.ex | 3 --- 2 files changed, 6 deletions(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex index c3c72c4fb8..1c52a6e6c9 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex @@ -441,9 +441,6 @@ defmodule EthereumJSONRPC.Block do {key, quantity_to_integer(quantity)} end - # we don't need transaction hashes because we fetch full transactions - defp entry_to_elixir({"transactionHashes" = key, _}), do: {key, nil} - # Size and totalDifficulty may be `nil` for uncle blocks defp entry_to_elixir({key, nil}) when key in ~w(size totalDifficulty) do {key, nil} diff --git a/apps/indexer/lib/indexer/transform/blocks.ex b/apps/indexer/lib/indexer/transform/blocks.ex index 8d506a413d..c55c9a9974 100644 --- a/apps/indexer/lib/indexer/transform/blocks.ex +++ b/apps/indexer/lib/indexer/transform/blocks.ex @@ -65,9 +65,6 @@ defmodule Indexer.Transform.Blocks do decode(rest) end - # specific to Nethermind - defp decode("0"), do: 0 - defp decode(data) do Base.decode16!(data, case: :mixed) end From f9d7b022c205859c63c234243a1050bafb3bfea9 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 16:21:41 +0300 Subject: [PATCH 39/52] fix CR issue --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex index f660da4ab4..0fd8804980 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex @@ -7,8 +7,6 @@ defmodule EthereumJSONRPC.HTTP do require Logger - import EthereumJSONRPC, only: [quantity_to_integer: 1] - @behaviour Transport @doc """ @@ -134,12 +132,7 @@ defmodule EthereumJSONRPC.HTTP do # validated, so we can indicate that with switch to atom keys. defp standardize_response(%{"jsonrpc" => "2.0" = jsonrpc, "id" => id} = unstandardized) do # Nethermind return string ids - id = - if is_binary(id) do - quantity_to_integer(id) - else - id - end + id = quantity_to_integer(id) standardized = %{jsonrpc: jsonrpc, id: id} From 072ce483e6e49fc5112e168005b31fdde2096b85 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 16:33:17 +0300 Subject: [PATCH 40/52] fix CR issues --- .../controllers/api/v1/health_controller.ex | 18 ++++++++---------- .../lib/block_scout_web/router.ex | 2 +- .../api/v1/health_controller_test.exs | 6 +++--- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex index d935d15012..957dc797be 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex @@ -3,17 +3,15 @@ defmodule BlockScoutWeb.API.V1.HealthController do alias Explorer.Chain - def last_block_status(conn, _) do - status = Chain.last_block_status() - - case status do - {:ok, _, _} -> send_resp(conn, :ok, result(status)) - {:error, _} -> send_resp(conn, :internal_server_error, result(status)) - {:error, _, _} -> send_resp(conn, :internal_server_error, result(status)) + def health(conn, _) do + with {:ok, number, timestamp} <- Chain.last_block_status() do + send_resp(conn, :ok, result(number, timestamp)) + else + status -> send_resp(conn, :internal_server_error, error(status)) end end - def result({:ok, number, timestamp}) do + def result(number, timestamp) do %{ "healthy" => true, "data" => %{ @@ -24,7 +22,7 @@ defmodule BlockScoutWeb.API.V1.HealthController do |> Jason.encode!() end - def result({:error, :no_blocks}) do + def error({:error, :no_blocks}) do %{ "healthy" => false, "error_code" => 5002, @@ -34,7 +32,7 @@ defmodule BlockScoutWeb.API.V1.HealthController do |> Jason.encode!() end - def result({:error, number, timestamp}) do + def error({:error, number, timestamp}) do %{ "healthy" => false, "error_code" => 5001, diff --git a/apps/block_scout_web/lib/block_scout_web/router.ex b/apps/block_scout_web/lib/block_scout_web/router.ex index a535d81d00..d13dc9c43e 100644 --- a/apps/block_scout_web/lib/block_scout_web/router.ex +++ b/apps/block_scout_web/lib/block_scout_web/router.ex @@ -23,7 +23,7 @@ defmodule BlockScoutWeb.Router do get("/supply", SupplyController, :supply) - get("/health/last_block_status", HealthController, :last_block_status) + get("/health", HealthController, :health) resources("/decompiled_smart_contract", DecompiledSmartContractController, only: [:create]) resources("/verified_smart_contracts", VerifiedSmartContractController, only: [:create]) diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs index 8acab7cc52..41735f685a 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs @@ -3,7 +3,7 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do describe "GET last_block_status/0" do test "returns error when there are no blocks in db", %{conn: conn} do - request = get(conn, api_v1_health_path(conn, :last_block_status)) + request = get(conn, api_v1_health_path(conn, :health)) assert request.status == 500 @@ -14,7 +14,7 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do test "returns error when last block is stale", %{conn: conn} do insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50)) - request = get(conn, api_v1_health_path(conn, :last_block_status)) + request = get(conn, api_v1_health_path(conn, :health)) assert request.status == 500 @@ -34,7 +34,7 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do test "returns ok when last block is not stale", %{conn: conn} do insert(:block, consensus: true, timestamp: DateTime.utc_now()) - request = get(conn, api_v1_health_path(conn, :last_block_status)) + request = get(conn, api_v1_health_path(conn, :health)) assert request.status == 200 From 209b1d68e9426a7bf6ddf9c7991e0e32e6cfa50e Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 16:37:43 +0300 Subject: [PATCH 41/52] fix build --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex index 0fd8804980..5c39243110 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex @@ -7,6 +7,8 @@ defmodule EthereumJSONRPC.HTTP do require Logger + import EthereumJSONRPC, only: [quantity_to_integer: 1] + @behaviour Transport @doc """ From d8647676722c0f9f3cd5ba1f1756a6824945804e Mon Sep 17 00:00:00 2001 From: maxgrapps Date: Thu, 4 Jul 2019 16:56:51 +0300 Subject: [PATCH 42/52] active tab chech mark issue --- apps/block_scout_web/assets/css/components/_card.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/css/components/_card.scss b/apps/block_scout_web/assets/css/components/_card.scss index 6ae655fcf9..0737e1b355 100644 --- a/apps/block_scout_web/assets/css/components/_card.scss +++ b/apps/block_scout_web/assets/css/components/_card.scss @@ -6,7 +6,7 @@ $card-vertical-padding: 30px; $card-background-1: $primary !default; $card-background-1-text-color: #fff !default; $card-tab-icon-color: #20b760 !default; -$card-tab-icon-color-active: #20b760 !default; +$card-tab-icon-color-active: #fff !default; .card { background-color: $card-background-color; From 55efa0a47a4f25afb85bbff13562c1d6e6ee76c0 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 4 Jul 2019 17:01:00 +0300 Subject: [PATCH 43/52] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7ca597775..2913d81255 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ - [#2266](https://github.com/poanetwork/blockscout/pull/2266) - allow excluding uncles from average block time calculation ### Fixes -- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue +- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue, check mark issue - [#2286](https://github.com/poanetwork/blockscout/pull/2286) - banner stats issues on sm resolutions, transactions title issue - [#2284](https://github.com/poanetwork/blockscout/pull/2284) - add 404 status for not existing pages - [#2244](https://github.com/poanetwork/blockscout/pull/2244) - fix internal transactions failing to be indexed because of constraint From 34ab07fcf7e54e99ddc992c8cd73259bdcbfa54f Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 4 Jul 2019 17:02:14 +0300 Subject: [PATCH 44/52] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2913d81255..7c84006016 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features ### Fixes +- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue, check mark issue ### Chore - [#2289](https://github.com/poanetwork/blockscout/pull/2289) - Optional websockets for dev environment @@ -25,7 +26,6 @@ - [#2266](https://github.com/poanetwork/blockscout/pull/2266) - allow excluding uncles from average block time calculation ### Fixes -- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue, check mark issue - [#2286](https://github.com/poanetwork/blockscout/pull/2286) - banner stats issues on sm resolutions, transactions title issue - [#2284](https://github.com/poanetwork/blockscout/pull/2284) - add 404 status for not existing pages - [#2244](https://github.com/poanetwork/blockscout/pull/2244) - fix internal transactions failing to be indexed because of constraint From 2c7c97b170f65e51a9248a3eb138ba56444ec86b Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 4 Jul 2019 20:32:36 +0300 Subject: [PATCH 45/52] fix interpolation in error message --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex index 5c39243110..6d9f946554 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex @@ -141,7 +141,9 @@ defmodule EthereumJSONRPC.HTTP do case unstandardized do %{"result" => _, "error" => _} -> raise ArgumentError, - "result and error keys are mutually exclusive in JSONRPC 2.0 response objects, but got #{unstandardized}" + "result and error keys are mutually exclusive in JSONRPC 2.0 response objects, but got #{ + inspect(unstandardized) + }" %{"result" => result} -> Map.put(standardized, :result, result) From 0b17f71ad7eeeca80e8c058badeae74239d5ff07 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 5 Jul 2019 13:28:46 +0300 Subject: [PATCH 46/52] fix name for xDai source --- apps/explorer/config/config.exs | 4 +- .../chain/supply/transaction_and_log.ex | 78 ----------- ...transaction_and_log.ex => token_bridge.ex} | 4 +- .../chain/supply/transaction_and_log_test.exs | 122 ------------------ ...and_log_test.exs => token_bridge_test.exs} | 6 +- docs/env-variables.md | 4 +- 6 files changed, 9 insertions(+), 209 deletions(-) delete mode 100644 apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex rename apps/explorer/lib/explorer/exchange_rates/source/{transaction_and_log.ex => token_bridge.ex} (90%) delete mode 100644 apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs rename apps/explorer/test/explorer/exchange_rates/source/{transaction_and_log_test.exs => token_bridge_test.exs} (78%) diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index d834d23384..88eb3b86de 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -84,8 +84,8 @@ case System.get_env("SUPPLY_MODULE") do :ok end -if System.get_env("SOURCE_MODULE") == "TransactionAndLog" do - config :explorer, Explorer.ExchangeRates.Source, source: Explorer.ExchangeRates.Source.TransactionAndLog +if System.get_env("SOURCE_MODULE") == "TokenBridge" do + config :explorer, Explorer.ExchangeRates.Source, source: Explorer.ExchangeRates.Source.TokenBridge end config :explorer, diff --git a/apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex b/apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex deleted file mode 100644 index 36432094fa..0000000000 --- a/apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex +++ /dev/null @@ -1,78 +0,0 @@ -defmodule Explorer.Chain.Supply.TransactionAndLog do - @moduledoc """ - Defines the supply API for calculating the supply for smaller chains with - specific mint and burn events - """ - use Explorer.Chain.Supply - - alias Explorer.Chain.{InternalTransaction, Log, Wei} - alias Explorer.{Chain, Repo} - - {:ok, base_wei} = Wei.cast(0) - @base_wei base_wei - - {:ok, burn_address} = Chain.string_to_address_hash("0x0000000000000000000000000000000000000000") - - @burn_address burn_address - @bridge_edge "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a" - - import Ecto.Query, only: [from: 2] - - def circulating, do: total(Timex.now()) - - def total, do: total(Timex.now()) - - @doc false - @spec total(DateTime.t()) :: %Decimal{sign: 1} - def total(on_date) do - on_date - |> minted_value - |> Wei.sub(burned_value(on_date)) - |> Wei.to(:ether) - end - - def supply_for_days(days_count) when is_integer(days_count) and days_count > 0 do - past_days = -(days_count - 1) - - result = - for i <- past_days..0, into: %{} do - datetime = Timex.shift(Timex.now(), days: i) - {DateTime.to_date(datetime), total(datetime)} - end - - {:ok, result} - end - - defp minted_value(on_date) do - query = - from( - l in Log, - join: t in assoc(l, :transaction), - join: b in assoc(t, :block), - where: b.timestamp <= ^on_date and l.first_topic == @bridge_edge, - select: fragment("concat('0x', encode(?, 'hex'))", l.data) - ) - - query - |> Repo.all() - |> Enum.reduce(@base_wei, fn data, acc -> - {:ok, wei_value} = Wei.cast(data) - Wei.sum(wei_value, acc) - end) - end - - defp burned_value(on_date) do - query = - from( - it in InternalTransaction, - join: t in assoc(it, :transaction), - join: b in assoc(t, :block), - where: b.timestamp <= ^on_date and it.to_address_hash == ^@burn_address, - select: it.value - ) - - query - |> Repo.all() - |> Enum.reduce(@base_wei, fn data, acc -> Wei.sum(data, acc) end) - end -end diff --git a/apps/explorer/lib/explorer/exchange_rates/source/transaction_and_log.ex b/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex similarity index 90% rename from apps/explorer/lib/explorer/exchange_rates/source/transaction_and_log.ex rename to apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex index 2b8699accc..03234ff649 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source/transaction_and_log.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex @@ -1,6 +1,6 @@ -defmodule Explorer.ExchangeRates.Source.TransactionAndLog do +defmodule Explorer.ExchangeRates.Source.TokenBridge do @moduledoc """ - Adapter for calculating the market cap and total supply from logs and transactions + Adapter for calculating the market cap and total supply from token bridge while still getting other info like price in dollars and bitcoin from a secondary source """ diff --git a/apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs b/apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs deleted file mode 100644 index 5126d7acaf..0000000000 --- a/apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs +++ /dev/null @@ -1,122 +0,0 @@ -defmodule Explorer.Chain.Supply.TransactionAndLogTest do - use Explorer.DataCase - alias Explorer.Chain - alias Explorer.Chain.Supply.TransactionAndLog - - setup do - {:ok, burn_address_hash} = Chain.string_to_address_hash("0x0000000000000000000000000000000000000000") - - burn_address = - case Chain.hash_to_address(burn_address_hash) do - {:ok, burn_address} -> burn_address - {:error, :not_found} -> insert(:address, hash: "0x0000000000000000000000000000000000000000") - end - - {:ok, %{burn_address: burn_address}} - end - - describe "total/1" do - test "today with no mints or burns brings zero" do - assert TransactionAndLog.total(Timex.now()) == Decimal.new(0) - end - - test "today with mints and burns calculates a value", %{burn_address: burn_address} do - old_block = insert(:block, timestamp: Timex.shift(Timex.now(), days: -1), number: 1000) - - insert(:log, - transaction: - insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 2), - first_topic: "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a", - data: "0x0000000000000000000000000000000000000000000000008ac7230489e80000" - ) - - insert(:internal_transaction, - index: 527, - transaction: - insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 3), - to_address: burn_address, - value: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ) - - assert TransactionAndLog.total(Timex.now()) == Decimal.new(9) - end - - test "yesterday with mints and burns calculates a value ignoring whatever happened today", %{ - burn_address: burn_address - } do - old_block = insert(:block, timestamp: Timex.shift(Timex.now(), days: -1), number: 1000) - - insert(:log, - transaction: - insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 2), - first_topic: "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a", - data: "0x0000000000000000000000000000000000000000000000008ac7230489e80000" - ) - - new_block = insert(:block, timestamp: Timex.now(), number: 1001) - - insert(:internal_transaction, - index: 527, - transaction: - insert(:transaction, block: new_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 3), - to_address: burn_address, - value: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ) - - assert TransactionAndLog.total(Timex.shift(Timex.now(), days: -1)) == Decimal.new(10) - end - end - - describe "total/0" do - test "calculates the same value as total/1 receiving today's date", %{burn_address: burn_address} do - old_block = insert(:block, timestamp: Timex.shift(Timex.now(), days: -1), number: 1000) - - insert(:log, - transaction: - insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 2), - first_topic: "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a", - data: "0x0000000000000000000000000000000000000000000000008ac7230489e80000" - ) - - insert(:internal_transaction, - index: 527, - transaction: - insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 3), - to_address: burn_address, - value: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ) - - assert TransactionAndLog.total() == TransactionAndLog.total(Timex.now()) - end - end - - describe "supply_for_days/1" do - test "bring the supply of today and yesterday when receiving 2", %{burn_address: burn_address} do - old_block = insert(:block, timestamp: Timex.shift(Timex.now(), days: -1), number: 1000) - - insert(:log, - transaction: - insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 2), - first_topic: "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a", - data: "0x0000000000000000000000000000000000000000000000008ac7230489e80000" - ) - - new_block = insert(:block, timestamp: Timex.now(), number: 1001) - - insert(:internal_transaction, - index: 527, - transaction: - insert(:transaction, block: new_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 3), - to_address: burn_address, - value: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ) - - expected_result = %{ - Timex.shift(Timex.today(), days: -1) => Decimal.new(10), - Timex.today() => Decimal.new(9) - } - - assert TransactionAndLog.supply_for_days(2) == {:ok, expected_result} - end - end -end diff --git a/apps/explorer/test/explorer/exchange_rates/source/transaction_and_log_test.exs b/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs similarity index 78% rename from apps/explorer/test/explorer/exchange_rates/source/transaction_and_log_test.exs rename to apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs index 47aa09f805..d5bd5f9b96 100644 --- a/apps/explorer/test/explorer/exchange_rates/source/transaction_and_log_test.exs +++ b/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs @@ -1,6 +1,6 @@ -defmodule Explorer.ExchangeRates.Source.TransactionAndLogTest do +defmodule Explorer.ExchangeRates.Source.TokenBridgeTest do use Explorer.DataCase - alias Explorer.ExchangeRates.Source.TransactionAndLog + alias Explorer.ExchangeRates.Source.TokenBridge alias Explorer.ExchangeRates.Token @json """ @@ -27,7 +27,7 @@ defmodule Explorer.ExchangeRates.Source.TransactionAndLogTest do describe "format_data/1" do test "bring a list with one %Token{}" do - assert [%Token{}] = TransactionAndLog.format_data(@json) + assert [%Token{}] = TokenBridge.format_data(@json) end end end diff --git a/docs/env-variables.md b/docs/env-variables.md index 4cbef49e82..0c93460150 100644 --- a/docs/env-variables.md +++ b/docs/env-variables.md @@ -21,7 +21,7 @@ Below is a table outlining the environment variables utilized by BlockScout. | `METADATA_CONTRACT` | | This environment variable is specifically used by POA Network to obtain Validators information to display in the UI. | (empty) | all | | `VALIDATORS_CONTRACT` | | This environment variable is specifically used by POA Network to obtain the Emission Fund contract. | (empty) | all | | `SUPPLY_MODULE` | | This environment variable is used by the xDai Chain in order to tell the application how to calculate the total supply of the chain. | false | all | -| `SOURCE_MODULE` | | This environment variable is used to calculate the total supply and is specifically used by the xDai Chain. | false | all | +| `SOURCE_MODULE` | | This environment variable is used to calculate the exchange rate and is specifically used by the xDai Chain. | false | all | | `DATABASE_URL` | | Production environment variable to define the Database endpoint. | (empty) | all | | `POOL_SIZE` | | Production environment variable to define the number of database connections allowed. | 20 | all | | `ECTO_USE_SSL`| | Production environment variable to use SSL on Ecto queries. | true | all | @@ -33,7 +33,7 @@ Below is a table outlining the environment variables utilized by BlockScout. | `HEART_COMMAND` | | Production environment variable to restart the application in the event of a crash. | systemctl restart explorer.service | all | | `BLOCKSCOUT_VERSION` | | Added to the footer to signify the current BlockScout version. | (empty) | v1.3.4+ | | `RELEASE_LINK` | | The link to Blockscout release notes in the footer. | https://github.com/poanetwork/
blockscout/releases/
tag/${BLOCKSCOUT_VERSION} | v1.3.5+ | -| `ELIXIR_VERSION` | | Elixir version to install on the node before Blockscout deploy. | (empty) | all | +| `ELIXIR_VERSION` | | Elixir version to install on the node before Blockscout deploy. | (empty) | all | | `BLOCK_TRANSFORMER` | | Transformer for blocks: base or clique. | base | v1.3.4+ | | `GRAPHIQL _TRANSACTION` | | Default transaction in query to GraphiQL. | (empty) | v1.3.4+ | | `FIRST_BLOCK` | | The block number, where indexing begins from. | 0 | v1.3.8+ | From 3232fb0c81c3d2361139800a874b3133420d9bec Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 5 Jul 2019 13:43:31 +0300 Subject: [PATCH 47/52] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c84006016..a0935844e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features ### Fixes +- [#2299](https://github.com/poanetwork/blockscout/pull/2299) - fix interpolation in error message - [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue, check mark issue ### Chore From cd994261890af66502fd231eedf60c2a62c7583e Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 5 Jul 2019 13:44:37 +0300 Subject: [PATCH 48/52] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c84006016..9283b3ee65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue, check mark issue ### Chore +- [#2302](https://github.com/poanetwork/blockscout/pull/2302) - fix names for xDai source - [#2289](https://github.com/poanetwork/blockscout/pull/2289) - Optional websockets for dev environment From 6929f002a46f8647adafe85b5060af1e9adfa11c Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 5 Jul 2019 13:57:17 +0300 Subject: [PATCH 49/52] fix transaction csv download link --- .../templates/address_transaction/index.html.eex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex index 5abd8285c6..c3a4c94129 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex @@ -66,10 +66,10 @@

- +
- Download to_string(@address.hash)}) %>><%= gettext("CSV") %> + Download to_string(@address.hash)}) %>><%= gettext("CSV") %> From a3d4d8902e37dfa9c4211c3e37fe5fdc32f7f16a Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 5 Jul 2019 14:00:49 +0300 Subject: [PATCH 50/52] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b63c269ae..dfe4429156 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features ### Fixes +- [#2303](https://github.com/poanetwork/blockscout/pull/2303) - fix transaction csv download link - [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue, check mark issue ### Chore From b88e468634e50d752d6357896a9b754a1c3960ca Mon Sep 17 00:00:00 2001 From: maxgrapps Date: Fri, 5 Jul 2019 15:56:16 +0300 Subject: [PATCH 51/52] footer grid fix for md resolution --- .../block_scout_web/templates/layout/_footer.html.eex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex index 7188f283a1..9d84836a5a 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex @@ -13,7 +13,7 @@ <% col_size = if Enum.empty?(other_explorers), do: 3, else: 2 %>
-
+ -