Find the pools an address have ever staked into

staking
Vadim 5 years ago committed by Victor Baranov
parent 0a83835b35
commit 23c2815be5
  1. 76
      apps/block_scout_web/lib/block_scout_web/channels/stakes_channel.ex
  2. 15
      apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex

@ -252,11 +252,15 @@ defmodule BlockScoutWeb.StakesChannel do
end end
end end
staking_contract_address = try do ContractState.get(:staking_contract).address after end
cond do cond do
search_in_progress == true -> search_in_progress == true ->
{:reply, {:error, %{reason: gettext("Pools searching is already in progress for this address")}}, socket} {:reply, {:error, %{reason: gettext("Pools searching is already in progress for this address")}}, socket}
staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" -> staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" ->
{:reply, {:error, %{reason: gettext("Unknown staker address. Please, choose your account in MetaMask")}}, socket} {:reply, {:error, %{reason: gettext("Unknown staker address. Please, choose your account in MetaMask")}}, socket}
staking_contract_address == nil || staking_contract_address == "" || staking_contract_address == "0x0000000000000000000000000000000000000000" ->
{:reply, {:error, %{reason: gettext("Unknown address of Staking contract. Please, contact support")}}, socket}
true -> true ->
result = if data["preload"] do result = if data["preload"] do
%{ %{
@ -264,7 +268,7 @@ defmodule BlockScoutWeb.StakesChannel do
socket: socket socket: socket
} }
else else
task = Task.async(__MODULE__, :find_claim_reward_pools, [socket, staker]) task = Task.async(__MODULE__, :find_claim_reward_pools, [socket, staker, staking_contract_address])
%{ %{
html: "OK", html: "OK",
socket: assign(socket, @searching_claim_reward_pools, %{task: task, staker: staker}) socket: assign(socket, @searching_claim_reward_pools, %{task: task, staker: staker})
@ -324,12 +328,44 @@ defmodule BlockScoutWeb.StakesChannel do
{:noreply, socket} {:noreply, socket}
end end
def find_claim_reward_pools(socket, staker) do def find_claim_reward_pools(socket, staker, staking_contract_address) do
:ets.insert(ContractState, {searching_claim_reward_pools_key(staker), true}) :ets.insert(ContractState, {searching_claim_reward_pools_key(staker), true})
try do try do
pools = [] staker_padded =
:timer.sleep(15000) # emulate working staker
html = View.render_to_string(StakesView, "_stakes_modal_claim_reward_content.html", pools: pools) |> String.replace_leading("0x", "")
|> String.pad_leading(64, ["0"])
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
# Search for `PlacedStake` events
{error, pools_staked_into} = find_claim_reward_pools_by_logs(staking_contract_address, [
# keccak-256 of `PlacedStake(address,address,uint256,uint256)`
"0x2273de02cb1f69ba6259d22c4bc22c60e4c94c193265ef6afee324a04a9b6d22",
nil, # don't filter by `toPoolStakingAddress`
"0x" <> staker_padded # filter by `staker`
], json_rpc_named_arguments, 1)
# Search for `MovedStake` events
{error, pools_moved_into} = if error == nil do
find_claim_reward_pools_by_logs(staking_contract_address, [
# keccak-256 of `MovedStake(address,address,address,uint256,uint256)`
"0x4480d8e4b1e9095b94bf513961d26fe1d32386ebdd103d18fe8738cf4b2223ff",
nil, # fromPoolStakingAddress,
nil, # toPoolStakingAddress
"0x" <> staker_padded
], json_rpc_named_arguments, 2)
else
{error, []}
end
html = View.render_to_string(
StakesView,
"_stakes_modal_claim_reward_content.html",
pools: Enum.uniq(pools_staked_into ++ pools_moved_into),
error: error
)
push(socket, "claim_reward_pools", %{ push(socket, "claim_reward_pools", %{
html: html html: html
}) })
@ -338,6 +374,32 @@ defmodule BlockScoutWeb.StakesChannel do
end end
end end
defp find_claim_reward_pools_by_logs(staking_contract_address, topics, json_rpc_named_arguments, topic_index) do
result = EthereumJSONRPC.request(%{
id: 0,
method: "eth_getLogs",
params: [%{
fromBlock: "0x0",
toBlock: "latest",
address: staking_contract_address,
topics: topics
}]
}) |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments)
case result do
{:ok, response} ->
pools = Enum.uniq(Enum.map(response, fn event ->
truncate_address(Enum.at(event["topics"], topic_index))
end))
{nil, pools}
{:error, reason} ->
if is_map(reason) && Map.has_key?(reason, :message) && String.length(String.trim(reason.message)) > 0 do
{reason.message, []}
else
{gettext("JSON RPC error") <> ": " <> inspect(reason), []}
end
end
end
defp push_staking_contract(socket) do defp push_staking_contract(socket) do
if socket.assigns[:contract_sent] do if socket.assigns[:contract_sent] do
socket socket
@ -359,4 +421,8 @@ defmodule BlockScoutWeb.StakesChannel do
staker = if staker == nil, do: "", else: staker staker = if staker == nil, do: "", else: staker
Atom.to_string(@searching_claim_reward_pools) <> "_" <> staker Atom.to_string(@searching_claim_reward_pools) <> "_" <> staker
end end
defp truncate_address("0x000000000000000000000000" <> truncated_address) do
"0x#{truncated_address}"
end
end end

@ -1,5 +1,16 @@
<%= if not Enum.empty?(@pools) do %> <%= if not Enum.empty?(@pools) do %>
<p>Pool list...</p> <p>
Pool list:<br />
<%= for pool <- @pools do %>
<%= pool %><br />
<% end %>
</p>
<% else %> <% else %>
<p><%= gettext("Unable to find any pools you staked into.") %></p> <p>
<%= if @error do %>
<%= @error %>
<% else %>
<%= gettext("Unable to find any pools you staked into.") %>
<% end %>
</p>
<% end %> <% end %>
Loading…
Cancel
Save