From d020fc9baa09a263d571e144138df0258a8db4b6 Mon Sep 17 00:00:00 2001 From: Paul Tsupikoff Date: Wed, 14 Aug 2019 09:42:25 +0200 Subject: [PATCH] Periodically refresh the table with staking pools (#2557) The table is refreshed when new staking epoch starts and after an interval configured in apps/block_scout_web/config/config.exs. If no interval is configured, the table is only updated on new epoch. --- .../block_scout_web/assets/js/pages/stakes.js | 34 +++++++++++++++++-- apps/block_scout_web/config/config.exs | 3 +- .../channels/stakes_channel.ex | 14 ++++++-- .../controllers/stakes_controller.ex | 3 +- .../lib/block_scout_web/notifier.ex | 5 ++- .../templates/stakes/index.html.eex | 2 +- 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index fc82e0482f..b40105db19 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -21,7 +21,10 @@ export const initialState = { stakingContract: null, blockRewardContract: null, tokenDecimals: 0, - tokenSymbol: '' + tokenSymbol: '', + refreshInterval: null, + lastEpochNumber: 0, + lastBlockNumber: 0 } export function reducer (state = initialState, action) { @@ -42,6 +45,12 @@ export function reducer (state = initialState, action) { additionalParams: { account: action.account } }) } + case 'RECEIVED_UPDATE': { + return Object.assign({}, state, { + lastEpochNumber: action.lastEpochNumber, + lastBlockNumber: action.lastBlockNumber + }) + } case 'RECEIVED_CONTRACTS': { return Object.assign({}, state, { stakingContract: action.stakingContract, @@ -56,6 +65,11 @@ export function reducer (state = initialState, action) { } const elements = { + '[data-page="stakes"]': { + load ($el) { + return { refreshInterval: $el.data('refresh-interval') || null } + } + } } const $stakesPage = $('[data-page="stakes"]') @@ -67,7 +81,23 @@ if ($stakesPage.length) { const channel = subscribeChannel('stakes:staking_update') store.dispatch({ type: 'CHANNEL_CONNECTED', channel }) - channel.on('staking_update', msg => $stakesTop.html(msg.top_html)) + channel.on('staking_update', msg => { + $stakesTop.html(msg.top_html) + + const state = store.getState() + if ( + msg.epoch_number > state.lastEpochNumber || + (state.refreshInterval && msg.block_number >= state.lastBlockNumber + state.refreshInterval) + ) { + store.dispatch({ + type: 'RECEIVED_UPDATE', + lastEpochNumber: msg.epoch_number, + lastBlockNumber: msg.block_number + }) + refreshPage(store) + } + }) + channel.on('contracts', msg => { const web3 = store.getState().web3 const stakingContract = diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs index 423c8fe9d4..a034c8312c 100644 --- a/apps/block_scout_web/config/config.exs +++ b/apps/block_scout_web/config/config.exs @@ -23,7 +23,8 @@ config :block_scout_web, BlockScoutWeb.Chain, logo_footer: System.get_env("LOGO_FOOTER"), logo_text: System.get_env("LOGO_TEXT"), has_emission_funds: false, - staking_enabled: not is_nil(System.get_env("POS_STAKING_CONTRACT")) + staking_enabled: not is_nil(System.get_env("POS_STAKING_CONTRACT")), + staking_table_refresh_interval: 10 config :block_scout_web, link_to_other_explorers: System.get_env("LINK_TO_OTHER_EXPLORERS") == "true", diff --git a/apps/block_scout_web/lib/block_scout_web/channels/stakes_channel.ex b/apps/block_scout_web/lib/block_scout_web/channels/stakes_channel.ex index b6326f49db..0db3086489 100644 --- a/apps/block_scout_web/lib/block_scout_web/channels/stakes_channel.ex +++ b/apps/block_scout_web/lib/block_scout_web/channels/stakes_channel.ex @@ -6,6 +6,7 @@ defmodule BlockScoutWeb.StakesChannel do alias BlockScoutWeb.{StakesController, StakesView} alias Explorer.Chain + alias Explorer.Chain.Cache.BlockNumber alias Explorer.Counters.AverageBlockTime alias Explorer.Staking.ContractState alias Phoenix.View @@ -22,7 +23,14 @@ defmodule BlockScoutWeb.StakesChannel do |> assign(:account, account) |> push_staking_contract() - handle_out("staking_update", nil, socket) + handle_out( + "staking_update", + %{ + block_number: BlockNumber.get_max(), + epoch_number: ContractState.get(:epoch_number, 0) + }, + socket + ) end def handle_in("render_validator_info", %{"address" => staking_address}, socket) do @@ -167,8 +175,10 @@ defmodule BlockScoutWeb.StakesChannel do {:reply, {:ok, result}, socket} end - def handle_out("staking_update", _data, socket) do + def handle_out("staking_update", data, socket) do push(socket, "staking_update", %{ + epoch_number: data.epoch_number, + block_number: data.block_number, top_html: StakesController.render_top(socket) }) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex index 3d27df3b99..da4bdcd442 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex @@ -104,7 +104,8 @@ defmodule BlockScoutWeb.StakesController do top: render_top(conn), pools_type: filter, current_path: current_path(conn), - average_block_time: AverageBlockTime.average_block_time() + average_block_time: AverageBlockTime.average_block_time(), + refresh_interval: Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:staking_table_refresh_interval] ) end diff --git a/apps/block_scout_web/lib/block_scout_web/notifier.ex b/apps/block_scout_web/lib/block_scout_web/notifier.ex index a3d4ae34f1..f31ce08062 100644 --- a/apps/block_scout_web/lib/block_scout_web/notifier.ex +++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex @@ -7,6 +7,7 @@ defmodule BlockScoutWeb.Notifier do alias BlockScoutWeb.{AddressContractVerificationView, Endpoint} alias Explorer.{Chain, Market, Repo} alias Explorer.Chain.{Address, InternalTransaction, TokenTransfer, Transaction} + alias Explorer.Chain.Cache.BlockNumber alias Explorer.Chain.Supply.RSK alias Explorer.Chain.Transaction.History.TransactionStats alias Explorer.Counters.AverageBlockTime @@ -104,10 +105,12 @@ defmodule BlockScoutWeb.Notifier do def handle_event({:chain_event, :staking_update}) do epoch_number = ContractState.get(:epoch_number, 0) epoch_end_block = ContractState.get(:epoch_end_block, 0) + block_number = BlockNumber.get_max() Endpoint.broadcast("stakes:staking_update", "staking_update", %{ epoch_number: epoch_number, - epoch_end_block: epoch_end_block + epoch_end_block: epoch_end_block, + block_number: block_number }) end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/index.html.eex index 4112ea6df9..df3b3a29bc 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/index.html.eex @@ -1,7 +1,7 @@
<%= raw(@top) %>
-
+
<%= render BlockScoutWeb.StakesView, "_stakes_tabs.html", conn: @conn %>