Update BlockReward contract ERC balance

staking
Vadim 5 years ago committed by Victor Baranov
parent 598673fb0a
commit 24c607b28c
  1. 39
      apps/explorer/lib/explorer/staking/contract_reader.ex
  2. 140
      apps/explorer/lib/explorer/staking/contract_state.ex
  3. 26
      apps/explorer/lib/explorer/staking/stake_snapshotting.ex

@ -1,26 +1,25 @@
defmodule Explorer.Staking.ContractReader do defmodule Explorer.Staking.ContractReader do
@moduledoc """ @moduledoc """
Routines for batched fetching of information from POSDAO contracts Routines for batched fetching of information from POSDAO contracts.
""" """
alias Explorer.Chain
alias Explorer.SmartContract.Reader alias Explorer.SmartContract.Reader
def global_requests do def global_requests do
[ [
token_contract_address: {:staking, "erc677TokenContract", []}, active_pools: {:staking, "getPools", []},
min_candidate_stake: {:staking, "candidateMinStake", []}, epoch_end_block: {:staking, "stakingEpochEndBlock", []},
min_delegator_stake: {:staking, "delegatorMinStake", []},
epoch_number: {:staking, "stakingEpoch", []}, epoch_number: {:staking, "stakingEpoch", []},
epoch_start_block: {:staking, "stakingEpochStartBlock", []}, epoch_start_block: {:staking, "stakingEpochStartBlock", []},
epoch_end_block: {:staking, "stakingEpochEndBlock", []},
staking_allowed: {:staking, "areStakeAndWithdrawAllowed", []},
active_pools: {:staking, "getPools", []},
inactive_pools: {:staking, "getPoolsInactive", []}, inactive_pools: {:staking, "getPoolsInactive", []},
pools_to_be_elected: {:staking, "getPoolsToBeElected", []}, min_candidate_stake: {:staking, "candidateMinStake", []},
min_delegator_stake: {:staking, "delegatorMinStake", []},
pools_likelihood: {:staking, "getPoolsLikelihood", []}, pools_likelihood: {:staking, "getPoolsLikelihood", []},
validators: {:validator_set, "getValidators", []}, pools_to_be_elected: {:staking, "getPoolsToBeElected", []},
staking_allowed: {:staking, "areStakeAndWithdrawAllowed", []},
token_contract_address: {:staking, "erc677TokenContract", []},
unremovable_validator: {:validator_set, "unremovableValidator", []}, unremovable_validator: {:validator_set, "unremovableValidator", []},
validators: {:validator_set, "getValidators", []},
validator_set_apply_block: {:validator_set, "validatorSetApplyBlock", []} validator_set_apply_block: {:validator_set, "validatorSetApplyBlock", []}
] ]
end end
@ -28,23 +27,23 @@ defmodule Explorer.Staking.ContractReader do
def pool_staking_requests(staking_address) do def pool_staking_requests(staking_address) do
[ [
active_delegators: {:staking, "poolDelegators", [staking_address]}, active_delegators: {:staking, "poolDelegators", [staking_address]},
validator_reward_percent: {:block_reward, "validatorRewardPercent", [staking_address]},
inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]}, inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]},
is_active: {:staking, "isPoolActive", [staking_address]}, is_active: {:staking, "isPoolActive", [staking_address]},
mining_address_hash: {:validator_set, "miningByStakingAddress", [staking_address]}, mining_address_hash: {:validator_set, "miningByStakingAddress", [staking_address]},
self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address]}, self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address]},
total_staked_amount: {:staking, "stakeAmountTotal", [staking_address]} total_staked_amount: {:staking, "stakeAmountTotal", [staking_address]},
validator_reward_percent: {:block_reward, "validatorRewardPercent", [staking_address]}
] ]
end end
def pool_mining_requests(mining_address) do def pool_mining_requests(mining_address) do
[ [
was_validator_count: {:validator_set, "validatorCounter", [mining_address]},
is_banned: {:validator_set, "isValidatorBanned", [mining_address]},
are_delegators_banned: {:validator_set, "areDelegatorsBanned", [mining_address]}, are_delegators_banned: {:validator_set, "areDelegatorsBanned", [mining_address]},
ban_reason: {:validator_set, "banReason", [mining_address]}, ban_reason: {:validator_set, "banReason", [mining_address]},
banned_until: {:validator_set, "bannedUntil", [mining_address]}, banned_until: {:validator_set, "bannedUntil", [mining_address]},
banned_delegators_until: {:validator_set, "bannedDelegatorsUntil", [mining_address]}, banned_delegators_until: {:validator_set, "bannedDelegatorsUntil", [mining_address]},
is_banned: {:validator_set, "isValidatorBanned", [mining_address]},
was_validator_count: {:validator_set, "validatorCounter", [mining_address]},
was_banned_count: {:validator_set, "banCounter", [mining_address]} was_banned_count: {:validator_set, "banCounter", [mining_address]}
] ]
end end
@ -85,18 +84,6 @@ defmodule Explorer.Staking.ContractReader do
] ]
end end
def decode_data(address_hash_string) do
{
:ok,
%Chain.Hash{
byte_count: _,
bytes: bytes
}
} = Chain.string_to_address_hash(address_hash_string)
bytes
end
def perform_requests(requests, contracts, abi) do def perform_requests(requests, contracts, abi) do
requests requests
|> generate_requests(contracts) |> generate_requests(contracts)

@ -1,7 +1,7 @@
defmodule Explorer.Staking.ContractState do defmodule Explorer.Staking.ContractState do
@moduledoc """ @moduledoc """
Fetches all information from POSDAO staking contracts. Fetches all information from POSDAO staking contracts.
All contract calls are batched into four requests, according to their dependencies. All contract calls are batched into requests, according to their dependencies.
Subscribes to new block notifications and refreshes when previously unseen block arrives. Subscribes to new block notifications and refreshes when previously unseen block arrives.
""" """
@ -13,25 +13,28 @@ defmodule Explorer.Staking.ContractState do
alias Explorer.Chain.Events.{Publisher, Subscriber} alias Explorer.Chain.Events.{Publisher, Subscriber}
alias Explorer.SmartContract.Reader alias Explorer.SmartContract.Reader
alias Explorer.Staking.{ContractReader, StakeSnapshotting} alias Explorer.Staking.{ContractReader, StakeSnapshotting}
alias Explorer.Token.{BalanceReader, MetadataRetriever}
@table_name __MODULE__ @table_name __MODULE__
@table_keys [ @table_keys [
:token_contract_address, :block_reward_contract,
:token, :epoch_end_block,
:min_candidate_stake,
:min_delegator_stake,
:epoch_number, :epoch_number,
:epoch_start_block, :epoch_start_block,
:epoch_end_block, :is_snapshotted,
:min_candidate_stake,
:min_delegator_stake,
:staking_allowed, :staking_allowed,
:staking_contract, :staking_contract,
:validator_set_contract, :token_contract_address,
:block_reward_contract, :token,
:validator_set_apply_block,
:validator_min_reward_percent, :validator_min_reward_percent,
:is_snapshotted :validator_set_apply_block,
:validator_set_contract
] ]
@token_renew_frequency 10 # frequency in blocks
defstruct [ defstruct [
:seen_block, :seen_block,
:contracts, :contracts,
@ -91,13 +94,15 @@ defmodule Explorer.Staking.ContractState do
abi: staking_abi ++ validator_set_abi ++ block_reward_abi abi: staking_abi ++ validator_set_abi ++ block_reward_abi
} }
token = get_token(token_contract_address)
:ets.insert(@table_name, :ets.insert(@table_name,
staking_contract: %{abi: staking_abi, address: staking_contract_address},
validator_set_contract: %{abi: validator_set_abi, address: validator_set_contract_address},
block_reward_contract: %{abi: block_reward_abi, address: block_reward_contract_address}, block_reward_contract: %{abi: block_reward_abi, address: block_reward_contract_address},
is_snapshotted: false,
staking_contract: %{abi: staking_abi, address: staking_contract_address},
token_contract_address: token_contract_address, token_contract_address: token_contract_address,
token: get_token(token_contract_address), token: token,
is_snapshotted: false validator_set_contract: %{abi: validator_set_abi, address: validator_set_contract_address}
) )
{:ok, state, {:continue, []}} {:ok, state, {:continue, []}}
@ -123,14 +128,13 @@ defmodule Explorer.Staking.ContractState do
defp fetch_state(contracts, abi, block_number) do defp fetch_state(contracts, abi, block_number) do
# read general info from the contracts (including pool list and validator list) # read general info from the contracts (including pool list and validator list)
global_responses = ContractReader.perform_requests(ContractReader.global_requests(), contracts, abi) global_responses = ContractReader.perform_requests(ContractReader.global_requests(), contracts, abi)
token = get_token(global_responses.token_contract_address)
validator_min_reward_percent = ContractReader.perform_requests( validator_min_reward_percent = ContractReader.perform_requests(
ContractReader.validator_min_reward_percent_request(global_responses.epoch_number), contracts, abi ContractReader.validator_min_reward_percent_request(global_responses.epoch_number), contracts, abi
).value ).value
start_snapshotting = (global_responses.epoch_start_block == block_number + 1) epoch_finished = (global_responses.epoch_start_block == block_number + 1)
is_validator = Enum.into(global_responses.validators, %{}, &{hash_to_string(&1), true}) is_validator = Enum.into(global_responses.validators, %{}, &{address_bytes_to_string(&1), true})
unremovable_validator = global_responses.unremovable_validator
# save the general info to ETS (excluding pool list and validator list) # save the general info to ETS (excluding pool list and validator list)
settings = settings =
@ -146,23 +150,32 @@ defmodule Explorer.Staking.ContractState do
:validator_set_apply_block :validator_set_apply_block
]) ])
|> Map.to_list() |> Map.to_list()
|> Enum.concat(token: token)
|> Enum.concat(validator_min_reward_percent: validator_min_reward_percent) |> Enum.concat(validator_min_reward_percent: validator_min_reward_percent)
update_token =
get(:token) == nil or
get(:token_contract_address) != global_responses.token_contract_address or
rem(block_number, @token_renew_frequency) == 0
settings = if update_token do
Enum.concat(settings, token: get_token(global_responses.token_contract_address))
else
settings
end
:ets.insert(@table_name, settings) :ets.insert(@table_name, settings)
# form the list of all pools # form the list of all pools
validators = if start_snapshotting do validators = if epoch_finished do
%{ %{
"getPendingValidators" => {:ok, [pending_validators]}, "getPendingValidators" => {:ok, [validators_pending]},
"validatorsToBeFinalized" => {:ok, [to_be_finalized_validators]} "validatorsToBeFinalized" => {:ok, [validators_to_be_finalized]}
} = Reader.query_contract(contracts.validator_set, abi, %{ } = Reader.query_contract(contracts.validator_set, abi, %{
"getPendingValidators" => [], "getPendingValidators" => [],
"validatorsToBeFinalized" => [] "validatorsToBeFinalized" => []
}) })
validators_pending = Enum.uniq(pending_validators ++ to_be_finalized_validators) validators_pending = Enum.uniq(validators_pending ++ validators_to_be_finalized)
# get the list of all validators (the current and pending)
%{ %{
# get the list of all validators (the current and pending)
all: Enum.uniq(global_responses.validators ++ validators_pending), all: Enum.uniq(global_responses.validators ++ validators_pending),
pending: validators_pending pending: validators_pending
} }
@ -170,30 +183,33 @@ defmodule Explorer.Staking.ContractState do
%{all: global_responses.validators} %{all: global_responses.validators}
end end
# miningToStakingAddress mapping
mining_to_staking_address = mining_to_staking_address =
validators.all validators.all
|> Enum.map(&ContractReader.staking_by_mining_requests/1) |> Enum.map(&ContractReader.staking_by_mining_requests/1)
|> ContractReader.perform_grouped_requests(validators.all, contracts, abi) |> ContractReader.perform_grouped_requests(validators.all, contracts, abi)
|> Map.new(fn {mining_address, resp} -> {mining_address, ContractReader.decode_data(resp.staking_address)} end) |> Map.new(fn {mining_address, resp} -> {mining_address, address_string_to_bytes(resp.staking_address)} end)
# the list of all pools (validators + active pools + inactive pools)
pools = Enum.uniq( pools = Enum.uniq(
Map.values(mining_to_staking_address) ++ Map.values(mining_to_staking_address) ++
global_responses.active_pools ++ global_responses.active_pools ++
global_responses.inactive_pools global_responses.inactive_pools
) )
# read info about each pool from the contracts (including delegator list) # read pool info from the contracts by its staking address
pool_staking_responses = pool_staking_responses =
pools pools
|> Enum.map(&ContractReader.pool_staking_requests/1) |> Enum.map(&ContractReader.pool_staking_requests/1)
|> ContractReader.perform_grouped_requests(pools, contracts, abi) |> ContractReader.perform_grouped_requests(pools, contracts, abi)
# read pool info from the contracts by its mining address
pool_mining_responses = pool_mining_responses =
pools pools
|> Enum.map(&ContractReader.pool_mining_requests(pool_staking_responses[&1].mining_address_hash)) |> Enum.map(&ContractReader.pool_mining_requests(pool_staking_responses[&1].mining_address_hash))
|> ContractReader.perform_grouped_requests(pools, contracts, abi) |> ContractReader.perform_grouped_requests(pools, contracts, abi)
# form a flat list of all stakers in the form {pool_staking_address, staker_address, is_active} # get a flat list of all stakers in the form of {pool_staking_address, staker_address, is_active}
stakers = stakers =
Enum.flat_map(pool_staking_responses, fn {pool_staking_address, resp} -> Enum.flat_map(pool_staking_responses, fn {pool_staking_address, resp} ->
[{pool_staking_address, pool_staking_address, true}] ++ [{pool_staking_address, pool_staking_address, true}] ++
@ -201,7 +217,7 @@ defmodule Explorer.Staking.ContractState do
Enum.map(resp.inactive_delegators, &{pool_staking_address, &1, false}) Enum.map(resp.inactive_delegators, &{pool_staking_address, &1, false})
end) end)
# get amounts for each of the stakers # read info of each staker from the contracts
staker_responses = staker_responses =
stakers stakers
|> Enum.map(fn {pool_staking_address, staker_address, _is_active} -> |> Enum.map(fn {pool_staking_address, staker_address, _is_active} ->
@ -209,9 +225,11 @@ defmodule Explorer.Staking.ContractState do
end) end)
|> ContractReader.perform_grouped_requests(stakers, contracts, abi) |> ContractReader.perform_grouped_requests(stakers, contracts, abi)
# to keep sort order # to keep sort order when using `perform_grouped_requests` (see below)
pool_staking_keys = Enum.map(pool_staking_responses, fn {key, _} -> key end) pool_staking_keys = Enum.map(pool_staking_responses, fn {pool_staking_address, _} -> pool_staking_address end)
# call `BlockReward.validatorShare` function for each pool
# to get validator's reward share of the pool (needed for the `Delegators` list in UI)
candidate_reward_responses = candidate_reward_responses =
pool_staking_responses pool_staking_responses
|> Enum.map(fn {_pool_staking_address, resp} -> |> Enum.map(fn {_pool_staking_address, resp} ->
@ -224,9 +242,11 @@ defmodule Explorer.Staking.ContractState do
end) end)
|> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi)
# to keep sort order # to keep sort order when using `perform_grouped_requests` (see below)
delegator_keys = Enum.map(staker_responses, fn {key, _} -> key end) delegator_keys = Enum.map(staker_responses, fn {key, _} -> key end)
# call `BlockReward.delegatorShare` function for each delegator
# to get their reward share of the pool (needed for the `Delegators` list in UI)
delegator_reward_responses = delegator_reward_responses =
staker_responses staker_responses
|> Enum.map(fn {{pool_staking_address, _staker_address, _is_active}, resp} -> |> Enum.map(fn {{pool_staking_address, _staker_address, _is_active}, resp} ->
@ -247,7 +267,6 @@ defmodule Explorer.Staking.ContractState do
# calculate likelihood of becoming a validator on the next epoch # calculate likelihood of becoming a validator on the next epoch
[likelihood_values, total_likelihood] = global_responses.pools_likelihood [likelihood_values, total_likelihood] = global_responses.pools_likelihood
likelihood = likelihood =
global_responses.pools_to_be_elected # array of pool addresses (staking addresses) global_responses.pools_to_be_elected # array of pool addresses (staking addresses)
|> Enum.zip(likelihood_values) |> Enum.zip(likelihood_values)
@ -283,7 +302,7 @@ defmodule Explorer.Staking.ContractState do
validator_reward_percent: staking_resp.validator_reward_percent / 10_000, validator_reward_percent: staking_resp.validator_reward_percent / 10_000,
is_deleted: false, is_deleted: false,
is_validator: is_validator, is_validator: is_validator,
is_unremovable: hash_to_string(pool_staking_address) == unremovable_validator, is_unremovable: address_bytes_to_string(pool_staking_address) == global_responses.unremovable_validator,
ban_reason: binary_to_string(mining_resp.ban_reason) ban_reason: binary_to_string(mining_resp.ban_reason)
} }
|> Map.merge( |> Map.merge(
@ -319,6 +338,7 @@ defmodule Explorer.Staking.ContractState do
}) })
end) end)
# perform SQL queries
{:ok, _} = {:ok, _} =
Chain.import(%{ Chain.import(%{
staking_pools: %{params: pool_entries}, staking_pools: %{params: pool_entries},
@ -326,9 +346,44 @@ defmodule Explorer.Staking.ContractState do
timeout: :infinity timeout: :infinity
}) })
if start_snapshotting do if epoch_finished do
# update ERC balance of the BlockReward contract
token = get(:token)
if token != nil do
block_reward_address = address_string_to_bytes(get(:block_reward_contract).address)
token_contract_address_hash = token.contract_address_hash
block_reward_balance = BalanceReader.get_balances_of([%{
token_contract_address_hash: token_contract_address_hash,
address_hash: block_reward_address,
block_number: block_number
}])[:ok]
token_params =
token_contract_address_hash
|> MetadataRetriever.get_functions_of()
|> Map.merge(%{
contract_address_hash: token_contract_address_hash,
type: "ERC-20"
})
Chain.import(%{
addresses: %{params: [%{hash: block_reward_address}], on_conflict: :nothing},
address_current_token_balances: %{params: [%{
address_hash: block_reward_address,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
value: block_reward_balance,
value_fetched_at: DateTime.utc_now()
}]},
tokens: %{params: [token_params]}
})
end
# start snapshotting at the beginning of the staking epoch
spawn(StakeSnapshotting, :do_snapshotting, [ spawn(StakeSnapshotting, :do_snapshotting, [
%{contracts: contracts, abi: abi, epoch_number: global_responses.epoch_number, ets_table_name: @table_name}, %{contracts: contracts, abi: abi, ets_table_name: @table_name},
global_responses.epoch_number,
pool_staking_responses, pool_staking_responses,
pool_mining_responses, pool_mining_responses,
Map.new(Enum.map(staker_responses, fn {key, resp} -> {pool_staking_address, staker_address, _} = key; {{pool_staking_address, staker_address}, resp} end)), Map.new(Enum.map(staker_responses, fn {key, resp} -> {pool_staking_address, staker_address, _} = key; {{pool_staking_address, staker_address}, resp} end)),
@ -338,6 +393,7 @@ defmodule Explorer.Staking.ContractState do
]) ])
end end
# notify the UI about new block
Publisher.broadcast(:staking_update) Publisher.broadcast(:staking_update)
end end
@ -367,7 +423,19 @@ defmodule Explorer.Staking.ContractState do
defp ratio(_numerator, 0), do: 0 defp ratio(_numerator, 0), do: 0
defp ratio(numerator, denominator), do: numerator / denominator * 100 defp ratio(numerator, denominator), do: numerator / denominator * 100
defp hash_to_string(hash), do: "0x" <> Base.encode16(hash, case: :lower) defp address_bytes_to_string(hash), do: "0x" <> Base.encode16(hash, case: :lower)
defp address_string_to_bytes(address_string) do
{
:ok,
%Chain.Hash{
byte_count: _,
bytes: bytes
}
} = Chain.string_to_address_hash(address_string)
bytes
end
# sobelow_skip ["Traversal"] # sobelow_skip ["Traversal"]
defp abi(file_name) do defp abi(file_name) do

@ -1,6 +1,6 @@
defmodule Explorer.Staking.StakeSnapshotting do defmodule Explorer.Staking.StakeSnapshotting do
@moduledoc """ @moduledoc """
Makes snapshots of staked amounts Makes snapshots of staked amounts.
""" """
import Ecto.Query, only: [from: 2] import Ecto.Query, only: [from: 2]
@ -12,7 +12,8 @@ defmodule Explorer.Staking.StakeSnapshotting do
alias Explorer.Staking.ContractReader alias Explorer.Staking.ContractReader
def do_snapshotting( def do_snapshotting(
%{contracts: contracts, abi: abi, epoch_number: epoch_number, ets_table_name: ets_table_name}, %{contracts: contracts, abi: abi, ets_table_name: ets_table_name},
epoch_number,
cached_pool_staking_responses, cached_pool_staking_responses,
cached_pool_mining_responses, cached_pool_mining_responses,
cached_staker_responses, cached_staker_responses,
@ -27,7 +28,8 @@ defmodule Explorer.Staking.StakeSnapshotting do
pending_validators_mining_addresses pending_validators_mining_addresses
|> Enum.map(&mining_to_staking_address[&1]) |> Enum.map(&mining_to_staking_address[&1])
# get snapshotted amounts and other pool info for each pending validator. # get snapshotted amounts and other pool info for each
# pending validator by their staking address.
# use `cached_pool_staking_responses` when possible # use `cached_pool_staking_responses` when possible
pool_staking_responses = pool_staking_responses =
pool_staking_addresses pool_staking_addresses
@ -46,7 +48,7 @@ defmodule Explorer.Staking.StakeSnapshotting do
|> Enum.zip(pool_staking_addresses) |> Enum.zip(pool_staking_addresses)
|> Map.new(fn {key, val} -> {val, key} end) |> Map.new(fn {key, val} -> {val, key} end)
# get pool info by its mining address. # read pool info from the contracts by its mining address.
# use `cached_pool_mining_responses` when possible # use `cached_pool_mining_responses` when possible
pool_mining_responses = pool_mining_responses =
pool_staking_addresses pool_staking_addresses
@ -63,14 +65,15 @@ defmodule Explorer.Staking.StakeSnapshotting do
|> Enum.zip(pool_staking_addresses) |> Enum.zip(pool_staking_addresses)
|> Map.new(fn {key, val} -> {val, key} end) |> Map.new(fn {key, val} -> {val, key} end)
# form a flat list of all active stakers in the form {pool_staking_address, staker_address} # get a flat list of all stakers of each validator
# in the form of {pool_staking_address, staker_address}
stakers = stakers =
Enum.flat_map(pool_staking_responses, fn {pool_staking_address, resp} -> Enum.flat_map(pool_staking_responses, fn {pool_staking_address, resp} ->
[{pool_staking_address, pool_staking_address}] ++ [{pool_staking_address, pool_staking_address}] ++
Enum.map(resp.active_delegators, &{pool_staking_address, &1}) Enum.map(resp.active_delegators, &{pool_staking_address, &1})
end) end)
# get amounts for each of the stakers # read info of each staker from the contracts.
# use `cached_staker_responses` when possible # use `cached_staker_responses` when possible
staker_responses = staker_responses =
stakers stakers
@ -96,9 +99,11 @@ defmodule Explorer.Staking.StakeSnapshotting do
|> Enum.zip(stakers) |> Enum.zip(stakers)
|> Map.new(fn {key, val} -> {val, key} end) |> Map.new(fn {key, val} -> {val, key} end)
# to keep sort order # to keep sort order when using `perform_grouped_requests` (see below)
pool_staking_keys = Enum.map(pool_staking_responses, fn {key, _} -> key end) pool_staking_keys = Enum.map(pool_staking_responses, fn {key, _} -> key end)
# call `BlockReward.validatorShare` function for each pool
# to get validator's reward share of the pool (needed for the `Delegators` list in UI)
validator_reward_responses = validator_reward_responses =
pool_staking_responses pool_staking_responses
|> Enum.map(fn {_pool_staking_address, resp} -> |> Enum.map(fn {_pool_staking_address, resp} ->
@ -111,9 +116,11 @@ defmodule Explorer.Staking.StakeSnapshotting do
end) end)
|> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi)
# to keep sort order # to keep sort order when using `perform_grouped_requests` (see below)
delegator_keys = Enum.map(staker_responses, fn {key, _} -> key end) delegator_keys = Enum.map(staker_responses, fn {key, _} -> key end)
# call `BlockReward.delegatorShare` function for each delegator
# to get their reward share of the pool (needed for the `Delegators` list in UI)
delegator_reward_responses = delegator_reward_responses =
staker_responses staker_responses
|> Enum.map(fn {{pool_staking_address, _staker_address}, resp} -> |> Enum.map(fn {{pool_staking_address, _staker_address}, resp} ->
@ -129,6 +136,7 @@ defmodule Explorer.Staking.StakeSnapshotting do
end) end)
|> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi) |> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi)
# form entries for updating the `staking_pools` table in DB
pool_entries = pool_entries =
Enum.map(pool_staking_addresses, fn pool_staking_address -> Enum.map(pool_staking_addresses, fn pool_staking_address ->
staking_resp = pool_staking_responses[pool_staking_address] staking_resp = pool_staking_responses[pool_staking_address]
@ -158,6 +166,7 @@ defmodule Explorer.Staking.StakeSnapshotting do
) )
end) end)
# form entries for updating the `staking_pools_delegators` table in DB
delegator_entries = delegator_entries =
Enum.map(staker_responses, fn {{pool_staking_address, staker_address}, resp} -> Enum.map(staker_responses, fn {{pool_staking_address, staker_address}, resp} ->
delegator_reward_resp = delegator_reward_responses[{pool_staking_address, staker_address}] delegator_reward_resp = delegator_reward_responses[{pool_staking_address, staker_address}]
@ -169,6 +178,7 @@ defmodule Explorer.Staking.StakeSnapshotting do
}) })
end) end)
# perform SQL queries
case Chain.import(%{ case Chain.import(%{
staking_pools: %{params: pool_entries, on_conflict: staking_pools_update(), clear_snapshotted_values: true}, staking_pools: %{params: pool_entries, on_conflict: staking_pools_update(), clear_snapshotted_values: true},
staking_pools_delegators: %{params: delegator_entries, on_conflict: staking_pools_delegators_update(), clear_snapshotted_values: true}, staking_pools_delegators: %{params: delegator_entries, on_conflict: staking_pools_delegators_update(), clear_snapshotted_values: true},

Loading…
Cancel
Save