Add rootstock locked widget in stats

mf-rootstock-widget
Maxim Filonov 1 year ago
parent 94a76bf982
commit 843430cf33
  1. 28
      .github/workflows/config.yml
  2. 1
      CHANGELOG.md
  3. 13
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex
  4. 2
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex
  5. 5
      apps/explorer/config/runtime/test.exs
  6. 3
      apps/explorer/lib/explorer/application.ex
  7. 31
      apps/explorer/lib/explorer/chain/cache/rootstock_locked_btc.ex
  8. 38
      apps/explorer/test/explorer/chain/cache/rootstock_locked_btc_test.exs
  9. 2
      config/config_helper.exs
  10. 5
      config/runtime.exs
  11. 2
      docker-compose/envs/common-blockscout.env

@ -54,7 +54,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-
@ -112,7 +112,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -136,7 +136,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -159,7 +159,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -168,7 +168,7 @@ jobs:
id: dialyzer-cache
with:
path: priv/plts
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-"
@ -199,7 +199,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -225,7 +225,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -254,7 +254,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -302,7 +302,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -348,7 +348,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -405,7 +405,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -459,7 +459,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -524,7 +524,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@ -588,7 +588,7 @@ jobs:
path: |
deps
_build
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_23-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_24-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"

@ -7,6 +7,7 @@
- [#8472](https://github.com/blockscout/blockscout/pull/8472) - Integrate `/api/v2/bytecodes/sources:search-all` of `eth_bytecode_db`
- [#8589](https://github.com/blockscout/blockscout/pull/8589) - DefiLlama TVL source
- [#8544](https://github.com/blockscout/blockscout/pull/8544) - Fix `nil` `"structLogs"`
- [#8583](https://github.com/blockscout/blockscout/pull/8583) - Add stats widget for rootstock
- [#8542](https://github.com/blockscout/blockscout/pull/8542) - Add tracing for rootstock
- [#8561](https://github.com/blockscout/blockscout/pull/8561), [#8564](https://github.com/blockscout/blockscout/pull/8564) - Get historical market cap data from CoinGecko
- [#8543](https://github.com/blockscout/blockscout/pull/8543) - Fix polygon tracer

@ -3,10 +3,11 @@ defmodule BlockScoutWeb.API.V2.StatsController do
alias BlockScoutWeb.API.V2.Helper
alias BlockScoutWeb.Chain.MarketHistoryChartController
alias EthereumJSONRPC.Variant
alias Explorer.{Chain, Market}
alias Explorer.Chain.Address.Counters
alias Explorer.Chain.Cache.Block, as: BlockCache
alias Explorer.Chain.Cache.{GasPriceOracle, GasUsage}
alias Explorer.Chain.Cache.{GasPriceOracle, GasUsage, RootstockLockedBTC}
alias Explorer.Chain.Cache.Transaction, as: TransactionCache
alias Explorer.Chain.Supply.RSK
alias Explorer.Chain.Transaction.History.TransactionStats
@ -57,6 +58,7 @@ defmodule BlockScoutWeb.API.V2.StatsController do
"tvl" => exchange_rate_from_db.tvl_usd,
"network_utilization_percentage" => network_utilization_percentage()
}
|> add_rootstock_locked_btc()
)
end
@ -124,4 +126,13 @@ defmodule BlockScoutWeb.API.V2.StatsController do
available_supply: current_total_supply
})
end
defp add_rootstock_locked_btc(stats) do
with "rsk" <- Variant.get(),
rootstock_locked_btc when not is_nil(rootstock_locked_btc) <- RootstockLockedBTC.get_locked_value() do
stats |> Map.put("rootstock_locked_btc", rootstock_locked_btc)
else
_ -> stats
end
end
end

@ -102,7 +102,7 @@ defmodule EthereumJSONRPC.Geth do
"enableMemory" => true,
"disableStack" => false,
"disableStorage" => true,
"enableReturnData" => true
"enableReturnData" => false
}
true ->

@ -24,6 +24,11 @@ config :explorer, Explorer.Chain.Cache.VerifiedContractsCounter, enabled: false,
config :explorer, Explorer.Chain.Cache.NewVerifiedContractsCounter, enabled: false, enable_consolidation: false
config :explorer, Explorer.Chain.Cache.WithdrawalsSum, enabled: false, enable_consolidation: false
config :explorer, Explorer.Chain.Cache.RootstockLockedBTC,
enabled: true,
global_ttl: :timer.minutes(10),
locking_cap: 21_000_000
config :explorer, Explorer.Market.History.Cataloger, enabled: false
config :explorer, Explorer.Tracer, disabled?: false

@ -124,7 +124,8 @@ defmodule Explorer.Application do
configure(Explorer.Chain.Fetcher.CheckBytecodeMatchingOnDemand),
configure(Explorer.Chain.Fetcher.FetchValidatorInfoOnDemand),
configure(Explorer.TokenInstanceOwnerAddressMigration.Supervisor),
sc_microservice_configure(Explorer.Chain.Fetcher.LookUpSmartContractSourcesOnDemand)
sc_microservice_configure(Explorer.Chain.Fetcher.LookUpSmartContractSourcesOnDemand),
configure(Explorer.Chain.Cache.RootstockLockedBTC)
]
|> List.flatten()
end

@ -0,0 +1,31 @@
defmodule Explorer.Chain.Cache.RootstockLockedBTC do
@moduledoc """
Caches the number of BTC locked in 2WP on Rootstock chain.
"""
require Logger
alias Explorer.Chain
alias Explorer.Chain.{Address, Wei}
use Explorer.Chain.MapCache,
name: :locked_rsk,
key: :locked_value,
global_ttl: Application.get_env(:explorer, __MODULE__)[:global_ttl],
ttl_check_interval: :timer.seconds(1)
defp handle_fallback(:locked_value) do
rootstock_bridge_address_str = Application.get_env(:explorer, Explorer.Chain.Transaction)[:rootstock_bridge_address]
rootstock_locking_cap = Application.get_env(:explorer, __MODULE__)[:locking_cap] |> Decimal.new()
with {:ok, rootstock_bridge_address_hash} <- Chain.string_to_address_hash(rootstock_bridge_address_str),
{:ok, %Address{fetched_coin_balance: balance}} when not is_nil(balance) <-
Chain.hash_to_address(rootstock_bridge_address_hash) do
{:update, rootstock_locking_cap |> Wei.from(:ether) |> Wei.sub(balance)}
else
_ ->
{:return, nil}
end
end
defp handle_fallback(_key), do: {:return, nil}
end

@ -0,0 +1,38 @@
defmodule Explorer.Chain.Cache.RootstockLockedBTCTest do
use Explorer.DataCase
alias Explorer.Chain.Cache.RootstockLockedBTC
alias Explorer.Chain.{Transaction, Wei}
@bridge_address "0x0000000000000000000000000000000001000006"
setup do
transaction_configuration = Application.get_env(:explorer, Transaction)
Application.put_env(:explorer, Transaction, rootstock_bridge_address: @bridge_address)
:ok
Supervisor.terminate_child(Explorer.Supervisor, RootstockLockedBTC.child_id())
Supervisor.restart_child(Explorer.Supervisor, RootstockLockedBTC.child_id())
on_exit(fn ->
Application.put_env(:explorer, Transaction, transaction_configuration)
end)
:ok
end
test "returns nil in case if there is no bridged address in the database" do
result = RootstockLockedBTC.get_locked_value()
assert is_nil(result)
end
test "updates cache if initial value is zero and returns converted wei" do
insert(:address, hash: @bridge_address, fetched_coin_balance: 42_000_000_000_000_000_000)
result = RootstockLockedBTC.get_locked_value()
assert result == Wei.from(Decimal.new(21_000_000), :ether) |> Wei.sub(Wei.from(Decimal.new(42), :ether))
end
end

@ -36,7 +36,7 @@ defmodule ConfigHelper do
|> :timer.seconds()
end
@spec parse_integer_env_var(String.t(), String.t()) :: non_neg_integer()
@spec parse_integer_env_var(String.t(), integer()) :: non_neg_integer()
def parse_integer_env_var(env_var, default_value) do
env_var
|> safe_get_env(to_string(default_value))

@ -246,6 +246,11 @@ config :explorer, Explorer.Chain.Cache.GasPriceOracle,
average_percentile: ConfigHelper.parse_integer_env_var("GAS_PRICE_ORACLE_AVERAGE_PERCENTILE", 60),
fast_percentile: ConfigHelper.parse_integer_env_var("GAS_PRICE_ORACLE_FAST_PERCENTILE", 90)
config :explorer, Explorer.Chain.Cache.RootstockLockedBTC,
enabled: System.get_env("ETHEREUM_JSONRPC_VARIANT") == "rsk",
global_ttl: ConfigHelper.parse_time_env_var("ROOTSTOCK_LOCKED_BTC_CACHE_PERIOD", "10m"),
locking_cap: ConfigHelper.parse_integer_env_var("ROOTSTOCK_LOCKING_CAP", 21_000_000)
config :explorer, Explorer.Counters.AddressTransactionsGasUsageCounter,
cache_period: ConfigHelper.parse_time_env_var("CACHE_ADDRESS_TRANSACTIONS_GAS_USAGE_COUNTER_PERIOD", "30m")

@ -147,6 +147,8 @@ INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER=false
# WITHDRAWALS_FIRST_BLOCK=
# ROOTSTOCK_REMASC_ADDRESS=
# ROOTSTOCK_BRIDGE_ADDRESS=
# ROOTSTOCK_LOCKED_BTC_CACHE_PERIOD=
# ROOTSTOCK_LOCKING_CAP=
# TOKEN_ID_MIGRATION_FIRST_BLOCK=
# TOKEN_ID_MIGRATION_CONCURRENCY=
# TOKEN_ID_MIGRATION_BATCH_SIZE=

Loading…
Cancel
Save