diff --git a/CHANGELOG.md b/CHANGELOG.md index 26c4fff461..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 @@ -62,6 +72,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 +- [#2237](https://github.com/poanetwork/blockscout/pull/2237) - fix rsk total_supply - [#2198](https://github.com/poanetwork/blockscout/pull/2198) - reduce transaction status and error constraint - [#2167](https://github.com/poanetwork/blockscout/pull/2167) - feat: document eth rpc api mimicking endpoints - [#2225](https://github.com/poanetwork/blockscout/pull/2225) - fix metadata decoding in Solidity 0.5.9 smart contract verification @@ -80,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 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) } }, diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index bb1108f17d..5a6aa1795b 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -16,6 +16,8 @@ defmodule Explorer.Application do TransactionsCache } + alias Explorer.Chain.Supply.RSK + alias Explorer.Market.MarketHistoryCache alias Explorer.Repo.PrometheusLogger @@ -44,6 +46,7 @@ defmodule Explorer.Application do 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(RSK.cache_name(), ttl_check_interval: :timer.minutes(1), global_ttl: :timer.minutes(30)), con_cache_child_spec(TransactionsCache.cache_name()) ] @@ -93,14 +96,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 09a02252a2..bc4171e45f 100644 --- a/apps/explorer/lib/explorer/chain/supply/rsk.ex +++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex @@ -6,14 +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.ExchangeRates.Token - alias Explorer.{Market, Repo} + alias Explorer.Chain.{Block, BlockNumberCache, Wei} + alias Explorer.Repo + + @cache_name :rsk_balance + @balance_key :balance def market_cap(exchange_rate) do - circulating() * exchange_rate.usd_value + btc = circulating() + + Decimal.mult(btc, exchange_rate.usd_value) end @doc "Equivalent to getting the circulating value " @@ -60,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, last), last} + cur_value = + case Map.get(by_day, date) do + nil -> + last + + value -> + value.value + end - value -> - {Map.put(days, date, value.value), value.value} - end + {Map.put(days, date, calculate_value(cur_value)), cur_value} end) |> elem(0) @@ -74,18 +83,48 @@ 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() - Repo.one(query) || wei!(0) + ConCache.put(@cache_name, @balance_key, updated_value) + + updated_value + else + value + end + end + + 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 + } + ] + }} -> + calculate_value(value) + + _ -> + Decimal.new(0) + end + rescue + _ -> Decimal.new(0) end defp wei!(value) do @@ -94,10 +133,15 @@ defmodule Explorer.Chain.Supply.RSK do end def total do - 21_000_000 + Decimal.new(21_000_000) end - def exchange_rate do - Market.get_exchange_rate(Explorer.coin()) || Token.null() + 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 40aa0a831b..71d3a530bb 100644 --- a/apps/explorer/test/explorer/chain/supply/rsk_test.exs +++ b/apps/explorer/test/explorer/chain/supply/rsk_test.exs @@ -1,32 +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 + @mult 1_000_000_000_000_000_000 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 "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) + describe "market_cap/1" do + @tag :no_parity + @tag :no_geth + test "calculates market_cap" do + EthereumJSONRPC.Mox + |> expect(:json_rpc, fn [%{id: id, method: "eth_getBalance"}], _options -> + {:ok, [%{id: id, result: "20999999999900000000000000"}]} + end) - 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 @@ -47,9 +45,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 @@ -59,14 +57,14 @@ 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, %{ - 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 @@ -77,16 +75,16 @@ 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, %{ - 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 @@ -98,18 +96,18 @@ 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, %{ - 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 @@ -122,17 +120,17 @@ 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, %{ - 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