From bca2bfd5e219aecfe03d862f8cb9d8dc1b0a6c2d Mon Sep 17 00:00:00 2001 From: Vadim Date: Mon, 2 Dec 2019 16:47:04 +0300 Subject: [PATCH] Refresh BlockReward contract ERC balance without page reloading --- .../assets/js/pages/address.js | 13 ++++++++++- .../lib/block_scout_web/notifier.ex | 11 +++++++++ .../block_scout_web/realtime_event_handler.ex | 1 + .../lib/explorer/chain/events/publisher.ex | 2 +- .../lib/explorer/chain/events/subscriber.ex | 2 +- .../lib/explorer/staking/contract_state.ex | 23 +++++++++++++------ 6 files changed, 42 insertions(+), 10 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/address.js b/apps/block_scout_web/assets/js/pages/address.js index 0c86066f71..2e407d8601 100644 --- a/apps/block_scout_web/assets/js/pages/address.js +++ b/apps/block_scout_web/assets/js/pages/address.js @@ -70,6 +70,14 @@ export function reducer (state = initialState, action) { } } +let fetchedTokenBalanceBlockNumber = 0; +function loadTokenBalance(blockNumber) { + if (blockNumber > fetchedTokenBalanceBlockNumber) { + fetchedTokenBalanceBlockNumber = blockNumber + setTimeout(loadTokenBalanceDropdown, 1000) + } +} + const elements = { '[data-selector="channel-disconnected-message"]': { render ($el, state) { @@ -83,7 +91,7 @@ const elements = { render ($el, state, oldState) { if (oldState.balance === state.balance) return $el.empty().append(state.balanceCard) - loadTokenBalanceDropdown() + loadTokenBalance(state.fetchedCoinBalanceBlockNumber) updateAllCalculatedUsdValues() } }, @@ -162,6 +170,9 @@ if ($addressDetailsPage.length) { type: 'RECEIVED_UPDATED_BALANCE', msg: humps.camelizeKeys(msg) })) + addressChannel.on('token_balance', (msg) => loadTokenBalance( + msg.block_number + )) addressChannel.on('transaction', (msg) => { store.dispatch({ type: 'RECEIVED_NEW_TRANSACTION', 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 4a542caef7..e1356401eb 100644 --- a/apps/block_scout_web/lib/block_scout_web/notifier.ex +++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex @@ -29,6 +29,11 @@ defmodule BlockScoutWeb.Notifier do Enum.each(address_coin_balances, &broadcast_address_coin_balance/1) end + def handle_event({:chain_event, :address_token_balances, type, address_token_balances}) + when type in [:realtime, :on_demand] do + Enum.each(address_token_balances, &broadcast_address_token_balance/1) + end + def handle_event( {:chain_event, :contract_verification_result, :on_demand, {address_hash, contract_verification_result, conn}} ) do @@ -203,6 +208,12 @@ defmodule BlockScoutWeb.Notifier do }) end + defp broadcast_address_token_balance(%{address_hash: address_hash, block_number: block_number}) do + Endpoint.broadcast("addresses:#{address_hash}", "token_balance", %{ + block_number: block_number + }) + end + defp broadcast_balance(%Address{hash: address_hash} = address) do Endpoint.broadcast( "addresses:#{address_hash}", diff --git a/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex b/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex index d556389209..c9e42f3b8e 100644 --- a/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex +++ b/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex @@ -23,6 +23,7 @@ defmodule BlockScoutWeb.RealtimeEventHandler do Subscriber.to(:transactions, :realtime) Subscriber.to(:addresses, :on_demand) Subscriber.to(:address_coin_balances, :on_demand) + Subscriber.to(:address_token_balances, :on_demand) Subscriber.to(:contract_verification_result, :on_demand) # Does not come from the indexer Subscriber.to(:exchange_rate) diff --git a/apps/explorer/lib/explorer/chain/events/publisher.ex b/apps/explorer/lib/explorer/chain/events/publisher.ex index a392d15da8..1792250d31 100644 --- a/apps/explorer/lib/explorer/chain/events/publisher.ex +++ b/apps/explorer/lib/explorer/chain/events/publisher.ex @@ -3,7 +3,7 @@ defmodule Explorer.Chain.Events.Publisher do Publishes events related to the Chain context. """ - @allowed_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions contract_verification_result)a + @allowed_events ~w(addresses address_coin_balances address_token_balances blocks block_rewards internal_transactions token_transfers transactions contract_verification_result)a def broadcast(_data, false), do: :ok diff --git a/apps/explorer/lib/explorer/chain/events/subscriber.ex b/apps/explorer/lib/explorer/chain/events/subscriber.ex index bb4211e79b..320a770418 100644 --- a/apps/explorer/lib/explorer/chain/events/subscriber.ex +++ b/apps/explorer/lib/explorer/chain/events/subscriber.ex @@ -3,7 +3,7 @@ defmodule Explorer.Chain.Events.Subscriber do Subscribes to events related to the Chain context. """ - @allowed_broadcast_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions contract_verification_result)a + @allowed_broadcast_events ~w(addresses address_coin_balances address_token_balances blocks block_rewards internal_transactions token_transfers transactions contract_verification_result)a @allowed_broadcast_types ~w(catchup realtime on_demand contract_verification_result)a diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 49ddde3746..fc8ebdac7d 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -188,7 +188,7 @@ defmodule Explorer.Staking.ContractState do validators.all |> Enum.map(&ContractReader.staking_by_mining_requests/1) |> ContractReader.perform_grouped_requests(validators.all, contracts, abi) - |> Map.new(fn {mining_address, resp} -> {mining_address, address_string_to_bytes(resp.staking_address)} end) + |> Map.new(fn {mining_address, resp} -> {mining_address, address_string_to_bytes(resp.staking_address).bytes} end) # the list of all pools (validators + active pools + inactive pools) pools = Enum.uniq( @@ -355,7 +355,7 @@ defmodule Explorer.Staking.ContractState do block_reward_balance = BalanceReader.get_balances_of([%{ token_contract_address_hash: token_contract_address_hash, - address_hash: block_reward_address, + address_hash: block_reward_address.bytes, block_number: block_number }])[:ok] @@ -367,10 +367,10 @@ defmodule Explorer.Staking.ContractState do type: "ERC-20" }) - Chain.import(%{ - addresses: %{params: [%{hash: block_reward_address}], on_conflict: :nothing}, + import_result = Chain.import(%{ + addresses: %{params: [%{hash: block_reward_address.bytes}], on_conflict: :nothing}, address_current_token_balances: %{params: [%{ - address_hash: block_reward_address, + address_hash: block_reward_address.bytes, token_contract_address_hash: token_contract_address_hash, block_number: block_number, value: block_reward_balance, @@ -378,6 +378,15 @@ defmodule Explorer.Staking.ContractState do }]}, tokens: %{params: [token_params]} }) + + with {:ok, _} <- import_result, do: + Publisher.broadcast([{ + :address_token_balances, [ + %{address_hash: block_reward_address.struct, block_number: block_number} + ] + }], + :on_demand + ) end # start snapshotting at the beginning of the staking epoch @@ -431,10 +440,10 @@ defmodule Explorer.Staking.ContractState do %Chain.Hash{ byte_count: _, bytes: bytes - } + } = struct } = Chain.string_to_address_hash(address_string) - bytes + %{bytes: bytes, struct: struct} end # sobelow_skip ["Traversal"]