From 411c650bf8ead0be488bf5822d6b133a47275fad Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Tue, 22 Oct 2019 16:54:57 +0300 Subject: [PATCH 01/75] Rename contract functions --- .../lib/explorer/staking/contract_reader.ex | 8 +-- .../lib/explorer/staking/contract_state.ex | 4 +- .../contracts_abi/posdao/StakingAuRa.json | 52 ++----------------- .../posdao/ValidatorSetAuRa.json | 2 +- 4 files changed, 12 insertions(+), 54 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 8c8271eab60d..35393dcc3395 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -7,7 +7,7 @@ defmodule Explorer.Staking.ContractReader do def global_requests do [ - token_contract_address: {:staking, "erc20TokenContract", []}, + token_contract_address: {:staking, "erc677TokenContract", []}, min_candidate_stake: {:staking, "candidateMinStake", []}, min_delegator_stake: {:staking, "delegatorMinStake", []}, epoch_number: {:staking, "stakingEpoch", []}, @@ -29,8 +29,8 @@ defmodule Explorer.Staking.ContractReader do is_active: {:staking, "isPoolActive", [staking_address]}, active_delegators: {:staking, "poolDelegators", [staking_address]}, inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]}, - staked_amount: {:staking, "stakeAmountTotalMinusOrderedWithdraw", [staking_address]}, - self_staked_amount: {:staking, "stakeAmountMinusOrderedWithdraw", [staking_address, staking_address]}, + staked_amount: {:staking, "stakeAmountTotal", [staking_address]}, + self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address]}, block_reward: {:block_reward, "validatorRewardPercent", [staking_address]}, stakers: {:block_reward, "snapshotStakers", [staking_address]}, reward_percents: {:block_reward, "snapshotRewardPercents", [staking_address]} @@ -51,7 +51,7 @@ defmodule Explorer.Staking.ContractReader do def delegator_requests(pool_address, delegator_address) do [ - stake_amount: {:staking, "stakeAmountMinusOrderedWithdraw", [pool_address, delegator_address]}, + stake_amount: {:staking, "stakeAmount", [pool_address, delegator_address]}, ordered_withdraw: {:staking, "orderedWithdrawAmount", [pool_address, delegator_address]}, max_withdraw_allowed: {:staking, "maxWithdrawAllowed", [pool_address, delegator_address]}, max_ordered_withdraw_allowed: {:staking, "maxWithdrawOrderAllowed", [pool_address, delegator_address]}, diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index b717706f40ac..c1da32cdabed 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -67,11 +67,11 @@ defmodule Explorer.Staking.ContractState do %{ "validatorSetContract" => {:ok, [validator_set_contract_address]}, - "erc20TokenContract" => {:ok, [token_contract_address]} + "erc677TokenContract" => {:ok, [token_contract_address]} } = Reader.query_contract(staking_contract_address, staking_abi, %{ "validatorSetContract" => [], - "erc20TokenContract" => [] + "erc677TokenContract" => [] }) %{"blockRewardContract" => {:ok, [block_reward_contract_address]}} = diff --git a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json index 77fc815d2150..0f96e7cc68f2 100644 --- a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json @@ -22,25 +22,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "stakeAmountTotal", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [], @@ -105,7 +86,7 @@ { "constant": true, "inputs": [], - "name": "erc20TokenContract", + "name": "erc677TokenContract", "outputs": [ { "name": "", @@ -176,29 +157,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "address" - } - ], - "name": "stakeAmount", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [ @@ -778,11 +736,11 @@ "constant": false, "inputs": [ { - "name": "_erc20TokenContract", + "name": "_erc677TokenContract", "type": "address" } ], - "name": "setErc20TokenContract", + "name": "setErc677TokenContract", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -1083,7 +1041,7 @@ "type": "address" } ], - "name": "stakeAmountMinusOrderedWithdraw", + "name": "stakeAmount", "outputs": [ { "name": "", @@ -1102,7 +1060,7 @@ "type": "address" } ], - "name": "stakeAmountTotalMinusOrderedWithdraw", + "name": "stakeAmountTotal", "outputs": [ { "name": "", diff --git a/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json b/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json index 3269bd5c9fca..44d93c75803b 100644 --- a/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json @@ -78,7 +78,7 @@ "type": "address" } ], - "name": "isValidatorOnPreviousEpoch", + "name": "isValidatorPrevious", "outputs": [ { "name": "", From fcfa8d1dfd64d5bc1a4c65ed6dcb123f45d7d02c Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Tue, 22 Oct 2019 16:58:50 +0300 Subject: [PATCH 02/75] Rename contract events --- .../priv/contracts_abi/posdao/StakingAuRa.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json index 0f96e7cc68f2..09612a31f7d1 100644 --- a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json @@ -378,7 +378,7 @@ "type": "uint256" } ], - "name": "Claimed", + "name": "ClaimedOrderedWithdrawal", "type": "event" }, { @@ -405,7 +405,7 @@ "type": "uint256" } ], - "name": "Staked", + "name": "PlacedStake", "type": "event" }, { @@ -437,7 +437,7 @@ "type": "uint256" } ], - "name": "StakeMoved", + "name": "MovedStake", "type": "event" }, { @@ -464,7 +464,7 @@ "type": "int256" } ], - "name": "WithdrawalOrdered", + "name": "OrderedWithdrawal", "type": "event" }, { @@ -491,7 +491,7 @@ "type": "uint256" } ], - "name": "Withdrawn", + "name": "WithdrewStake", "type": "event" }, { From a7bc950cc221d192f4074955fa09a93e38976a5f Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Tue, 22 Oct 2019 19:52:31 +0300 Subject: [PATCH 03/75] Delete contract functions --- .../contracts_abi/posdao/BlockRewardAuRa.json | 28 ------- .../contracts_abi/posdao/StakingAuRa.json | 74 ------------------- .../posdao/ValidatorSetAuRa.json | 37 ---------- 3 files changed, 139 deletions(-) diff --git a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json index f4d0ad316b8a..d56dd7fa8f97 100644 --- a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json @@ -1,18 +1,4 @@ [ - { - "constant": true, - "inputs": [], - "name": "DELEGATORS_ALIQUOT", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [], @@ -27,20 +13,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [], - "name": "isRewarding", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [ diff --git a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json index 09612a31f7d1..98b955b34f57 100644 --- a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json @@ -176,34 +176,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [], - "name": "STAKE_UNIT", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "erc20Restricted", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [], @@ -288,20 +260,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [], - "name": "MAX_DELEGATORS_PER_POOL", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [ @@ -512,20 +470,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_miningAddress", - "type": "address" - } - ], - "name": "addPoolNative", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, { "constant": false, "inputs": [ @@ -579,10 +523,6 @@ { "name": "_stakeWithdrawDisallowPeriod", "type": "uint256" - }, - { - "name": "_erc20Restricted", - "type": "bool" } ], "name": "initialize", @@ -668,20 +608,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_toPoolStakingAddress", - "type": "address" - } - ], - "name": "stakeNative", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, { "constant": false, "inputs": [ diff --git a/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json b/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json index 44d93c75803b..3ba4af685b24 100644 --- a/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json @@ -211,25 +211,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "validatorIndex", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [ @@ -584,24 +565,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [], - "name": "getQueueValidators", - "outputs": [ - { - "name": "miningAddresses", - "type": "address[]" - }, - { - "name": "newStakingEpoch", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [], From ceed09cf5f81a8fe8b421edfbbb51b357ca45c00 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Thu, 7 Nov 2019 17:21:02 +0200 Subject: [PATCH 04/75] Add fields to StakingPool and StakingPoolsDelegator required for stakes snapshotting --- .../lib/explorer/chain/import/runner/staking_pools.ex | 2 ++ .../chain/import/runner/staking_pools_delegators.ex | 1 + apps/explorer/lib/explorer/chain/staking_pool.ex | 6 +++++- .../lib/explorer/chain/staking_pools_delegator.ex | 4 +++- ...35401_add_snapshotting_fields_to_staking_pools.exs | 11 +++++++++++ ...819_add_snapshotting_fields_to_pool_delegators.exs | 10 ++++++++++ 6 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs create mode 100644 apps/explorer/priv/repo/migrations/20191101133819_add_snapshotting_fields_to_pool_delegators.exs diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 566fd5898729..2a2dda7fd8d7 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -134,6 +134,8 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do staked_ratio: fragment("EXCLUDED.staked_ratio"), self_staked_amount: fragment("EXCLUDED.self_staked_amount"), staked_amount: fragment("EXCLUDED.staked_amount"), + snapshotted_self_staked_amount: fragment("EXCLUDED.self_staked_amount"), + snapshotted_staked_amount: fragment("EXCLUDED.staked_amount"), ban_reason: fragment("EXCLUDED.ban_reason"), was_banned_count: fragment("EXCLUDED.was_banned_count"), was_validator_count: fragment("EXCLUDED.was_validator_count"), diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex index 82949ef876bd..856f9341e797 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex @@ -106,6 +106,7 @@ defmodule Explorer.Chain.Import.Runner.StakingPoolsDelegators do update: [ set: [ stake_amount: fragment("EXCLUDED.stake_amount"), + snapshotted_stake_amount: fragment("EXCLUDED.snapshotted_stake_amount"), ordered_withdraw: fragment("EXCLUDED.ordered_withdraw"), max_withdraw_allowed: fragment("EXCLUDED.max_withdraw_allowed"), max_ordered_withdraw_allowed: fragment("EXCLUDED.max_ordered_withdraw_allowed"), diff --git a/apps/explorer/lib/explorer/chain/staking_pool.ex b/apps/explorer/lib/explorer/chain/staking_pool.ex index f7e10ba14474..7565a9442756 100644 --- a/apps/explorer/lib/explorer/chain/staking_pool.ex +++ b/apps/explorer/lib/explorer/chain/staking_pool.ex @@ -28,6 +28,8 @@ defmodule Explorer.Chain.StakingPool do staked_ratio: Decimal.t(), self_staked_amount: Decimal.t(), staked_amount: Decimal.t(), + snapshotted_self_staked_amount: Decimal.t(), + snapshotted_staked_amount: Decimal.t(), ban_reason: String.t(), was_banned_count: integer, was_validator_count: integer, @@ -35,7 +37,7 @@ defmodule Explorer.Chain.StakingPool do } @attrs ~w( - is_active delegators_count staked_amount self_staked_amount is_validator + is_active delegators_count staked_amount self_staked_amount snapshotted_staked_amount snapshotted_self_staked_amount is_validator was_validator_count is_banned are_delegators_banned ban_reason was_banned_count banned_until banned_delegators_until likelihood staked_ratio staking_address_hash mining_address_hash block_reward_ratio is_unremovable @@ -60,6 +62,8 @@ defmodule Explorer.Chain.StakingPool do field(:staked_ratio, :decimal) field(:self_staked_amount, :decimal) field(:staked_amount, :decimal) + field(:snapshotted_self_staked_amount, :decimal) + field(:snapshotted_staked_amount, :decimal) field(:ban_reason, :string) field(:was_banned_count, :integer) field(:was_validator_count, :integer) diff --git a/apps/explorer/lib/explorer/chain/staking_pools_delegator.ex b/apps/explorer/lib/explorer/chain/staking_pools_delegator.ex index af90f6ab73c3..5f91fbfbe1ae 100644 --- a/apps/explorer/lib/explorer/chain/staking_pools_delegator.ex +++ b/apps/explorer/lib/explorer/chain/staking_pools_delegator.ex @@ -20,6 +20,7 @@ defmodule Explorer.Chain.StakingPoolsDelegator do ordered_withdraw: Decimal.t(), ordered_withdraw_epoch: integer(), stake_amount: Decimal.t(), + snapshotted_stake_amount: Decimal.t(), reward_ratio: Decimal.t(), is_active: boolean(), is_deleted: boolean() @@ -27,7 +28,7 @@ defmodule Explorer.Chain.StakingPoolsDelegator do @attrs ~w( pool_address_hash delegator_address_hash max_ordered_withdraw_allowed - max_withdraw_allowed ordered_withdraw stake_amount ordered_withdraw_epoch + max_withdraw_allowed ordered_withdraw stake_amount snapshotted_stake_amount ordered_withdraw_epoch reward_ratio is_active is_deleted )a @@ -43,6 +44,7 @@ defmodule Explorer.Chain.StakingPoolsDelegator do field(:ordered_withdraw, :decimal) field(:ordered_withdraw_epoch, :integer) field(:stake_amount, :decimal) + field(:snapshotted_stake_amount, :decimal) field(:reward_ratio, :decimal) field(:is_active, :boolean, default: true) field(:is_deleted, :boolean, default: false) diff --git a/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs b/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs new file mode 100644 index 000000000000..d7fe5a2e0492 --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs @@ -0,0 +1,11 @@ +defmodule Explorer.Repo.Migrations.AddSnapshottingFieldsToStakingPools do + use Ecto.Migration + + def change do + alter table(:staking_pools) do + add(:snapshotted_staked_amount, :numeric, precision: 100) + add(:snapshotted_self_staked_amount, :numeric, precision: 100) + add(:snapshotted_staked_ratio, :decimal, precision: 5, scale: 2) + end + end +end diff --git a/apps/explorer/priv/repo/migrations/20191101133819_add_snapshotting_fields_to_pool_delegators.exs b/apps/explorer/priv/repo/migrations/20191101133819_add_snapshotting_fields_to_pool_delegators.exs new file mode 100644 index 000000000000..14f3997cfebd --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20191101133819_add_snapshotting_fields_to_pool_delegators.exs @@ -0,0 +1,10 @@ +defmodule Explorer.Repo.Migrations.AddSnapshottingFieldsToPoolDelegators do + use Ecto.Migration + + def change do + alter table(:staking_pools_delegators) do + add(:snapshotted_stake_amount, :numeric, precision: 100) + add(:snapshotted_reward_ratio, :decimal, precision: 5, scale: 2) + end + end +end From 21dbc70fa926baa575a23e83579151d3b6a0bc13 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Tue, 5 Nov 2019 17:23:07 +0200 Subject: [PATCH 05/75] Remove chain based stakes snapshotting porcess --- .../js/pages/stakes/become_candidate.js | 7 +- .../lib/explorer/staking/contract_reader.ex | 12 +-- .../lib/explorer/staking/contract_state.ex | 78 +----------------- .../contracts_abi/posdao/BlockRewardAuRa.json | 80 ------------------- 4 files changed, 3 insertions(+), 174 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes/become_candidate.js b/apps/block_scout_web/assets/js/pages/stakes/become_candidate.js index 89c1baa1e51f..ea4ee78353c5 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/become_candidate.js +++ b/apps/block_scout_web/assets/js/pages/stakes/become_candidate.js @@ -39,18 +39,13 @@ async function becomeCandidate ($modal, store, msg) { lockModal($modal) const stakingContract = store.getState().stakingContract - const blockRewardContract = store.getState().blockRewardContract const decimals = store.getState().tokenDecimals const stake = new BigNumber($modal.find('[candidate-stake]').val().replace(',', '.').trim()).shiftedBy(decimals).integerValue() const miningAddress = $modal.find('[mining-address]').val().trim().toLowerCase() try { if (!await stakingContract.methods.areStakeAndWithdrawAllowed().call()) { - if (await blockRewardContract.methods.isSnapshotting().call()) { - openErrorModal('Error', 'Staking actions are temporarily restricted. Please try again in a few blocks.') - } else { - openErrorModal('Error', 'The current staking epoch is ending, and staking actions are temporarily restricted. Please try again when the new epoch starts.') - } + openErrorModal('Error', 'The current staking epoch is ending, and staking actions are temporarily restricted. Please try again when the new epoch starts.') return false } diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 35393dcc3395..08a4c2e3fece 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -31,9 +31,7 @@ defmodule Explorer.Staking.ContractReader do inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]}, staked_amount: {:staking, "stakeAmountTotal", [staking_address]}, self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address]}, - block_reward: {:block_reward, "validatorRewardPercent", [staking_address]}, - stakers: {:block_reward, "snapshotStakers", [staking_address]}, - reward_percents: {:block_reward, "snapshotRewardPercents", [staking_address]} + block_reward: {:block_reward, "validatorRewardPercent", [staking_address]} ] end @@ -59,14 +57,6 @@ defmodule Explorer.Staking.ContractReader do ] end - def pools_snapshot_requests(block_number) do - [staking_addresses: {:block_reward, "snapshotStakingAddresses", [], block_number}] - end - - def stakers_snapshot_requests(pool_address, block_number) do - [{pool_address, {:block_reward, "snapshotStakers", [pool_address], block_number}}] - end - def perform_requests(requests, contracts, abi) do requests |> generate_requests(contracts) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index c1da32cdabed..1671b9e65741 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -11,7 +11,6 @@ defmodule Explorer.Staking.ContractState do alias Explorer.Chain.Events.{Publisher, Subscriber} alias Explorer.SmartContract.Reader alias Explorer.Staking.ContractReader - alias Explorer.Token.{BalanceReader, MetadataRetriever} @table_name __MODULE__ @table_keys [ @@ -158,11 +157,6 @@ defmodule Explorer.Staking.ContractState do Enum.map(responses.inactive_delegators, &{pool_address, &1, false}) end) - delegator_rewards = - Enum.into(pool_staking_responses, %{}, fn {pool_address, responses} -> - {pool_address, Enum.into(Enum.zip(responses.stakers, responses.reward_percents), %{})} - end) - delegator_responses = delegators |> Enum.map(fn {pool_address, delegator_address, _} -> @@ -219,27 +213,10 @@ defmodule Explorer.Staking.ContractState do delegator_entries = Enum.map(delegator_responses, fn {{pool_address, delegator_address, is_active}, response} -> - staking_response = pool_staking_responses[pool_address] - - reward_ratio = - if is_validator[staking_response.mining_address_hash] do - reward_ratio = delegator_rewards[pool_address][delegator_address] - - if reward_ratio do - reward_ratio / 10_000 - end - else - ratio( - response.stake_amount - response.ordered_withdraw, - staking_response.staked_amount - staking_response.self_staked_amount - ) * min(0.7, 1 - staking_response.block_reward / 1_000_000) - end - Map.merge(response, %{ delegator_address_hash: delegator_address, pool_address_hash: pool_address, - is_active: is_active, - reward_ratio: reward_ratio + is_active: is_active }) end) @@ -250,64 +227,11 @@ defmodule Explorer.Staking.ContractState do timeout: :infinity }) - if token && previous_epoch != global_responses.epoch_number do - update_tokens(token.contract_address_hash, contracts, abi, global_responses.epoch_start_block - 1, block_number) end Publisher.broadcast(:staking_update) end - defp update_tokens(token_contract_address_hash, contracts, abi, last_epoch_block_number, block_number) do - now = DateTime.utc_now() - - token_params = - token_contract_address_hash - |> MetadataRetriever.get_functions_of() - |> Map.merge(%{ - contract_address_hash: token_contract_address_hash, - type: "ERC-20" - }) - - addresses = - block_number - |> ContractReader.pools_snapshot_requests() - |> ContractReader.perform_requests(contracts, abi) - |> Map.fetch!(:staking_addresses) - |> Enum.flat_map(&ContractReader.stakers_snapshot_requests(&1, last_epoch_block_number)) - |> ContractReader.perform_requests(contracts, abi) - |> Map.values() - |> List.flatten() - |> Enum.uniq() - - balance_params = - addresses - |> Enum.map( - &%{ - token_contract_address_hash: token_contract_address_hash, - address_hash: &1, - block_number: block_number - } - ) - |> BalanceReader.get_balances_of() - |> Enum.zip(addresses) - |> Enum.map(fn {{:ok, balance}, address} -> - %{ - address_hash: address, - token_contract_address_hash: token_contract_address_hash, - block_number: block_number, - value: balance, - value_fetched_at: now - } - end) - - {:ok, _} = - Chain.import(%{ - addresses: %{params: Enum.map(addresses, &%{hash: &1}), on_conflict: :nothing}, - address_current_token_balances: %{params: balance_params}, - tokens: %{params: [token_params]} - }) - end - defp get_token(address) do with {:ok, address_hash} <- Chain.string_to_address_hash(address), {:ok, token} <- Chain.token_from_address_hash(address_hash) do diff --git a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json index d56dd7fa8f97..1b6076b8b8f0 100644 --- a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json @@ -139,20 +139,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [], - "name": "isSnapshotting", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [ @@ -223,20 +209,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [], - "name": "snapshotTotalStakeAmount", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [ @@ -530,58 +502,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "name": "_validatorStakingAddress", - "type": "address" - } - ], - "name": "snapshotRewardPercents", - "outputs": [ - { - "name": "result", - "type": "uint256[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_validatorStakingAddress", - "type": "address" - } - ], - "name": "snapshotStakers", - "outputs": [ - { - "name": "result", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "snapshotStakingAddresses", - "outputs": [ - { - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [ From 224f5cbabbcd521455e1b89711d2b1ef89701fc6 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Tue, 5 Nov 2019 18:53:40 +0200 Subject: [PATCH 06/75] Add blockscout based stakes snapshottting process --- .../lib/explorer/staking/contract_reader.ex | 4 +- .../lib/explorer/staking/contract_state.ex | 4 +- .../explorer/staking/stake_snapshotting.ex | 194 ++++++++++++++++++ .../posdao/ValidatorSetAuRa.json | 16 +- 4 files changed, 215 insertions(+), 3 deletions(-) create mode 100644 apps/explorer/lib/explorer/staking/stake_snapshotting.ex diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 08a4c2e3fece..16f5fe56790c 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -19,7 +19,9 @@ defmodule Explorer.Staking.ContractReader do pools_likely: {:staking, "getPoolsToBeElected", []}, pools_likelihood: {:staking, "getPoolsLikelihood", []}, validators: {:validator_set, "getValidators", []}, - unremovable_validator: {:validator_set, "unremovableValidator", []} + unremovable_validator: {:validator_set, "unremovableValidator", []}, + pending_validators: {:validator_set, "getPendingValidators", []}, + be_finalized_validators: {:validator_set, "validatorsToBeFinalized", []} ] end diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 1671b9e65741..c8fea7c7642f 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -10,7 +10,7 @@ defmodule Explorer.Staking.ContractState do alias Explorer.Chain alias Explorer.Chain.Events.{Publisher, Subscriber} alias Explorer.SmartContract.Reader - alias Explorer.Staking.ContractReader + alias Explorer.Staking.{ContractReader, StakeSnapshotting} @table_name __MODULE__ @table_keys [ @@ -227,6 +227,8 @@ defmodule Explorer.Staking.ContractState do timeout: :infinity }) + if previous_epoch && previous_epoch != 0 && previous_epoch != global_responses.epoch_number do + Supervisor.start_link([{StakeSnapshotting, block_number: block_number}], strategy: :one_for_all) end Publisher.broadcast(:staking_update) diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex new file mode 100644 index 000000000000..3b79a2e69881 --- /dev/null +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -0,0 +1,194 @@ +defmodule Explorer.Staking.StakeSnapshotting do + @moduledoc """ + Need to store stakeAmount from previous block in the beginning of new epoch. + for validators + params: + current block number + + """ + + use GenServer + + alias Explorer.Chain + alias Explorer.SmartContract.Reader + alias Explorer.Staking.ContractReader + + defstruct [ + :block_number, + :contracts, + :abi + ] + + def start_link(opts) do + {block_number, _opts} = Keyword.pop(opts, :block_number) + GenServer.start_link(__MODULE__, block_number, name: __MODULE__) + end + + def init(block_number) do + staking_abi = abi("StakingAuRa") + validator_set_abi = abi("ValidatorSetAuRa") + block_reward_abi = abi("BlockRewardAuRa") + + staking_contract_address = Application.get_env(:explorer, Explorer.Staking.ContractState)[:staking_contract_address] + + %{"validatorSetContract" => {:ok, [validator_set_contract_address]}} = + Reader.query_contract(staking_contract_address, staking_abi, %{"validatorSetContract" => []}) + + %{"blockRewardContract" => {:ok, [block_reward_contract_address]}} = + Reader.query_contract(validator_set_contract_address, validator_set_abi, %{"blockRewardContract" => []}) + + state = %__MODULE__{ + block_number: block_number, + contracts: %{ + staking: staking_contract_address, + validator_set: validator_set_contract_address, + block_reward: block_reward_contract_address + }, + abi: staking_abi ++ validator_set_abi ++ block_reward_abi + } + + {:ok, state, {:continue, []}} + end + + def handle_continue(_, state) do + start_snapshoting(state) + {:noreply, state} + end + + defp start_snapshoting(%{contracts: contracts, abi: abi, block_number: block_number} = _state) do + %{ + "getPendingValidators" => {:ok, [pending_validators_mining_addresses]}, + "validatorsToBeFinalized" => {:ok, [be_finalized_validators_mining_addresses]} + } = + Reader.query_contract(contracts.validator_set, abi, %{ + "getPendingValidators" => [], + "validatorsToBeFinalized" => [] + }) + + pool_mining_addresses = pending_validators_mining_addresses ++ be_finalized_validators_mining_addresses + + pool_staking_addresses = + pool_mining_addresses + |> Enum.map(&transform_requests/1) + |> ContractReader.perform_grouped_requests(pool_mining_addresses, contracts, abi) + |> Enum.flat_map(fn {_, value} -> value end) + |> Enum.map(fn {_key, staking_address_hash} -> decode_data(staking_address_hash) end) + + pool_staking_responses = + pool_staking_addresses + |> Enum.map(fn address_hashe -> pool_staking_requests(address_hashe, block_number) end) + |> ContractReader.perform_grouped_requests(pool_staking_addresses, contracts, abi) + + pool_mining_responses = + pool_staking_addresses + |> Enum.map(&ContractReader.pool_mining_requests(pool_staking_responses[&1].mining_address_hash)) + |> ContractReader.perform_grouped_requests(pool_staking_addresses, contracts, abi) + + delegators = + Enum.flat_map(pool_staking_responses, fn {pool_address, responses} -> + [{pool_address, pool_address, true}] ++ + Enum.map(responses.active_delegators, &{pool_address, &1, true}) ++ + Enum.map(responses.inactive_delegators, &{pool_address, &1, false}) + end) + + delegator_responses = + delegators + |> Enum.map(fn {pool_address, delegator_address, _} -> + delegator_requests(pool_address, delegator_address, block_number) + end) + |> ContractReader.perform_grouped_requests(delegators, contracts, abi) + + pool_entries = + Enum.map(pool_staking_addresses, fn staking_address -> + staking_response = pool_staking_responses[staking_address] + mining_response = pool_mining_responses[staking_address] + + %{ + staking_address_hash: staking_address, + delegators_count: length(staking_response.active_delegators) + } + |> Map.merge( + Map.take(staking_response, [ + :snapshotted_staked_amount, + :snapshotted_self_staked_amount, + :staked_amount, + :self_staked_amount, + :mining_address_hash + ]) + ) + |> Map.merge( + Map.take(mining_response, [ + :was_validator_count, + :was_banned_count, + :banned_until + ]) + ) + end) + + delegator_entries = + Enum.map(delegator_responses, fn {{pool_address, delegator_address, is_active}, response} -> + # staking_response = pool_staking_responses[pool_address] + + Map.merge(response, %{ + delegator_address_hash: delegator_address, + pool_address_hash: pool_address, + is_active: is_active + }) + end) + + {:ok, _} = + Chain.import(%{ + staking_pools: %{params: pool_entries}, + staking_pools_delegators: %{params: delegator_entries}, + timeout: :infinity + }) + end + + def transform_requests(minig_address) do + [ + staking_address: {:validator_set, "stakingByMiningAddress", [minig_address]} + ] + end + + defp pool_staking_requests(staking_address, block_number) do + [ + snapshotted_staked_amount: {:staking, "stakeAmountTotal", [staking_address], block_number - 1}, + snapshotted_self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address], block_number - 1}, + staked_amount: {:staking, "stakeAmountTotal", [staking_address]}, + self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address]}, + mining_address_hash: {:validator_set, "miningByStakingAddress", [staking_address]}, + active_delegators: {:staking, "poolDelegators", [staking_address]}, + inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]} + ] + end + + defp delegator_requests(pool_address, delegator_address, block_number) do + [ + stake_amount: {:staking, "stakeAmount", [pool_address, delegator_address]}, + snapshotted_staked_amount: {:staking, "stakeAmount", [pool_address, delegator_address], block_number - 1}, + ordered_withdraw: {:staking, "orderedWithdrawAmount", [pool_address, delegator_address]}, + max_withdraw_allowed: {:staking, "maxWithdrawAllowed", [pool_address, delegator_address]}, + max_ordered_withdraw_allowed: {:staking, "maxWithdrawOrderAllowed", [pool_address, delegator_address]}, + ordered_withdraw_epoch: {:staking, "orderWithdrawEpoch", [pool_address, delegator_address]} + ] + end + + defp abi(file_name) do + :explorer + |> Application.app_dir("priv/contracts_abi/posdao/#{file_name}.json") + |> File.read!() + |> Jason.decode!() + end + + defp decode_data(address_hash_string) do + { + :ok, + %Chain.Hash{ + byte_count: _, + bytes: bytes + } + } = Chain.string_to_address_hash(address_hash_string) + + bytes + end +end diff --git a/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json b/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json index 3ba4af685b24..fcfd9237bc2a 100644 --- a/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json @@ -557,7 +557,21 @@ "name": "getPendingValidators", "outputs": [ { - "name": "", + "name": "_miningAddress", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "validatorsToBeFinalized", + "outputs": [ + { + "name": "_miningAddress", "type": "address[]" } ], From 98a4a696d18f1b8c5acd8acb311fc5258e82a574 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Wed, 6 Nov 2019 16:33:58 +0200 Subject: [PATCH 07/75] Exclude snapshotted fields from being nilified --- .../lib/explorer/chain/import/runner/staking_pools.ex | 4 ++-- .../explorer/chain/import/runner/staking_pools_delegators.ex | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 2a2dda7fd8d7..35ccea981a0d 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -134,8 +134,8 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do staked_ratio: fragment("EXCLUDED.staked_ratio"), self_staked_amount: fragment("EXCLUDED.self_staked_amount"), staked_amount: fragment("EXCLUDED.staked_amount"), - snapshotted_self_staked_amount: fragment("EXCLUDED.self_staked_amount"), - snapshotted_staked_amount: fragment("EXCLUDED.staked_amount"), + snapshotted_self_staked_amount: pool.snapshotted_self_staked_amount, + snapshotted_staked_amount: pool.snapshotted_staked_amount, ban_reason: fragment("EXCLUDED.ban_reason"), was_banned_count: fragment("EXCLUDED.was_banned_count"), was_validator_count: fragment("EXCLUDED.was_validator_count"), diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex index 856f9341e797..53cfeef4e326 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex @@ -106,7 +106,7 @@ defmodule Explorer.Chain.Import.Runner.StakingPoolsDelegators do update: [ set: [ stake_amount: fragment("EXCLUDED.stake_amount"), - snapshotted_stake_amount: fragment("EXCLUDED.snapshotted_stake_amount"), + snapshotted_stake_amount: delegator.snapshotted_stake_amount, ordered_withdraw: fragment("EXCLUDED.ordered_withdraw"), max_withdraw_allowed: fragment("EXCLUDED.max_withdraw_allowed"), max_ordered_withdraw_allowed: fragment("EXCLUDED.max_ordered_withdraw_allowed"), From 2d6f8e9c5898ab558d83d938a06fbfe6e78cd9e5 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Fri, 8 Nov 2019 20:43:11 +0200 Subject: [PATCH 08/75] Update stake reward value defentions and add snapshotted stake reward --- .../chain/import/runner/staking_pools.ex | 1 + .../import/runner/staking_pools_delegators.ex | 1 + .../lib/explorer/chain/staking_pool.ex | 4 +- .../explorer/chain/staking_pools_delegator.ex | 5 +- .../lib/explorer/staking/contract_reader.ex | 14 +++ .../lib/explorer/staking/contract_state.ex | 37 +++++- .../explorer/staking/stake_snapshotting.ex | 112 +++++++++++++++++- .../contracts_abi/posdao/BlockRewardAuRa.json | 66 +++++++++++ 8 files changed, 225 insertions(+), 15 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 35ccea981a0d..7eecebea3dfe 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -132,6 +132,7 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do likelihood: fragment("EXCLUDED.likelihood"), block_reward_ratio: fragment("EXCLUDED.block_reward_ratio"), staked_ratio: fragment("EXCLUDED.staked_ratio"), + snapshotted_staked_ratio: pool.snapshotted_staked_ratio, self_staked_amount: fragment("EXCLUDED.self_staked_amount"), staked_amount: fragment("EXCLUDED.staked_amount"), snapshotted_self_staked_amount: pool.snapshotted_self_staked_amount, diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex index 53cfeef4e326..f1fa18664390 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex @@ -112,6 +112,7 @@ defmodule Explorer.Chain.Import.Runner.StakingPoolsDelegators do max_ordered_withdraw_allowed: fragment("EXCLUDED.max_ordered_withdraw_allowed"), ordered_withdraw_epoch: fragment("EXCLUDED.ordered_withdraw_epoch"), reward_ratio: fragment("EXCLUDED.reward_ratio"), + snapshotted_reward_ratio: delegator.snapshotted_reward_ratio, inserted_at: fragment("LEAST(?, EXCLUDED.inserted_at)", delegator.inserted_at), updated_at: fragment("GREATEST(?, EXCLUDED.updated_at)", delegator.updated_at), is_active: fragment("EXCLUDED.is_active"), diff --git a/apps/explorer/lib/explorer/chain/staking_pool.ex b/apps/explorer/lib/explorer/chain/staking_pool.ex index 7565a9442756..7414709cc45a 100644 --- a/apps/explorer/lib/explorer/chain/staking_pool.ex +++ b/apps/explorer/lib/explorer/chain/staking_pool.ex @@ -26,6 +26,7 @@ defmodule Explorer.Chain.StakingPool do likelihood: Decimal.t(), block_reward_ratio: Decimal.t(), staked_ratio: Decimal.t(), + snapshotted_staked_ratio: Decimal.t(), self_staked_amount: Decimal.t(), staked_amount: Decimal.t(), snapshotted_self_staked_amount: Decimal.t(), @@ -39,7 +40,7 @@ defmodule Explorer.Chain.StakingPool do @attrs ~w( is_active delegators_count staked_amount self_staked_amount snapshotted_staked_amount snapshotted_self_staked_amount is_validator was_validator_count is_banned are_delegators_banned ban_reason was_banned_count banned_until banned_delegators_until likelihood - staked_ratio staking_address_hash mining_address_hash block_reward_ratio + staked_ratio snapshotted_staked_ratio staking_address_hash mining_address_hash block_reward_ratio is_unremovable )a @req_attrs ~w( @@ -60,6 +61,7 @@ defmodule Explorer.Chain.StakingPool do field(:likelihood, :decimal) field(:block_reward_ratio, :decimal) field(:staked_ratio, :decimal) + field(:snapshotted_staked_ratio, :decimal) field(:self_staked_amount, :decimal) field(:staked_amount, :decimal) field(:snapshotted_self_staked_amount, :decimal) diff --git a/apps/explorer/lib/explorer/chain/staking_pools_delegator.ex b/apps/explorer/lib/explorer/chain/staking_pools_delegator.ex index 5f91fbfbe1ae..ae9c273bf7f8 100644 --- a/apps/explorer/lib/explorer/chain/staking_pools_delegator.ex +++ b/apps/explorer/lib/explorer/chain/staking_pools_delegator.ex @@ -22,6 +22,7 @@ defmodule Explorer.Chain.StakingPoolsDelegator do stake_amount: Decimal.t(), snapshotted_stake_amount: Decimal.t(), reward_ratio: Decimal.t(), + snapshotted_reward_ratio: Decimal.t(), is_active: boolean(), is_deleted: boolean() } @@ -29,13 +30,12 @@ defmodule Explorer.Chain.StakingPoolsDelegator do @attrs ~w( pool_address_hash delegator_address_hash max_ordered_withdraw_allowed max_withdraw_allowed ordered_withdraw stake_amount snapshotted_stake_amount ordered_withdraw_epoch - reward_ratio is_active is_deleted + reward_ratio snapshotted_reward_ratio is_active is_deleted )a @req_attrs ~w( pool_address_hash delegator_address_hash max_ordered_withdraw_allowed max_withdraw_allowed ordered_withdraw stake_amount ordered_withdraw_epoch - )a schema "staking_pools_delegators" do @@ -46,6 +46,7 @@ defmodule Explorer.Chain.StakingPoolsDelegator do field(:stake_amount, :decimal) field(:snapshotted_stake_amount, :decimal) field(:reward_ratio, :decimal) + field(:snapshotted_reward_ratio, :decimal) field(:is_active, :boolean, default: true) field(:is_deleted, :boolean, default: false) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 16f5fe56790c..1feff6c2838f 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -59,6 +59,20 @@ defmodule Explorer.Staking.ContractReader do ] end + # args = [staking_epoch, validator_staked, total_staked, pool_reward \\ 10_00000] + def pool_reward_requests(args) do + [ + validator_share: {:block_reward, "validatorShare", args}, + ] + end + + # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] + def delegator_reward_requests(args) do + [ + delegator_share: {:block_reward, "delegatorShare", args}, + ] + end + def perform_requests(requests, contracts, abi) do requests |> generate_requests(contracts) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index c8fea7c7642f..5116a5bef584 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -164,7 +164,6 @@ defmodule Explorer.Staking.ContractState do end) |> ContractReader.perform_grouped_requests(delegators, contracts, abi) - staked_total = Enum.sum(for {_, pool} <- pool_staking_responses, pool.is_active, do: pool.staked_amount) [likelihood_values, total_likelihood] = global_responses.pools_likelihood likelihood = @@ -172,18 +171,42 @@ defmodule Explorer.Staking.ContractState do |> Enum.zip(likelihood_values) |> Enum.into(%{}) + pool_reward_responses = + pool_staking_responses + |> Enum.map(fn {_address, response} -> + ContractReader.pool_reward_requests([ + global_responses.epoch_number, + response.self_staked_amount, + response.staked_amount, + 1000_000 + ]) + end) + |> ContractReader.perform_grouped_requests(pools, contracts, abi) + + delegator_reward_responses = + delegator_responses + |> Enum.map(fn {{pool_address, _, _}, response} -> + staking_response = pool_staking_responses[pool_address] + ContractReader.delegator_reward_requests([ + global_responses.epoch_number, + response.stake_amount, + staking_response.self_staked_amount, + staking_response.staked_amount, + 1000_000 + ]) + end) + |> ContractReader.perform_grouped_requests(delegators, contracts, abi) + pool_entries = Enum.map(pools, fn staking_address -> staking_response = pool_staking_responses[staking_address] mining_response = pool_mining_responses[staking_address] + pool_reward_response = pool_reward_responses[staking_address] %{ staking_address_hash: staking_address, delegators_count: length(staking_response.active_delegators), - staked_ratio: - if staking_response.is_active do - ratio(staking_response.staked_amount, staked_total) - end, + staked_ratio: pool_reward_response.validator_share / 10_000, likelihood: ratio(likelihood[staking_address] || 0, total_likelihood), block_reward_ratio: staking_response.block_reward / 10_000, is_deleted: false, @@ -213,10 +236,12 @@ defmodule Explorer.Staking.ContractState do delegator_entries = Enum.map(delegator_responses, fn {{pool_address, delegator_address, is_active}, response} -> + delegator_reward_response = delegator_reward_responses[{pool_address, delegator_address, is_active}] Map.merge(response, %{ delegator_address_hash: delegator_address, pool_address_hash: pool_address, - is_active: is_active + is_active: is_active, + reward_ratio: delegator_reward_response.delegator_share / 10_000 }) end) diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 3b79a2e69881..de2a32c38ccc 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -9,7 +9,10 @@ defmodule Explorer.Staking.StakeSnapshotting do use GenServer + import Ecto.Query, only: [from: 2] + alias Explorer.Chain + alias Explorer.Chain.{StakingPool, StakingPoolsDelegator} alias Explorer.SmartContract.Reader alias Explorer.Staking.ContractReader @@ -65,6 +68,7 @@ defmodule Explorer.Staking.StakeSnapshotting do "validatorsToBeFinalized" => [] }) + global_responses = ContractReader.perform_requests(ContractReader.global_requests(), contracts, abi) pool_mining_addresses = pending_validators_mining_addresses ++ be_finalized_validators_mining_addresses pool_staking_addresses = @@ -98,14 +102,40 @@ defmodule Explorer.Staking.StakeSnapshotting do end) |> ContractReader.perform_grouped_requests(delegators, contracts, abi) + pool_reward_responses = + pool_staking_responses + |> Enum.map(fn {_address, response} -> + ContractReader.pool_reward_requests([ + global_responses.epoch_number, + response.snapshotted_self_staked_amount, + response.snapshotted_staked_amount, + 1000_000]) + end) + |> ContractReader.perform_grouped_requests(pool_staking_addresses, contracts, abi) + + delegator_reward_responses = + delegator_responses + |> Enum.map(fn {{pool_address, _delegator_address, _}, response} -> + staking_response = pool_staking_responses[pool_address] + ContractReader.delegator_reward_requests([ + global_responses.epoch_number, + response.stake_amount, + staking_response.snapshotted_self_staked_amount, + staking_response.snapshotted_staked_amount, + 1000_000]) + end) + |> ContractReader.perform_grouped_requests(delegators, contracts, abi) + pool_entries = Enum.map(pool_staking_addresses, fn staking_address -> staking_response = pool_staking_responses[staking_address] mining_response = pool_mining_responses[staking_address] + pool_reward_response = pool_reward_responses[staking_address] %{ staking_address_hash: staking_address, - delegators_count: length(staking_response.active_delegators) + delegators_count: length(staking_response.active_delegators), + snapshotted_staked_ratio: pool_reward_response.validator_share / 10_000, } |> Map.merge( Map.take(staking_response, [ @@ -127,19 +157,20 @@ defmodule Explorer.Staking.StakeSnapshotting do delegator_entries = Enum.map(delegator_responses, fn {{pool_address, delegator_address, is_active}, response} -> - # staking_response = pool_staking_responses[pool_address] + delegator_reward_response = delegator_reward_responses[{pool_address, delegator_address, is_active}] Map.merge(response, %{ delegator_address_hash: delegator_address, pool_address_hash: pool_address, - is_active: is_active + is_active: is_active, + snapshotted_reward_ratio: delegator_reward_response.delegator_share / 10_000 }) end) {:ok, _} = Chain.import(%{ - staking_pools: %{params: pool_entries}, - staking_pools_delegators: %{params: delegator_entries}, + staking_pools: %{params: pool_entries, on_conflict: staking_pool_on_conflict()}, + staking_pools_delegators: %{params: delegator_entries, on_conflict: staking_pools_delegator_on_conflict()}, timeout: :infinity }) end @@ -165,7 +196,7 @@ defmodule Explorer.Staking.StakeSnapshotting do defp delegator_requests(pool_address, delegator_address, block_number) do [ stake_amount: {:staking, "stakeAmount", [pool_address, delegator_address]}, - snapshotted_staked_amount: {:staking, "stakeAmount", [pool_address, delegator_address], block_number - 1}, + snapshotted_stake_amount: {:staking, "stakeAmount", [pool_address, delegator_address], block_number - 1}, ordered_withdraw: {:staking, "orderedWithdrawAmount", [pool_address, delegator_address]}, max_withdraw_allowed: {:staking, "maxWithdrawAllowed", [pool_address, delegator_address]}, max_ordered_withdraw_allowed: {:staking, "maxWithdrawOrderAllowed", [pool_address, delegator_address]}, @@ -173,6 +204,75 @@ defmodule Explorer.Staking.StakeSnapshotting do ] end + # args = [staking_epoch, validator_staked, total_staked, pool_reward \\ 10_00000] + def pool_reward_requests(args, block_number) do + [ + validator_share: {:block_reward, "validatorShare", args, block_number - 1}, + ] + end + + # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] + def delegator_reward_requests(args, block_number) do + [ + delegator_share: {:block_reward, "delegatorShare", args, block_number - 1}, + ] + end + + defp staking_pool_on_conflict do + from( + pool in StakingPool, + update: [ + set: [ + mining_address_hash: fragment("EXCLUDED.mining_address_hash"), + delegators_count: fragment("EXCLUDED.delegators_count"), + is_active: fragment("EXCLUDED.is_active"), + is_banned: fragment("EXCLUDED.is_banned"), + is_validator: fragment("EXCLUDED.is_validator"), + is_unremovable: fragment("EXCLUDED.is_unremovable"), + are_delegators_banned: fragment("EXCLUDED.are_delegators_banned"), + likelihood: fragment("EXCLUDED.likelihood"), + block_reward_ratio: fragment("EXCLUDED.block_reward_ratio"), + staked_ratio: fragment("EXCLUDED.staked_ratio"), + snapshotted_staked_ratio: fragment("EXCLUDED.snapshotted_staked_ratio"), + self_staked_amount: fragment("EXCLUDED.self_staked_amount"), + staked_amount: fragment("EXCLUDED.staked_amount"), + snapshotted_self_staked_amount: fragment("EXCLUDED.snapshotted_self_staked_amount"), + snapshotted_staked_amount: fragment("EXCLUDED.snapshotted_staked_amount"), + ban_reason: fragment("EXCLUDED.ban_reason"), + was_banned_count: fragment("EXCLUDED.was_banned_count"), + was_validator_count: fragment("EXCLUDED.was_validator_count"), + is_deleted: fragment("EXCLUDED.is_deleted"), + banned_until: fragment("EXCLUDED.banned_until"), + banned_delegators_until: fragment("EXCLUDED.banned_delegators_until"), + inserted_at: fragment("LEAST(?, EXCLUDED.inserted_at)", pool.inserted_at), + updated_at: fragment("GREATEST(?, EXCLUDED.updated_at)", pool.updated_at) + ] + ] + ) + end + + defp staking_pools_delegator_on_conflict do + from( + delegator in StakingPoolsDelegator, + update: [ + set: [ + stake_amount: fragment("EXCLUDED.stake_amount"), + snapshotted_stake_amount: fragment("EXCLUDED.snapshotted_stake_amount"), + ordered_withdraw: fragment("EXCLUDED.ordered_withdraw"), + max_withdraw_allowed: fragment("EXCLUDED.max_withdraw_allowed"), + max_ordered_withdraw_allowed: fragment("EXCLUDED.max_ordered_withdraw_allowed"), + ordered_withdraw_epoch: fragment("EXCLUDED.ordered_withdraw_epoch"), + reward_ratio: fragment("EXCLUDED.reward_ratio"), + snapshotted_reward_ratio: fragment("EXCLUDED.snapshotted_reward_ratio"), + inserted_at: fragment("LEAST(?, EXCLUDED.inserted_at)", delegator.inserted_at), + updated_at: fragment("GREATEST(?, EXCLUDED.updated_at)", delegator.updated_at), + is_active: fragment("EXCLUDED.is_active"), + is_deleted: fragment("EXCLUDED.is_deleted") + ] + ] + ) + end + defp abi(file_name) do :explorer |> Application.app_dir("priv/contracts_abi/posdao/#{file_name}.json") diff --git a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json index 1b6076b8b8f0..6cabc8bcb233 100644 --- a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json @@ -520,5 +520,71 @@ "payable": false, "stateMutability": "view", "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_stakingEpoch", + "type": "uint256" + }, + { + "name": "_validatorStaked", + "type": "uint256" + }, + { + "name": "_totalStaked", + "type": "uint256" + }, + { + "name": "_poolReward", + "type": "uint256" + } + ], + "name": "validatorShare", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_stakingEpoch", + "type": "uint256" + }, + { + "name": "_delegatorStaked", + "type": "uint256" + }, + { + "name": "_validatorStaked", + "type": "uint256" + }, + { + "name": "_totalStaked", + "type": "uint256" + }, + { + "name": "_poolReward", + "type": "uint256" + } + ], + "name": "delegatorShare", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" } ] From b7b9761f6161334ebd050c6aa5abf4f72e781c3c Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Fri, 8 Nov 2019 20:55:42 +0200 Subject: [PATCH 09/75] Change stake snapshotting to simple function --- .../lib/explorer/staking/contract_reader.ex | 4 +- .../lib/explorer/staking/contract_state.ex | 7 +- .../explorer/staking/stake_snapshotting.ex | 69 +++---------------- 3 files changed, 17 insertions(+), 63 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 1feff6c2838f..98ad146ad262 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -62,14 +62,14 @@ defmodule Explorer.Staking.ContractReader do # args = [staking_epoch, validator_staked, total_staked, pool_reward \\ 10_00000] def pool_reward_requests(args) do [ - validator_share: {:block_reward, "validatorShare", args}, + validator_share: {:block_reward, "validatorShare", args} ] end # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] def delegator_reward_requests(args) do [ - delegator_share: {:block_reward, "delegatorShare", args}, + delegator_share: {:block_reward, "delegatorShare", args} ] end diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 5116a5bef584..5d088317e3cd 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -187,6 +187,7 @@ defmodule Explorer.Staking.ContractState do delegator_responses |> Enum.map(fn {{pool_address, _, _}, response} -> staking_response = pool_staking_responses[pool_address] + ContractReader.delegator_reward_requests([ global_responses.epoch_number, response.stake_amount, @@ -237,6 +238,7 @@ defmodule Explorer.Staking.ContractState do delegator_entries = Enum.map(delegator_responses, fn {{pool_address, delegator_address, is_active}, response} -> delegator_reward_response = delegator_reward_responses[{pool_address, delegator_address, is_active}] + Map.merge(response, %{ delegator_address_hash: delegator_address, pool_address_hash: pool_address, @@ -253,7 +255,10 @@ defmodule Explorer.Staking.ContractState do }) if previous_epoch && previous_epoch != 0 && previous_epoch != global_responses.epoch_number do - Supervisor.start_link([{StakeSnapshotting, block_number: block_number}], strategy: :one_for_all) + StakeSnapshotting.start_snapshoting( + %{contracts: contracts, abi: abi, global_responses: global_responses}, + block_number + ) end Publisher.broadcast(:staking_update) diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index de2a32c38ccc..f751eca5e6f0 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -2,13 +2,9 @@ defmodule Explorer.Staking.StakeSnapshotting do @moduledoc """ Need to store stakeAmount from previous block in the beginning of new epoch. for validators - params: - current block number """ - use GenServer - import Ecto.Query, only: [from: 2] alias Explorer.Chain @@ -16,49 +12,7 @@ defmodule Explorer.Staking.StakeSnapshotting do alias Explorer.SmartContract.Reader alias Explorer.Staking.ContractReader - defstruct [ - :block_number, - :contracts, - :abi - ] - - def start_link(opts) do - {block_number, _opts} = Keyword.pop(opts, :block_number) - GenServer.start_link(__MODULE__, block_number, name: __MODULE__) - end - - def init(block_number) do - staking_abi = abi("StakingAuRa") - validator_set_abi = abi("ValidatorSetAuRa") - block_reward_abi = abi("BlockRewardAuRa") - - staking_contract_address = Application.get_env(:explorer, Explorer.Staking.ContractState)[:staking_contract_address] - - %{"validatorSetContract" => {:ok, [validator_set_contract_address]}} = - Reader.query_contract(staking_contract_address, staking_abi, %{"validatorSetContract" => []}) - - %{"blockRewardContract" => {:ok, [block_reward_contract_address]}} = - Reader.query_contract(validator_set_contract_address, validator_set_abi, %{"blockRewardContract" => []}) - - state = %__MODULE__{ - block_number: block_number, - contracts: %{ - staking: staking_contract_address, - validator_set: validator_set_contract_address, - block_reward: block_reward_contract_address - }, - abi: staking_abi ++ validator_set_abi ++ block_reward_abi - } - - {:ok, state, {:continue, []}} - end - - def handle_continue(_, state) do - start_snapshoting(state) - {:noreply, state} - end - - defp start_snapshoting(%{contracts: contracts, abi: abi, block_number: block_number} = _state) do + def start_snapshoting(%{contracts: contracts, abi: abi, global_responses: global_responses}, block_number) do %{ "getPendingValidators" => {:ok, [pending_validators_mining_addresses]}, "validatorsToBeFinalized" => {:ok, [be_finalized_validators_mining_addresses]} @@ -68,7 +22,6 @@ defmodule Explorer.Staking.StakeSnapshotting do "validatorsToBeFinalized" => [] }) - global_responses = ContractReader.perform_requests(ContractReader.global_requests(), contracts, abi) pool_mining_addresses = pending_validators_mining_addresses ++ be_finalized_validators_mining_addresses pool_staking_addresses = @@ -109,7 +62,8 @@ defmodule Explorer.Staking.StakeSnapshotting do global_responses.epoch_number, response.snapshotted_self_staked_amount, response.snapshotted_staked_amount, - 1000_000]) + 1000_000 + ]) end) |> ContractReader.perform_grouped_requests(pool_staking_addresses, contracts, abi) @@ -117,12 +71,14 @@ defmodule Explorer.Staking.StakeSnapshotting do delegator_responses |> Enum.map(fn {{pool_address, _delegator_address, _}, response} -> staking_response = pool_staking_responses[pool_address] + ContractReader.delegator_reward_requests([ global_responses.epoch_number, response.stake_amount, staking_response.snapshotted_self_staked_amount, staking_response.snapshotted_staked_amount, - 1000_000]) + 1000_000 + ]) end) |> ContractReader.perform_grouped_requests(delegators, contracts, abi) @@ -135,7 +91,7 @@ defmodule Explorer.Staking.StakeSnapshotting do %{ staking_address_hash: staking_address, delegators_count: length(staking_response.active_delegators), - snapshotted_staked_ratio: pool_reward_response.validator_share / 10_000, + snapshotted_staked_ratio: pool_reward_response.validator_share / 10_000 } |> Map.merge( Map.take(staking_response, [ @@ -207,14 +163,14 @@ defmodule Explorer.Staking.StakeSnapshotting do # args = [staking_epoch, validator_staked, total_staked, pool_reward \\ 10_00000] def pool_reward_requests(args, block_number) do [ - validator_share: {:block_reward, "validatorShare", args, block_number - 1}, + validator_share: {:block_reward, "validatorShare", args, block_number - 1} ] end # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] def delegator_reward_requests(args, block_number) do [ - delegator_share: {:block_reward, "delegatorShare", args, block_number - 1}, + delegator_share: {:block_reward, "delegatorShare", args, block_number - 1} ] end @@ -273,13 +229,6 @@ defmodule Explorer.Staking.StakeSnapshotting do ) end - defp abi(file_name) do - :explorer - |> Application.app_dir("priv/contracts_abi/posdao/#{file_name}.json") - |> File.read!() - |> Jason.decode!() - end - defp decode_data(address_hash_string) do { :ok, From 09f2776b6e3d5e1ebb4b77864b750eb25ec7c3b3 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Mon, 11 Nov 2019 18:04:54 +0200 Subject: [PATCH 10/75] Fix order for reward ratio responses --- .../lib/explorer/staking/contract_state.ex | 14 ++++-- .../explorer/staking/stake_snapshotting.ex | 44 ++++++++++--------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 5d088317e3cd..3a281bac9d7c 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -24,7 +24,8 @@ defmodule Explorer.Staking.ContractState do :staking_allowed, :staking_contract, :validator_set_contract, - :block_reward_contract + :block_reward_contract, + :validator_set_apply_block ] defstruct [ @@ -129,7 +130,8 @@ defmodule Explorer.Staking.ContractState do :epoch_number, :epoch_start_block, :epoch_end_block, - :staking_allowed + :staking_allowed, + :validator_set_apply_block ]) |> Map.to_list() |> Enum.concat(token: token) @@ -171,6 +173,8 @@ defmodule Explorer.Staking.ContractState do |> Enum.zip(likelihood_values) |> Enum.into(%{}) + pool_staking_keys = Enum.map(pool_staking_responses, fn {key, _response} -> key end) + pool_reward_responses = pool_staking_responses |> Enum.map(fn {_address, response} -> @@ -181,7 +185,9 @@ defmodule Explorer.Staking.ContractState do 1000_000 ]) end) - |> ContractReader.perform_grouped_requests(pools, contracts, abi) + |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) + + delegator_keys = Enum.map(delegator_responses, fn {key, _response} -> key end) delegator_reward_responses = delegator_responses @@ -196,7 +202,7 @@ defmodule Explorer.Staking.ContractState do 1000_000 ]) end) - |> ContractReader.perform_grouped_requests(delegators, contracts, abi) + |> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi) pool_entries = Enum.map(pools, fn staking_address -> diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index f751eca5e6f0..0189eb641610 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -55,6 +55,8 @@ defmodule Explorer.Staking.StakeSnapshotting do end) |> ContractReader.perform_grouped_requests(delegators, contracts, abi) + pool_staking_keys = Enum.map(pool_staking_responses, fn {key, _response} -> key end) + pool_reward_responses = pool_staking_responses |> Enum.map(fn {_address, response} -> @@ -65,7 +67,9 @@ defmodule Explorer.Staking.StakeSnapshotting do 1000_000 ]) end) - |> ContractReader.perform_grouped_requests(pool_staking_addresses, contracts, abi) + |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) + + delegator_keys = Enum.map(delegator_responses, fn {key, _response} -> key end) delegator_reward_responses = delegator_responses @@ -80,7 +84,7 @@ defmodule Explorer.Staking.StakeSnapshotting do 1000_000 ]) end) - |> ContractReader.perform_grouped_requests(delegators, contracts, abi) + |> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi) pool_entries = Enum.map(pool_staking_addresses, fn staking_address -> @@ -181,25 +185,25 @@ defmodule Explorer.Staking.StakeSnapshotting do set: [ mining_address_hash: fragment("EXCLUDED.mining_address_hash"), delegators_count: fragment("EXCLUDED.delegators_count"), - is_active: fragment("EXCLUDED.is_active"), - is_banned: fragment("EXCLUDED.is_banned"), - is_validator: fragment("EXCLUDED.is_validator"), - is_unremovable: fragment("EXCLUDED.is_unremovable"), - are_delegators_banned: fragment("EXCLUDED.are_delegators_banned"), - likelihood: fragment("EXCLUDED.likelihood"), - block_reward_ratio: fragment("EXCLUDED.block_reward_ratio"), - staked_ratio: fragment("EXCLUDED.staked_ratio"), snapshotted_staked_ratio: fragment("EXCLUDED.snapshotted_staked_ratio"), self_staked_amount: fragment("EXCLUDED.self_staked_amount"), staked_amount: fragment("EXCLUDED.staked_amount"), snapshotted_self_staked_amount: fragment("EXCLUDED.snapshotted_self_staked_amount"), snapshotted_staked_amount: fragment("EXCLUDED.snapshotted_staked_amount"), - ban_reason: fragment("EXCLUDED.ban_reason"), - was_banned_count: fragment("EXCLUDED.was_banned_count"), - was_validator_count: fragment("EXCLUDED.was_validator_count"), - is_deleted: fragment("EXCLUDED.is_deleted"), - banned_until: fragment("EXCLUDED.banned_until"), - banned_delegators_until: fragment("EXCLUDED.banned_delegators_until"), + is_active: pool.is_active, + is_banned: pool.is_banned, + is_validator: pool.is_validator, + is_unremovable: pool.is_unremovable, + are_delegators_banned: pool.are_delegators_banned, + likelihood: pool.likelihood, + block_reward_ratio: pool.block_reward_ratio, + staked_ratio: pool.staked_ratio, + ban_reason: pool.ban_reason, + was_banned_count: pool.was_banned_count, + was_validator_count: pool.was_validator_count, + banned_until: pool.banned_until, + is_deleted: pool.is_deleted, + banned_delegators_until: pool.banned_delegators_until, inserted_at: fragment("LEAST(?, EXCLUDED.inserted_at)", pool.inserted_at), updated_at: fragment("GREATEST(?, EXCLUDED.updated_at)", pool.updated_at) ] @@ -218,12 +222,12 @@ defmodule Explorer.Staking.StakeSnapshotting do max_withdraw_allowed: fragment("EXCLUDED.max_withdraw_allowed"), max_ordered_withdraw_allowed: fragment("EXCLUDED.max_ordered_withdraw_allowed"), ordered_withdraw_epoch: fragment("EXCLUDED.ordered_withdraw_epoch"), - reward_ratio: fragment("EXCLUDED.reward_ratio"), + reward_ratio: delegator.reward_ratio, snapshotted_reward_ratio: fragment("EXCLUDED.snapshotted_reward_ratio"), + is_active: delegator.is_active, + is_deleted: delegator.is_deleted, inserted_at: fragment("LEAST(?, EXCLUDED.inserted_at)", delegator.inserted_at), - updated_at: fragment("GREATEST(?, EXCLUDED.updated_at)", delegator.updated_at), - is_active: fragment("EXCLUDED.is_active"), - is_deleted: fragment("EXCLUDED.is_deleted") + updated_at: fragment("GREATEST(?, EXCLUDED.updated_at)", delegator.updated_at) ] ] ) From 3c9a5ed861dfc6c671923ea667112aa406504363 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Mon, 11 Nov 2019 18:06:33 +0200 Subject: [PATCH 11/75] =?UTF-8?q?Display=20=E2=80=9CAccounted=20Stake=20Am?= =?UTF-8?q?ount=E2=80=9D=20and=20=E2=80=9CCurrent=20Reward=20Percent?= =?UTF-8?q?=E2=80=9D=20in=20delegators=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assets/css/components/_stakes_table.scss | 1 + .../_stakes_modal_delegators_list.html.eex | 17 ++++++++++++----- .../templates/stakes/_stakes_th.html.eex | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/_stakes_table.scss b/apps/block_scout_web/assets/css/components/_stakes_table.scss index 38a46f161825..ded5ae30f0a3 100644 --- a/apps/block_scout_web/assets/css/components/_stakes_table.scss +++ b/apps/block_scout_web/assets/css/components/_stakes_table.scss @@ -118,6 +118,7 @@ $stakes-link-color: $primary !default; .stakes-th-text { margin-right: 10px; white-space: nowrap; + text-align: center; } .stakes-td { diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index 0b438e88e38c..1fb85bea152c 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -13,14 +13,14 @@ <%= render BlockScoutWeb.StakesView, "_stakes_th.html", title: gettext("Staker's Address"), tooltip: gettext("All pool participant addresses. The top address belongs to the validator.") %>
- <%= render BlockScoutWeb.StakesView, "_stakes_th.html", title: gettext("Total Stake Amount"), tooltip: gettext("Amount of STAKE placed by an address") %> + <%= render BlockScoutWeb.StakesView, "_stakes_th.html", title: gettext("Current Stake Amount") <> "
(" <> gettext("Accounted Stake Amount") <> ")", tooltip: gettext("Amount of STAKE placed by an address") %>
<%= - title = if @pool.is_validator do gettext("Reward Percent") else gettext("Potential Reward Percent") end + _title = if @pool.is_validator do gettext("Reward Percent") else gettext("Potential Reward Percent") end render BlockScoutWeb.StakesView, "_stakes_th.html", - title: title, + title: gettext("Potential Reward Percent") <> "
(" <> gettext("Current Reward Percent") <> ")", tooltip: gettext("Reward distribution is based on stake amount. Validator receives a minimum of 30%.") %>
@@ -52,8 +52,15 @@ <% end %> -
<%= format_token_amount(delegator.stake_amount, @token, symbol: false) %>
-
<%= if delegator.reward_ratio do "#{delegator.reward_ratio}%" else "-" end %>
+
<%= format_token_amount(delegator.stake_amount, @token, symbol: false) %> (<%= if delegator.snapshotted_stake_amount do format_token_amount(delegator.snapshotted_stake_amount, @token, symbol: false) else 0 end %>)
+
+ <%= if delegator.reward_ratio do %> + <%= delegator.reward_ratio %>% + (<%= if delegator.snapshotted_reward_ratio do "#{delegator.snapshotted_reward_ratio}%" else "0%" end %>) + <% else %> + - + <% end %> +
<% end %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_th.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_th.html.eex index bb44f76e9108..4a703cfe5492 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_th.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_th.html.eex @@ -1,6 +1,6 @@
- <%= @title %> + <%= raw(@title) %> <%= render BlockScoutWeb.CommonComponentsView, "_i_tooltip.html", text: @tooltip %>
\ No newline at end of file From 7048cfeaae4f9084564873ca288c794da235e59e Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Mon, 11 Nov 2019 18:28:42 +0200 Subject: [PATCH 12/75] Add validator_set_apply_block tcheck before display snapshotted data --- .../channels/stakes_channel.ex | 4 +- .../_stakes_modal_delegators_list.html.eex | 58 +++++++++++++++---- .../lib/explorer/staking/contract_reader.ex | 3 +- 3 files changed, 53 insertions(+), 12 deletions(-) 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 bcbd3309a48c..e8e0f0639d3b 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 @@ -54,6 +54,7 @@ defmodule BlockScoutWeb.StakesChannel do def handle_in("render_delegators_list", %{"address" => staking_address}, socket) do pool = Chain.staking_pool(staking_address) token = ContractState.get(:token) + validator_set_apply_block = ContractState.get(:validator_set_apply_block) delegators = staking_address @@ -73,7 +74,8 @@ defmodule BlockScoutWeb.StakesChannel do account: socket.assigns[:account], pool: pool, delegators: delegators, - token: token + token: token, + validator_set_apply_block: validator_set_apply_block ) {:reply, {:ok, %{html: html}}, socket} diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index 1fb85bea152c..0de8dccddc7c 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -13,14 +13,29 @@ <%= render BlockScoutWeb.StakesView, "_stakes_th.html", title: gettext("Staker's Address"), tooltip: gettext("All pool participant addresses. The top address belongs to the validator.") %>
- <%= render BlockScoutWeb.StakesView, "_stakes_th.html", title: gettext("Current Stake Amount") <> "
(" <> gettext("Accounted Stake Amount") <> ")", tooltip: gettext("Amount of STAKE placed by an address") %> + <%= + amount_col_title = + if @validator_set_apply_block > 0 do + gettext("Current Stake Amount") <> "
(" <> gettext("Accounted Stake Amount") <> ")" + else + gettext("Current Stake Amount") + end + + render BlockScoutWeb.StakesView, "_stakes_th.html", title: amount_col_title, tooltip: gettext("Amount of STAKE placed by an address") + %>
<%= - _title = if @pool.is_validator do gettext("Reward Percent") else gettext("Potential Reward Percent") end + reward_col_title = + if @pool.is_validator && @validator_set_apply_block > 0 do + gettext("Potential Reward Percent") <> "
(" <> gettext("Current Reward Percent") <> ")" + else + gettext("Potential Reward Percent") + end + render BlockScoutWeb.StakesView, "_stakes_th.html", - title: gettext("Potential Reward Percent") <> "
(" <> gettext("Current Reward Percent") <> ")", + title: reward_col_title, tooltip: gettext("Reward distribution is based on stake amount. Validator receives a minimum of 30%.") %>
@@ -52,14 +67,37 @@ <% end %> -
<%= format_token_amount(delegator.stake_amount, @token, symbol: false) %> (<%= if delegator.snapshotted_stake_amount do format_token_amount(delegator.snapshotted_stake_amount, @token, symbol: false) else 0 end %>)
+
+ <%= format_token_amount(delegator.stake_amount, @token, symbol: false) %> + <%= if @pool.is_validator && @validator_set_apply_block > 0 do %> + ( + <%= + if delegator.snapshotted_stake_amount do + format_token_amount(delegator.snapshotted_stake_amount, @token, symbol: false) + else + 0 + end + %> + ) + <% end %> +
- <%= if delegator.reward_ratio do %> - <%= delegator.reward_ratio %>% - (<%= if delegator.snapshotted_reward_ratio do "#{delegator.snapshotted_reward_ratio}%" else "0%" end %>) - <% else %> - - - <% end %> + <%= if delegator.reward_ratio do %> + <%= delegator.reward_ratio %>% + <%= if @pool.is_validator && @validator_set_apply_block > 0 do %> + ( + <%= + if delegator.snapshotted_reward_ratio do + "#{delegator.snapshotted_reward_ratio}%" + else + "0%" + end + %> + ) + <% end %> + <% else %> + - + <% end %>
<% end %> diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 98ad146ad262..e6ebe8627631 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -21,7 +21,8 @@ defmodule Explorer.Staking.ContractReader do validators: {:validator_set, "getValidators", []}, unremovable_validator: {:validator_set, "unremovableValidator", []}, pending_validators: {:validator_set, "getPendingValidators", []}, - be_finalized_validators: {:validator_set, "validatorsToBeFinalized", []} + be_finalized_validators: {:validator_set, "validatorsToBeFinalized", []}, + validator_set_apply_block: {:validator_set, "validatorSetApplyBlock", []} ] end From be8dfefc3a5e1863ed071830ace05bba518c7efc Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Tue, 12 Nov 2019 15:02:45 +0200 Subject: [PATCH 13/75] Get uniq pool mining addresses for snapshotting process --- apps/explorer/lib/explorer/staking/stake_snapshotting.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 0189eb641610..a4a09aeaf979 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -22,7 +22,7 @@ defmodule Explorer.Staking.StakeSnapshotting do "validatorsToBeFinalized" => [] }) - pool_mining_addresses = pending_validators_mining_addresses ++ be_finalized_validators_mining_addresses + pool_mining_addresses = Enum.uniq(pending_validators_mining_addresses ++ be_finalized_validators_mining_addresses) pool_staking_addresses = pool_mining_addresses From b0434f20e54de3cf46c0d1da212a6951030691f0 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Tue, 12 Nov 2019 17:55:31 +0200 Subject: [PATCH 14/75] Add is_snapshotted check before showing snapshotted data --- .../channels/stakes_channel.ex | 6 ++++-- .../_stakes_modal_delegators_list.html.eex | 10 +++++----- .../lib/explorer/staking/contract_state.ex | 20 +++++++++++++------ .../explorer/staking/stake_snapshotting.ex | 11 +++++----- 4 files changed, 28 insertions(+), 19 deletions(-) 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 e8e0f0639d3b..b883b1648e87 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 @@ -54,7 +54,9 @@ defmodule BlockScoutWeb.StakesChannel do def handle_in("render_delegators_list", %{"address" => staking_address}, socket) do pool = Chain.staking_pool(staking_address) token = ContractState.get(:token) - validator_set_apply_block = ContractState.get(:validator_set_apply_block) + + is_show_snapshotted_data = + pool.is_validator && ContractState.get(:validator_set_apply_block) > 0 && ContractState.get(:is_snapshotted) delegators = staking_address @@ -75,7 +77,7 @@ defmodule BlockScoutWeb.StakesChannel do pool: pool, delegators: delegators, token: token, - validator_set_apply_block: validator_set_apply_block + is_show_snapshotted_data: is_show_snapshotted_data ) {:reply, {:ok, %{html: html}}, socket} diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index 0de8dccddc7c..44c8129aed98 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -15,7 +15,7 @@
<%= amount_col_title = - if @validator_set_apply_block > 0 do + if @is_show_snapshotted_data do gettext("Current Stake Amount") <> "
(" <> gettext("Accounted Stake Amount") <> ")" else gettext("Current Stake Amount") @@ -27,7 +27,7 @@
<%= reward_col_title = - if @pool.is_validator && @validator_set_apply_block > 0 do + if @is_show_snapshotted_data do gettext("Potential Reward Percent") <> "
(" <> gettext("Current Reward Percent") <> ")" else gettext("Potential Reward Percent") @@ -69,11 +69,11 @@
<%= format_token_amount(delegator.stake_amount, @token, symbol: false) %> - <%= if @pool.is_validator && @validator_set_apply_block > 0 do %> + <%= if @is_show_snapshotted_data do %> ( <%= if delegator.snapshotted_stake_amount do - format_token_amount(delegator.snapshotted_stake_amount, @token, symbol: false) + format_token_amount(delegator.snapshotted_stake_amount, @token, symbol: false) else 0 end @@ -84,7 +84,7 @@
<%= if delegator.reward_ratio do %> <%= delegator.reward_ratio %>% - <%= if @pool.is_validator && @validator_set_apply_block > 0 do %> + <%= if @is_show_snapshotted_data do %> ( <%= if delegator.snapshotted_reward_ratio do diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 3a281bac9d7c..6c70149bec3b 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -25,7 +25,8 @@ defmodule Explorer.Staking.ContractState do :staking_contract, :validator_set_contract, :block_reward_contract, - :validator_set_apply_block + :validator_set_apply_block, + :is_snapshotted ] defstruct [ @@ -92,7 +93,8 @@ defmodule Explorer.Staking.ContractState do validator_set_contract: %{abi: validator_set_abi, address: validator_set_contract_address}, block_reward_contract: %{abi: block_reward_abi, address: block_reward_contract_address}, token_contract_address: token_contract_address, - token: get_token(token_contract_address) + token: get_token(token_contract_address), + is_snapshotted: false ) {:ok, state, {:continue, []}} @@ -261,10 +263,16 @@ defmodule Explorer.Staking.ContractState do }) if previous_epoch && previous_epoch != 0 && previous_epoch != global_responses.epoch_number do - StakeSnapshotting.start_snapshoting( - %{contracts: contracts, abi: abi, global_responses: global_responses}, - block_number - ) + with( + true <- :ets.insert(@table_name, is_snapshotted: false), + {:ok, _} <- + StakeSnapshotting.start_snapshoting( + %{contracts: contracts, abi: abi, global_responses: global_responses}, + block_number + ) + ) do + :ets.insert(@table_name, is_snapshotted: true) + end end Publisher.broadcast(:staking_update) diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index a4a09aeaf979..cbcf76e8c6b1 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -127,12 +127,11 @@ defmodule Explorer.Staking.StakeSnapshotting do }) end) - {:ok, _} = - Chain.import(%{ - staking_pools: %{params: pool_entries, on_conflict: staking_pool_on_conflict()}, - staking_pools_delegators: %{params: delegator_entries, on_conflict: staking_pools_delegator_on_conflict()}, - timeout: :infinity - }) + Chain.import(%{ + staking_pools: %{params: pool_entries, on_conflict: staking_pool_on_conflict()}, + staking_pools_delegators: %{params: delegator_entries, on_conflict: staking_pools_delegator_on_conflict()}, + timeout: :infinity + }) end def transform_requests(minig_address) do From e1679ae728a60caa1ef53096a1a24477ce8d65f2 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Tue, 12 Nov 2019 21:30:37 +0200 Subject: [PATCH 15/75] Rename staked_amount field to total_staked_amount --- .../assets/js/pages/stakes/claim_withdrawal.js | 2 +- .../assets/js/pages/stakes/make_stake.js | 2 +- .../assets/js/pages/stakes/move_stake.js | 4 ++-- .../assets/js/pages/stakes/withdraw_stake.js | 2 +- .../block_scout_web/channels/stakes_channel.ex | 10 +++++----- .../templates/stakes/_rows.html.eex | 2 +- .../stakes/_stakes_modal_validator_info.html.eex | 2 +- .../templates/stakes/_stakes_progress.html.eex | 2 +- .../lib/block_scout_web/views/stakes_helpers.ex | 6 +++--- .../chain/import/runner/staking_pools.ex | 4 ++-- apps/explorer/lib/explorer/chain/staking_pool.ex | 16 ++++++++-------- .../lib/explorer/staking/contract_reader.ex | 2 +- .../lib/explorer/staking/contract_state.ex | 6 +++--- .../lib/explorer/staking/stake_snapshotting.ex | 16 ++++++++-------- .../20190521104412_create_staking_pools.exs | 2 +- ..._add_snapshotting_fields_to_staking_pools.exs | 2 +- apps/explorer/test/support/factory.ex | 2 +- 17 files changed, 41 insertions(+), 41 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_withdrawal.js b/apps/block_scout_web/assets/js/pages/stakes/claim_withdrawal.js index a48b92f83ce1..2251964fd32e 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_withdrawal.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_withdrawal.js @@ -11,7 +11,7 @@ export function openClaimWithdrawalModal (event, store) { .push('render_claim_withdrawal', { address }) .receive('ok', msg => { const $modal = $(msg.html) - setupChart($modal.find('.js-stakes-progress'), msg.self_staked_amount, msg.staked_amount) + setupChart($modal.find('.js-stakes-progress'), msg.self_staked_amount, msg.total_staked_amount) $modal.find('form').submit(() => { claimWithdraw($modal, address, store) return false diff --git a/apps/block_scout_web/assets/js/pages/stakes/make_stake.js b/apps/block_scout_web/assets/js/pages/stakes/make_stake.js index 81d1e70bc307..15757fd95061 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/make_stake.js +++ b/apps/block_scout_web/assets/js/pages/stakes/make_stake.js @@ -18,7 +18,7 @@ export function openMakeStakeModal (event, store) { .push('render_make_stake', { address }) .receive('ok', msg => { const $modal = $(msg.html) - setupChart($modal.find('.js-stakes-progress'), msg.self_staked_amount, msg.staked_amount) + setupChart($modal.find('.js-stakes-progress'), msg.self_staked_amount, msg.total_staked_amount) setupValidation( $modal.find('form'), { diff --git a/apps/block_scout_web/assets/js/pages/stakes/move_stake.js b/apps/block_scout_web/assets/js/pages/stakes/move_stake.js index 825e95f0a824..2c76ad2c0136 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/move_stake.js +++ b/apps/block_scout_web/assets/js/pages/stakes/move_stake.js @@ -19,9 +19,9 @@ export function openMoveStakeModal (event, store) { } function setupModal ($modal, fromAddress, store, msg) { - setupChart($modal.find('.js-pool-from-progress'), msg.from.self_staked_amount, msg.from.staked_amount) + setupChart($modal.find('.js-pool-from-progress'), msg.from.self_staked_amount, msg.from.total_staked_amount) if (msg.to) { - setupChart($modal.find('.js-pool-to-progress'), msg.to.self_staked_amount, msg.to.staked_amount) + setupChart($modal.find('.js-pool-to-progress'), msg.to.self_staked_amount, msg.to.total_staked_amount) setupValidation( $modal.find('form'), diff --git a/apps/block_scout_web/assets/js/pages/stakes/withdraw_stake.js b/apps/block_scout_web/assets/js/pages/stakes/withdraw_stake.js index 34ef310f534b..e0f9aec5d8d6 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/withdraw_stake.js +++ b/apps/block_scout_web/assets/js/pages/stakes/withdraw_stake.js @@ -16,7 +16,7 @@ export function openWithdrawStakeModal (event, store) { function setupWithdrawStakeModal (address, store, msg) { const $modal = $(msg.html) - setupChart($modal.find('.js-stakes-progress'), msg.self_staked_amount, msg.staked_amount) + setupChart($modal.find('.js-stakes-progress'), msg.self_staked_amount, msg.total_staked_amount) setupValidation( $modal.find('form'), { 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 b883b1648e87..ef306b50c48b 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 @@ -132,7 +132,7 @@ defmodule BlockScoutWeb.StakesChannel do delegator_staked: (delegator && delegator.stake_amount) || 0, min_stake: min_stake, self_staked_amount: pool.self_staked_amount, - staked_amount: pool.staked_amount + total_staked_amount: pool.total_staked_amount } {:reply, {:ok, result}, socket} @@ -178,7 +178,7 @@ defmodule BlockScoutWeb.StakesChannel do stake_amount: delegator_from.stake_amount, min_stake: min_from_stake, self_staked_amount: pool_from.self_staked_amount, - staked_amount: pool_from.staked_amount + total_staked_amount: pool_from.total_staked_amount }, to: if pool_to do @@ -186,7 +186,7 @@ defmodule BlockScoutWeb.StakesChannel do stake_amount: (delegator_to && delegator_to.stake_amount) || 0, min_stake: min_to_stake, self_staked_amount: pool_to.self_staked_amount, - staked_amount: pool_to.staked_amount + total_staked_amount: pool_to.total_staked_amount } end } @@ -216,7 +216,7 @@ defmodule BlockScoutWeb.StakesChannel do result = %{ html: html, self_staked_amount: pool.self_staked_amount, - staked_amount: pool.staked_amount, + total_staked_amount: pool.total_staked_amount, delegator_staked: delegator.stake_amount, ordered_withdraw: delegator.ordered_withdraw, max_withdraw_allowed: delegator.max_withdraw_allowed, @@ -242,7 +242,7 @@ defmodule BlockScoutWeb.StakesChannel do result = %{ html: html, self_staked_amount: pool.self_staked_amount, - staked_amount: pool.staked_amount + total_staked_amount: pool.total_staked_amount } {:reply, {:ok, result}, socket} diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex index 75ae6ff7e29c..25f7f6ac6661 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex @@ -15,7 +15,7 @@ render BlockScoutWeb.CommonComponentsView, "_progress_from_to.html", from: format_token_amount(@pool.self_staked_amount, @token, digits: 0, ellipsize: false, symbol: false), - to: format_token_amount(@pool.staked_amount, @token, digits: 0, ellipsize: false, symbol: false), + to: format_token_amount(@pool.total_staked_amount, @token, digits: 0, ellipsize: false, symbol: false), progress: amount_ratio(@pool) %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex index 2cebbfeb07da..02a01235548d 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex @@ -35,7 +35,7 @@ render BlockScoutWeb.StakesView, "_stakes_validator_info_item.html", title: gettext("Delegators’ Staked Amount"), - value: format_token_amount(Decimal.sub(@validator.staked_amount, @validator.self_staked_amount), @token) + value: format_token_amount(Decimal.sub(@validator.total_staked_amount, @validator.self_staked_amount), @token) %> <%= render BlockScoutWeb.StakesView, diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex index 924fd95c42ae..4c64f0239b0e 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex @@ -10,7 +10,7 @@ <%= format_token_amount(@pool.self_staked_amount, @token, symbol: false, digits: 2) %>
- <%= format_token_amount(@pool.staked_amount, @token, symbol: false, digits: 2) %> + <%= format_token_amount(@pool.total_staked_amount, @token, symbol: false, digits: 2) %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/stakes_helpers.ex b/apps/block_scout_web/lib/block_scout_web/views/stakes_helpers.ex index 07a30e7c7ee3..6db2042600a0 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/stakes_helpers.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/stakes_helpers.ex @@ -12,11 +12,11 @@ defmodule BlockScoutWeb.StakesHelpers do zero = Decimal.new(0) case pool do - %{staked_amount: ^zero} -> + %{total_staked_amount: ^zero} -> 0 - %{staked_amount: staked_amount, self_staked_amount: self_staked} -> - amount = Decimal.to_float(staked_amount) + %{total_staked_amount: total_staked_amount, self_staked_amount: self_staked} -> + amount = Decimal.to_float(total_staked_amount) self = Decimal.to_float(self_staked) self / amount * 100 end diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 7eecebea3dfe..67a9799e37ed 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -134,9 +134,9 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do staked_ratio: fragment("EXCLUDED.staked_ratio"), snapshotted_staked_ratio: pool.snapshotted_staked_ratio, self_staked_amount: fragment("EXCLUDED.self_staked_amount"), - staked_amount: fragment("EXCLUDED.staked_amount"), + total_staked_amount: fragment("EXCLUDED.total_staked_amount"), snapshotted_self_staked_amount: pool.snapshotted_self_staked_amount, - snapshotted_staked_amount: pool.snapshotted_staked_amount, + snapshotted_total_staked_amount: pool.snapshotted_total_staked_amount, ban_reason: fragment("EXCLUDED.ban_reason"), was_banned_count: fragment("EXCLUDED.was_banned_count"), was_validator_count: fragment("EXCLUDED.was_validator_count"), diff --git a/apps/explorer/lib/explorer/chain/staking_pool.ex b/apps/explorer/lib/explorer/chain/staking_pool.ex index 7414709cc45a..5dd0f6e9b3cf 100644 --- a/apps/explorer/lib/explorer/chain/staking_pool.ex +++ b/apps/explorer/lib/explorer/chain/staking_pool.ex @@ -28,9 +28,9 @@ defmodule Explorer.Chain.StakingPool do staked_ratio: Decimal.t(), snapshotted_staked_ratio: Decimal.t(), self_staked_amount: Decimal.t(), - staked_amount: Decimal.t(), + total_staked_amount: Decimal.t(), snapshotted_self_staked_amount: Decimal.t(), - snapshotted_staked_amount: Decimal.t(), + snapshotted_total_staked_amount: Decimal.t(), ban_reason: String.t(), was_banned_count: integer, was_validator_count: integer, @@ -38,13 +38,13 @@ defmodule Explorer.Chain.StakingPool do } @attrs ~w( - is_active delegators_count staked_amount self_staked_amount snapshotted_staked_amount snapshotted_self_staked_amount is_validator + is_active delegators_count total_staked_amount self_staked_amount snapshotted_total_staked_amount snapshotted_self_staked_amount is_validator was_validator_count is_banned are_delegators_banned ban_reason was_banned_count banned_until banned_delegators_until likelihood staked_ratio snapshotted_staked_ratio staking_address_hash mining_address_hash block_reward_ratio is_unremovable )a @req_attrs ~w( - is_active delegators_count staked_amount self_staked_amount is_validator + is_active delegators_count total_staked_amount self_staked_amount is_validator was_validator_count is_banned was_banned_count banned_until staking_address_hash mining_address_hash is_unremovable )a @@ -63,9 +63,9 @@ defmodule Explorer.Chain.StakingPool do field(:staked_ratio, :decimal) field(:snapshotted_staked_ratio, :decimal) field(:self_staked_amount, :decimal) - field(:staked_amount, :decimal) + field(:total_staked_amount, :decimal) field(:snapshotted_self_staked_amount, :decimal) - field(:snapshotted_staked_amount, :decimal) + field(:snapshotted_total_staked_amount, :decimal) field(:ban_reason, :string) field(:was_banned_count, :integer) field(:was_validator_count, :integer) @@ -104,8 +104,8 @@ defmodule Explorer.Chain.StakingPool do defp validate_staked_amount(%{valid?: false} = c), do: c defp validate_staked_amount(changeset) do - if get_field(changeset, :staked_amount) < get_field(changeset, :self_staked_amount) do - add_error(changeset, :staked_amount, "must be greater than self_staked_amount") + if get_field(changeset, :total_staked_amount) < get_field(changeset, :self_staked_amount) do + add_error(changeset, :total_staked_amount, "must be greater than self_staked_amount") else changeset end diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index e6ebe8627631..cc319fe7473d 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -32,7 +32,7 @@ defmodule Explorer.Staking.ContractReader do is_active: {:staking, "isPoolActive", [staking_address]}, active_delegators: {:staking, "poolDelegators", [staking_address]}, inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]}, - staked_amount: {:staking, "stakeAmountTotal", [staking_address]}, + total_staked_amount: {:staking, "stakeAmountTotal", [staking_address]}, self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address]}, block_reward: {:block_reward, "validatorRewardPercent", [staking_address]} ] diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 6c70149bec3b..b3aa3864c33a 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -183,7 +183,7 @@ defmodule Explorer.Staking.ContractState do ContractReader.pool_reward_requests([ global_responses.epoch_number, response.self_staked_amount, - response.staked_amount, + response.total_staked_amount, 1000_000 ]) end) @@ -200,7 +200,7 @@ defmodule Explorer.Staking.ContractState do global_responses.epoch_number, response.stake_amount, staking_response.self_staked_amount, - staking_response.staked_amount, + staking_response.total_staked_amount, 1000_000 ]) end) @@ -227,7 +227,7 @@ defmodule Explorer.Staking.ContractState do Map.take(staking_response, [ :mining_address_hash, :is_active, - :staked_amount, + :total_staked_amount, :self_staked_amount ]) ) diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index cbcf76e8c6b1..872d638760c6 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -63,7 +63,7 @@ defmodule Explorer.Staking.StakeSnapshotting do ContractReader.pool_reward_requests([ global_responses.epoch_number, response.snapshotted_self_staked_amount, - response.snapshotted_staked_amount, + response.snapshotted_total_staked_amount, 1000_000 ]) end) @@ -80,7 +80,7 @@ defmodule Explorer.Staking.StakeSnapshotting do global_responses.epoch_number, response.stake_amount, staking_response.snapshotted_self_staked_amount, - staking_response.snapshotted_staked_amount, + staking_response.snapshotted_total_staked_amount, 1000_000 ]) end) @@ -99,9 +99,9 @@ defmodule Explorer.Staking.StakeSnapshotting do } |> Map.merge( Map.take(staking_response, [ - :snapshotted_staked_amount, + :snapshotted_total_staked_amount, :snapshotted_self_staked_amount, - :staked_amount, + :total_staked_amount, :self_staked_amount, :mining_address_hash ]) @@ -142,9 +142,9 @@ defmodule Explorer.Staking.StakeSnapshotting do defp pool_staking_requests(staking_address, block_number) do [ - snapshotted_staked_amount: {:staking, "stakeAmountTotal", [staking_address], block_number - 1}, + snapshotted_total_staked_amount: {:staking, "stakeAmountTotal", [staking_address], block_number - 1}, snapshotted_self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address], block_number - 1}, - staked_amount: {:staking, "stakeAmountTotal", [staking_address]}, + total_staked_amount: {:staking, "stakeAmountTotal", [staking_address]}, self_staked_amount: {:staking, "stakeAmount", [staking_address, staking_address]}, mining_address_hash: {:validator_set, "miningByStakingAddress", [staking_address]}, active_delegators: {:staking, "poolDelegators", [staking_address]}, @@ -186,9 +186,9 @@ defmodule Explorer.Staking.StakeSnapshotting do delegators_count: fragment("EXCLUDED.delegators_count"), snapshotted_staked_ratio: fragment("EXCLUDED.snapshotted_staked_ratio"), self_staked_amount: fragment("EXCLUDED.self_staked_amount"), - staked_amount: fragment("EXCLUDED.staked_amount"), + total_staked_amount: fragment("EXCLUDED.total_staked_amount"), snapshotted_self_staked_amount: fragment("EXCLUDED.snapshotted_self_staked_amount"), - snapshotted_staked_amount: fragment("EXCLUDED.snapshotted_staked_amount"), + snapshotted_total_staked_amount: fragment("EXCLUDED.snapshotted_total_staked_amount"), is_active: pool.is_active, is_banned: pool.is_banned, is_validator: pool.is_validator, diff --git a/apps/explorer/priv/repo/migrations/20190521104412_create_staking_pools.exs b/apps/explorer/priv/repo/migrations/20190521104412_create_staking_pools.exs index 94483112f224..7011fd962c0b 100644 --- a/apps/explorer/priv/repo/migrations/20190521104412_create_staking_pools.exs +++ b/apps/explorer/priv/repo/migrations/20190521104412_create_staking_pools.exs @@ -6,7 +6,7 @@ defmodule Explorer.Repo.Migrations.CreateStakingPools do add(:is_active, :boolean, default: false, null: false) add(:is_deleted, :boolean, default: false, null: false) add(:delegators_count, :integer) - add(:staked_amount, :numeric, precision: 100) + add(:total_staked_amount, :numeric, precision: 100) add(:self_staked_amount, :numeric, precision: 100) add(:is_validator, :boolean, default: false, null: false) add(:was_validator_count, :integer) diff --git a/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs b/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs index d7fe5a2e0492..9d0f923fd949 100644 --- a/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs +++ b/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs @@ -3,7 +3,7 @@ defmodule Explorer.Repo.Migrations.AddSnapshottingFieldsToStakingPools do def change do alter table(:staking_pools) do - add(:snapshotted_staked_amount, :numeric, precision: 100) + add(:snapshotted_total_staked_amount, :numeric, precision: 100) add(:snapshotted_self_staked_amount, :numeric, precision: 100) add(:snapshotted_staked_ratio, :decimal, precision: 5, scale: 2) end diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index b2a1feeac655..2c56a56c7996 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -635,7 +635,7 @@ defmodule Explorer.Factory do is_active: true, is_banned: false, is_validator: true, - staked_amount: wei_per_ether * 500, + total_staked_amount: wei_per_ether * 500, self_staked_amount: wei_per_ether * 300, was_banned_count: 0, was_validator_count: 1 From d1310b0ba4eb42a7ea710e04771eb79a9613eed5 Mon Sep 17 00:00:00 2001 From: Eduard Sachava Date: Wed, 13 Nov 2019 15:35:56 +0200 Subject: [PATCH 16/75] Add validator_reward_ratio field and fix staked_ratio value --- .../_stakes_modal_delegators_list.html.eex | 22 +++++++++++++++---- .../chain/import/runner/staking_pools.ex | 3 ++- .../lib/explorer/chain/staking_pool.ex | 8 ++++--- .../lib/explorer/staking/contract_reader.ex | 2 +- .../lib/explorer/staking/contract_state.ex | 10 +++++++-- .../explorer/staking/stake_snapshotting.ex | 21 ++++-------------- ...d_snapshotting_fields_to_staking_pools.exs | 3 ++- 7 files changed, 40 insertions(+), 29 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index 44c8129aed98..6572a842c3d0 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -82,13 +82,27 @@ <% end %>
- <%= if delegator.reward_ratio do %> - <%= delegator.reward_ratio %>% + <% + reward = + if delegator.delegator_address_hash == @pool.staking_address_hash do + %{ + reward_ratio: @pool.validator_reward_ratio, + snapshotted_reward_ratio: @pool.snapshotted_validator_reward_ratio + } + else + %{ + reward_ratio: delegator.reward_ratio, + snapshotted_reward_ratio: delegator.snapshotted_reward_ratio + } + end + %> + <%= if reward.reward_ratio do %> + <%= reward.reward_ratio %>% <%= if @is_show_snapshotted_data do %> ( <%= - if delegator.snapshotted_reward_ratio do - "#{delegator.snapshotted_reward_ratio}%" + if reward.snapshotted_reward_ratio do + "#{reward.snapshotted_reward_ratio}%" else "0%" end diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 67a9799e37ed..d7a3b7c46bb4 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -132,7 +132,8 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do likelihood: fragment("EXCLUDED.likelihood"), block_reward_ratio: fragment("EXCLUDED.block_reward_ratio"), staked_ratio: fragment("EXCLUDED.staked_ratio"), - snapshotted_staked_ratio: pool.snapshotted_staked_ratio, + validator_reward_ratio: fragment("EXCLUDED.validator_reward_ratio"), + snapshotted_validator_reward_ratio: pool.snapshotted_validator_reward_ratio, self_staked_amount: fragment("EXCLUDED.self_staked_amount"), total_staked_amount: fragment("EXCLUDED.total_staked_amount"), snapshotted_self_staked_amount: pool.snapshotted_self_staked_amount, diff --git a/apps/explorer/lib/explorer/chain/staking_pool.ex b/apps/explorer/lib/explorer/chain/staking_pool.ex index 5dd0f6e9b3cf..7b51c07bceeb 100644 --- a/apps/explorer/lib/explorer/chain/staking_pool.ex +++ b/apps/explorer/lib/explorer/chain/staking_pool.ex @@ -26,7 +26,8 @@ defmodule Explorer.Chain.StakingPool do likelihood: Decimal.t(), block_reward_ratio: Decimal.t(), staked_ratio: Decimal.t(), - snapshotted_staked_ratio: Decimal.t(), + validator_reward_ratio: Decimal.t(), + snapshotted_validator_reward_ratio: Decimal.t(), self_staked_amount: Decimal.t(), total_staked_amount: Decimal.t(), snapshotted_self_staked_amount: Decimal.t(), @@ -40,7 +41,7 @@ defmodule Explorer.Chain.StakingPool do @attrs ~w( is_active delegators_count total_staked_amount self_staked_amount snapshotted_total_staked_amount snapshotted_self_staked_amount is_validator was_validator_count is_banned are_delegators_banned ban_reason was_banned_count banned_until banned_delegators_until likelihood - staked_ratio snapshotted_staked_ratio staking_address_hash mining_address_hash block_reward_ratio + staked_ratio validator_reward_ratio snapshotted_validator_reward_ratio staking_address_hash mining_address_hash block_reward_ratio is_unremovable )a @req_attrs ~w( @@ -61,7 +62,8 @@ defmodule Explorer.Chain.StakingPool do field(:likelihood, :decimal) field(:block_reward_ratio, :decimal) field(:staked_ratio, :decimal) - field(:snapshotted_staked_ratio, :decimal) + field(:validator_reward_ratio, :decimal) + field(:snapshotted_validator_reward_ratio, :decimal) field(:self_staked_amount, :decimal) field(:total_staked_amount, :decimal) field(:snapshotted_self_staked_amount, :decimal) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index cc319fe7473d..9b62f394d421 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -61,7 +61,7 @@ defmodule Explorer.Staking.ContractReader do end # args = [staking_epoch, validator_staked, total_staked, pool_reward \\ 10_00000] - def pool_reward_requests(args) do + def validator_reward_requests(args) do [ validator_share: {:block_reward, "validatorShare", args} ] diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index b3aa3864c33a..16e47f3de435 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -168,6 +168,8 @@ defmodule Explorer.Staking.ContractState do end) |> ContractReader.perform_grouped_requests(delegators, contracts, abi) + staked_total = Enum.sum(for {_, pool} <- pool_staking_responses, pool.is_active, do: pool.total_staked_amount) + [likelihood_values, total_likelihood] = global_responses.pools_likelihood likelihood = @@ -180,7 +182,7 @@ defmodule Explorer.Staking.ContractState do pool_reward_responses = pool_staking_responses |> Enum.map(fn {_address, response} -> - ContractReader.pool_reward_requests([ + ContractReader.validator_reward_requests([ global_responses.epoch_number, response.self_staked_amount, response.total_staked_amount, @@ -215,7 +217,11 @@ defmodule Explorer.Staking.ContractState do %{ staking_address_hash: staking_address, delegators_count: length(staking_response.active_delegators), - staked_ratio: pool_reward_response.validator_share / 10_000, + staked_ratio: + if staking_response.is_active do + ratio(staking_response.total_staked_amount, staked_total) + end, + validator_reward_ratio: pool_reward_response.validator_share / 10_000, likelihood: ratio(likelihood[staking_address] || 0, total_likelihood), block_reward_ratio: staking_response.block_reward / 10_000, is_deleted: false, diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 872d638760c6..ca479a9b2e1a 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -60,7 +60,7 @@ defmodule Explorer.Staking.StakeSnapshotting do pool_reward_responses = pool_staking_responses |> Enum.map(fn {_address, response} -> - ContractReader.pool_reward_requests([ + ContractReader.validator_reward_requests([ global_responses.epoch_number, response.snapshotted_self_staked_amount, response.snapshotted_total_staked_amount, @@ -95,7 +95,7 @@ defmodule Explorer.Staking.StakeSnapshotting do %{ staking_address_hash: staking_address, delegators_count: length(staking_response.active_delegators), - snapshotted_staked_ratio: pool_reward_response.validator_share / 10_000 + snapshotted_validator_reward_ratio: pool_reward_response.validator_share / 10_000 } |> Map.merge( Map.take(staking_response, [ @@ -163,20 +163,6 @@ defmodule Explorer.Staking.StakeSnapshotting do ] end - # args = [staking_epoch, validator_staked, total_staked, pool_reward \\ 10_00000] - def pool_reward_requests(args, block_number) do - [ - validator_share: {:block_reward, "validatorShare", args, block_number - 1} - ] - end - - # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] - def delegator_reward_requests(args, block_number) do - [ - delegator_share: {:block_reward, "delegatorShare", args, block_number - 1} - ] - end - defp staking_pool_on_conflict do from( pool in StakingPool, @@ -184,7 +170,7 @@ defmodule Explorer.Staking.StakeSnapshotting do set: [ mining_address_hash: fragment("EXCLUDED.mining_address_hash"), delegators_count: fragment("EXCLUDED.delegators_count"), - snapshotted_staked_ratio: fragment("EXCLUDED.snapshotted_staked_ratio"), + snapshotted_validator_reward_ratio: fragment("EXCLUDED.snapshotted_validator_reward_ratio"), self_staked_amount: fragment("EXCLUDED.self_staked_amount"), total_staked_amount: fragment("EXCLUDED.total_staked_amount"), snapshotted_self_staked_amount: fragment("EXCLUDED.snapshotted_self_staked_amount"), @@ -197,6 +183,7 @@ defmodule Explorer.Staking.StakeSnapshotting do likelihood: pool.likelihood, block_reward_ratio: pool.block_reward_ratio, staked_ratio: pool.staked_ratio, + validator_reward_ratio: pool.validator_reward_ratio, ban_reason: pool.ban_reason, was_banned_count: pool.was_banned_count, was_validator_count: pool.was_validator_count, diff --git a/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs b/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs index 9d0f923fd949..ecc44951f52e 100644 --- a/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs +++ b/apps/explorer/priv/repo/migrations/20191024135401_add_snapshotting_fields_to_staking_pools.exs @@ -5,7 +5,8 @@ defmodule Explorer.Repo.Migrations.AddSnapshottingFieldsToStakingPools do alter table(:staking_pools) do add(:snapshotted_total_staked_amount, :numeric, precision: 100) add(:snapshotted_self_staked_amount, :numeric, precision: 100) - add(:snapshotted_staked_ratio, :decimal, precision: 5, scale: 2) + add(:validator_reward_ratio, :decimal, precision: 5, scale: 2) + add(:snapshotted_validator_reward_ratio, :decimal, precision: 5, scale: 2) end end end From 74e723dc6f4194044e84f38cd724e63af689dc79 Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 20 Nov 2019 12:19:13 +0300 Subject: [PATCH 17/75] Fix fields/variables names --- .../lib/block_scout_web/chain.ex | 2 +- .../channels/stakes_channel.ex | 2 +- .../templates/stakes/_rows.html.eex | 2 +- ...l.eex => _stakes_modal_pool_info.html.eex} | 4 +- .../stakes/_stakes_progress.html.eex | 2 +- apps/block_scout_web/priv/gettext/default.pot | 72 ++++++++++------- .../priv/gettext/en/LC_MESSAGES/default.po | 80 +++++++++++-------- apps/explorer/lib/explorer/chain.ex | 6 +- .../chain/import/runner/staking_pools.ex | 2 +- .../lib/explorer/chain/staking_pool.ex | 6 +- .../lib/explorer/staking/contract_reader.ex | 14 ++-- .../lib/explorer/staking/contract_state.ex | 4 +- .../explorer/staking/stake_snapshotting.ex | 22 ++--- .../20190521104412_create_staking_pools.exs | 2 +- 14 files changed, 122 insertions(+), 98 deletions(-) rename apps/block_scout_web/lib/block_scout_web/templates/stakes/{_stakes_modal_validator_info.html.eex => _stakes_modal_pool_info.html.eex} (96%) diff --git a/apps/block_scout_web/lib/block_scout_web/chain.ex b/apps/block_scout_web/lib/block_scout_web/chain.ex index 9843377dca8a..e81179b44576 100644 --- a/apps/block_scout_web/lib/block_scout_web/chain.ex +++ b/apps/block_scout_web/lib/block_scout_web/chain.ex @@ -253,7 +253,7 @@ defmodule BlockScoutWeb.Chain do %{"block_number" => block_number} end - defp paging_params(%StakingPool{staking_address_hash: address_hash, staked_ratio: value}) do + defp paging_params(%StakingPool{staking_address_hash: address_hash, stakes_ratio: value}) do %{"address_hash" => address_hash, "value" => Decimal.to_string(value)} end 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 ef306b50c48b..6857470b14db 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 @@ -41,7 +41,7 @@ defmodule BlockScoutWeb.StakesChannel do token = ContractState.get(:token) html = - View.render_to_string(StakesView, "_stakes_modal_validator_info.html", + View.render_to_string(StakesView, "_stakes_modal_pool_info.html", validator: pool, delegator: delegator, average_block_time: average_block_time, diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex index 25f7f6ac6661..8ac2afb7c77e 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex @@ -23,7 +23,7 @@ <%= if @pools_type == :inactive do %> <%= if @pool.is_banned, do: gettext("Yes"), else: gettext("No") %> <% else %> - <%= if @pool.staked_ratio, do: "#{@pool.staked_ratio}%" %> + <%= if @pool.stakes_ratio, do: "#{@pool.stakes_ratio}%" %> <% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex similarity index 96% rename from apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex rename to apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex index 02a01235548d..bf011701d5e5 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex @@ -41,12 +41,12 @@ render BlockScoutWeb.StakesView, "_stakes_validator_info_item.html", title: gettext("Stakes Ratio"), - value: if(@validator.staked_ratio, do: "#{@validator.staked_ratio}%") + value: if(@validator.stakes_ratio, do: "#{@validator.stakes_ratio}%") %> <%= render BlockScoutWeb.StakesView, "_stakes_validator_info_item.html", - title: gettext("Reward Percent"), + title: gettext("Share of Pool’s Reward"), value: "#{@validator.block_reward_ratio}%" %> <%= diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex index 4c64f0239b0e..e4a48a7d6cbc 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex @@ -24,7 +24,7 @@

<%= gettext("Stakes Ratio") %>

- <%= @pool.staked_ratio %>% + <%= @pool.stakes_ratio %>%

diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index a8abf9e71ce5..7ff21b689b3d 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -1925,7 +1925,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:16 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:24 msgid "Amount of STAKE placed by an address" msgstr "" @@ -1968,7 +1968,7 @@ msgid "Candidate and Validator Pool Addresses. Current validator pools are speci msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:31 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:31 msgid "Candidate’s Staked Amount" msgstr "" @@ -2001,7 +2001,7 @@ msgid "Delegators" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:37 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:37 msgid "Delegators’ Staked Amount" msgstr "" @@ -2011,12 +2011,12 @@ msgid "Epoch number" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:61 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:61 msgid "How Many Times this Address has been Banned" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:55 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:55 msgid "How Many Times this Address has been a Validator" msgstr "" @@ -2028,18 +2028,18 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:48 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:63 msgid "It's me!" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:67 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:67 msgid "Likelihood of Becoming a Validator on the Next Epoch" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:50 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:65 msgid "ME" msgstr "" @@ -2056,7 +2056,7 @@ msgid "Minimum Stake:" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:8 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:8 msgid "Mining Address:" msgstr "" @@ -2099,12 +2099,13 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:20 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:31 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:33 msgid "Potential Reward Percent" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:16 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:16 msgid "Reason for Ban: %{ban_reason}" msgstr "" @@ -2115,14 +2116,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:20 -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:49 -msgid "Reward Percent" -msgstr "" - -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:24 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:39 msgid "Reward distribution is based on stake amount. Validator receives a minimum of 30%." msgstr "" @@ -2178,14 +2172,14 @@ msgid "Stakes" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:43 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:43 #: lib/block_scout_web/templates/stakes/_stakes_progress.html.eex:25 #: lib/block_scout_web/templates/stakes/_table.html.eex:14 msgid "Stakes Ratio" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:73 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:73 msgid "The Number of Delegators in the Pool" msgstr "" @@ -2211,21 +2205,15 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_rows.html.eex:5 -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:38 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 msgid "This is a validator" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:15 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:15 msgid "This pool is banned until block #%{banned_until} (%{estimated_unban_day})" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:16 -msgid "Total Stake Amount" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_table.html.eex:12 msgid "Validator pools can be banned for misbehavior (such as not revealing secret numbers). Validator and delegator stake contained in a banned pool cannot be withdrawn until the ban is over." @@ -2264,7 +2252,7 @@ msgid "You Staked:" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:22 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:22 msgid "You will be able to withdraw after block #%{banned_delegators_until} (%{estimated_unban_day})" msgstr "" @@ -2285,3 +2273,27 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:11 msgid "Your ordered amount" msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:19 +msgid "Accounted Stake Amount" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:31 +msgid "Current Reward Percent" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:19 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:21 +msgid "Current Stake Amount" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:49 +msgid "Share of Pool’s Reward" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index ce92ed2f113d..382e5571e1ee 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -1914,7 +1914,7 @@ msgstr "" msgid "Already Ordered:" msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:10 #: lib/block_scout_web/templates/stakes/_stakes_modal_move.html.eex:14 @@ -1925,7 +1925,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:16 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:24 msgid "Amount of STAKE placed by an address" msgstr "" @@ -1957,7 +1957,7 @@ msgstr "" msgid "Become a Candidate" msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:5 msgid "Block number" msgstr "" @@ -1968,7 +1968,7 @@ msgid "Candidate and Validator Pool Addresses. Current validator pools are speci msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:31 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:31 msgid "Candidate’s Staked Amount" msgstr "" @@ -2001,7 +2001,7 @@ msgid "Delegators" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:37 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:37 msgid "Delegators’ Staked Amount" msgstr "" @@ -2011,12 +2011,12 @@ msgid "Epoch number" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:61 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:61 msgid "How Many Times this Address has been Banned" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:55 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:55 msgid "How Many Times this Address has been a Validator" msgstr "" @@ -2028,18 +2028,18 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:48 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:63 msgid "It's me!" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:67 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:67 msgid "Likelihood of Becoming a Validator on the Next Epoch" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:50 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:65 msgid "ME" msgstr "" @@ -2056,7 +2056,7 @@ msgid "Minimum Stake:" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:8 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:8 msgid "Mining Address:" msgstr "" @@ -2099,12 +2099,13 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:20 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:31 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:33 msgid "Potential Reward Percent" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:16 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:16 msgid "Reason for Ban: %{ban_reason}" msgstr "" @@ -2113,16 +2114,9 @@ msgstr "" msgid "Remove My Pool" msgstr "" -#, elixir-format, fuzzy -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:20 -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:49 -msgid "Reward Percent" -msgstr "" - #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:24 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:39 msgid "Reward distribution is based on stake amount. Validator receives a minimum of 30%." msgstr "" @@ -2178,14 +2172,14 @@ msgid "Stakes" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:43 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:43 #: lib/block_scout_web/templates/stakes/_stakes_progress.html.eex:25 #: lib/block_scout_web/templates/stakes/_table.html.eex:14 msgid "Stakes Ratio" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:73 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:73 msgid "The Number of Delegators in the Pool" msgstr "" @@ -2211,27 +2205,21 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_rows.html.eex:5 -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:38 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 msgid "This is a validator" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:15 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:15 msgid "This pool is banned until block #%{banned_until} (%{estimated_unban_day})" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:16 -msgid "Total Stake Amount" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_table.html.eex:12 msgid "Validator pools can be banned for misbehavior (such as not revealing secret numbers). Validator and delegator stake contained in a banned pool cannot be withdrawn until the ban is over." msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: lib/block_scout_web/templates/layout/_topnav.html.eex:126 #: lib/block_scout_web/templates/stakes/_stakes_tabs.html.eex:4 msgid "Validators" @@ -2264,11 +2252,11 @@ msgid "You Staked:" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_validator_info.html.eex:22 +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:22 msgid "You will be able to withdraw after block #%{banned_delegators_until} (%{estimated_unban_day})" msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:18 #: lib/block_scout_web/templates/stakes/_stakes_modal_stake.html.eex:26 @@ -2285,3 +2273,27 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:11 msgid "Your ordered amount" msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:19 +msgid "Accounted Stake Amount" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:31 +msgid "Current Reward Percent" +msgstr "" + +#, elixir-format, fuzzy +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:19 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:21 +msgid "Current Stake Amount" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:49 +msgid "Share of Pool’s Reward" +msgstr "" diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index c8de9438974a..6b620cf343fe 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -3600,15 +3600,15 @@ defmodule Explorer.Chain do paging_query = base_query |> limit(^paging_options.page_size) - |> order_by(desc: :staked_ratio, asc: :staking_address_hash) + |> order_by(desc: :stakes_ratio, asc: :staking_address_hash) case paging_options.key do {value, address_hash} -> where( paging_query, [p], - p.staked_ratio < ^value or - (p.staked_ratio == ^value and p.staking_address_hash > ^address_hash) + p.stakes_ratio < ^value or + (p.stakes_ratio == ^value and p.staking_address_hash > ^address_hash) ) _ -> diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index d7a3b7c46bb4..bdc51d9e8225 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -131,7 +131,7 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do are_delegators_banned: fragment("EXCLUDED.are_delegators_banned"), likelihood: fragment("EXCLUDED.likelihood"), block_reward_ratio: fragment("EXCLUDED.block_reward_ratio"), - staked_ratio: fragment("EXCLUDED.staked_ratio"), + stakes_ratio: fragment("EXCLUDED.stakes_ratio"), validator_reward_ratio: fragment("EXCLUDED.validator_reward_ratio"), snapshotted_validator_reward_ratio: pool.snapshotted_validator_reward_ratio, self_staked_amount: fragment("EXCLUDED.self_staked_amount"), diff --git a/apps/explorer/lib/explorer/chain/staking_pool.ex b/apps/explorer/lib/explorer/chain/staking_pool.ex index 7b51c07bceeb..189715a5abd4 100644 --- a/apps/explorer/lib/explorer/chain/staking_pool.ex +++ b/apps/explorer/lib/explorer/chain/staking_pool.ex @@ -25,7 +25,7 @@ defmodule Explorer.Chain.StakingPool do are_delegators_banned: boolean, likelihood: Decimal.t(), block_reward_ratio: Decimal.t(), - staked_ratio: Decimal.t(), + stakes_ratio: Decimal.t(), validator_reward_ratio: Decimal.t(), snapshotted_validator_reward_ratio: Decimal.t(), self_staked_amount: Decimal.t(), @@ -41,7 +41,7 @@ defmodule Explorer.Chain.StakingPool do @attrs ~w( is_active delegators_count total_staked_amount self_staked_amount snapshotted_total_staked_amount snapshotted_self_staked_amount is_validator was_validator_count is_banned are_delegators_banned ban_reason was_banned_count banned_until banned_delegators_until likelihood - staked_ratio validator_reward_ratio snapshotted_validator_reward_ratio staking_address_hash mining_address_hash block_reward_ratio + stakes_ratio validator_reward_ratio snapshotted_validator_reward_ratio staking_address_hash mining_address_hash block_reward_ratio is_unremovable )a @req_attrs ~w( @@ -61,7 +61,7 @@ defmodule Explorer.Chain.StakingPool do field(:are_delegators_banned, :boolean, default: false) field(:likelihood, :decimal) field(:block_reward_ratio, :decimal) - field(:staked_ratio, :decimal) + field(:stakes_ratio, :decimal) field(:validator_reward_ratio, :decimal) field(:snapshotted_validator_reward_ratio, :decimal) field(:self_staked_amount, :decimal) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 9b62f394d421..d2e70fc2cbac 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -16,7 +16,7 @@ defmodule Explorer.Staking.ContractReader do staking_allowed: {:staking, "areStakeAndWithdrawAllowed", []}, active_pools: {:staking, "getPools", []}, inactive_pools: {:staking, "getPoolsInactive", []}, - pools_likely: {:staking, "getPoolsToBeElected", []}, + pools_to_be_elected: {:staking, "getPoolsToBeElected", []}, pools_likelihood: {:staking, "getPoolsLikelihood", []}, validators: {:validator_set, "getValidators", []}, unremovable_validator: {:validator_set, "unremovableValidator", []}, @@ -50,13 +50,13 @@ defmodule Explorer.Staking.ContractReader do ] end - def delegator_requests(pool_address, delegator_address) do + def delegator_requests(pool_staking_address, delegator_address) do [ - stake_amount: {:staking, "stakeAmount", [pool_address, delegator_address]}, - ordered_withdraw: {:staking, "orderedWithdrawAmount", [pool_address, delegator_address]}, - max_withdraw_allowed: {:staking, "maxWithdrawAllowed", [pool_address, delegator_address]}, - max_ordered_withdraw_allowed: {:staking, "maxWithdrawOrderAllowed", [pool_address, delegator_address]}, - ordered_withdraw_epoch: {:staking, "orderWithdrawEpoch", [pool_address, delegator_address]} + stake_amount: {:staking, "stakeAmount", [pool_staking_address, delegator_address]}, + ordered_withdraw: {:staking, "orderedWithdrawAmount", [pool_staking_address, delegator_address]}, + max_withdraw_allowed: {:staking, "maxWithdrawAllowed", [pool_staking_address, delegator_address]}, + max_ordered_withdraw_allowed: {:staking, "maxWithdrawOrderAllowed", [pool_staking_address, delegator_address]}, + ordered_withdraw_epoch: {:staking, "orderWithdrawEpoch", [pool_staking_address, delegator_address]} ] end diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 16e47f3de435..31f1315ced81 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -173,7 +173,7 @@ defmodule Explorer.Staking.ContractState do [likelihood_values, total_likelihood] = global_responses.pools_likelihood likelihood = - global_responses.pools_likely + global_responses.pools_to_be_elected # array of pool addresses (staking addresses) |> Enum.zip(likelihood_values) |> Enum.into(%{}) @@ -217,7 +217,7 @@ defmodule Explorer.Staking.ContractState do %{ staking_address_hash: staking_address, delegators_count: length(staking_response.active_delegators), - staked_ratio: + stakes_ratio: if staking_response.is_active do ratio(staking_response.total_staked_amount, staked_total) end, diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index ca479a9b2e1a..63557c53633b 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -26,7 +26,7 @@ defmodule Explorer.Staking.StakeSnapshotting do pool_staking_addresses = pool_mining_addresses - |> Enum.map(&transform_requests/1) + |> Enum.map(&staking_by_mining_requests/1) |> ContractReader.perform_grouped_requests(pool_mining_addresses, contracts, abi) |> Enum.flat_map(fn {_, value} -> value end) |> Enum.map(fn {_key, staking_address_hash} -> decode_data(staking_address_hash) end) @@ -134,9 +134,9 @@ defmodule Explorer.Staking.StakeSnapshotting do }) end - def transform_requests(minig_address) do + def staking_by_mining_requests(mining_address) do [ - staking_address: {:validator_set, "stakingByMiningAddress", [minig_address]} + staking_address: {:validator_set, "stakingByMiningAddress", [mining_address]} ] end @@ -152,14 +152,14 @@ defmodule Explorer.Staking.StakeSnapshotting do ] end - defp delegator_requests(pool_address, delegator_address, block_number) do + defp delegator_requests(pool_staking_address, delegator_address, block_number) do [ - stake_amount: {:staking, "stakeAmount", [pool_address, delegator_address]}, - snapshotted_stake_amount: {:staking, "stakeAmount", [pool_address, delegator_address], block_number - 1}, - ordered_withdraw: {:staking, "orderedWithdrawAmount", [pool_address, delegator_address]}, - max_withdraw_allowed: {:staking, "maxWithdrawAllowed", [pool_address, delegator_address]}, - max_ordered_withdraw_allowed: {:staking, "maxWithdrawOrderAllowed", [pool_address, delegator_address]}, - ordered_withdraw_epoch: {:staking, "orderWithdrawEpoch", [pool_address, delegator_address]} + stake_amount: {:staking, "stakeAmount", [pool_staking_address, delegator_address]}, + snapshotted_stake_amount: {:staking, "stakeAmount", [pool_staking_address, delegator_address], block_number - 1}, + ordered_withdraw: {:staking, "orderedWithdrawAmount", [pool_staking_address, delegator_address]}, + max_withdraw_allowed: {:staking, "maxWithdrawAllowed", [pool_staking_address, delegator_address]}, + max_ordered_withdraw_allowed: {:staking, "maxWithdrawOrderAllowed", [pool_staking_address, delegator_address]}, + ordered_withdraw_epoch: {:staking, "orderWithdrawEpoch", [pool_staking_address, delegator_address]} ] end @@ -182,7 +182,7 @@ defmodule Explorer.Staking.StakeSnapshotting do are_delegators_banned: pool.are_delegators_banned, likelihood: pool.likelihood, block_reward_ratio: pool.block_reward_ratio, - staked_ratio: pool.staked_ratio, + stakes_ratio: pool.stakes_ratio, validator_reward_ratio: pool.validator_reward_ratio, ban_reason: pool.ban_reason, was_banned_count: pool.was_banned_count, diff --git a/apps/explorer/priv/repo/migrations/20190521104412_create_staking_pools.exs b/apps/explorer/priv/repo/migrations/20190521104412_create_staking_pools.exs index 7011fd962c0b..ce78745053bd 100644 --- a/apps/explorer/priv/repo/migrations/20190521104412_create_staking_pools.exs +++ b/apps/explorer/priv/repo/migrations/20190521104412_create_staking_pools.exs @@ -14,7 +14,7 @@ defmodule Explorer.Repo.Migrations.CreateStakingPools do add(:was_banned_count, :integer) add(:banned_until, :bigint) add(:likelihood, :decimal, precision: 5, scale: 2) - add(:staked_ratio, :decimal, precision: 5, scale: 2) + add(:stakes_ratio, :decimal, precision: 5, scale: 2) add(:staking_address_hash, :bytea) add(:mining_address_hash, :bytea) From 8bb66694a91b9092b6ac1c8315d6d848d26c0546 Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 20 Nov 2019 15:48:44 +0300 Subject: [PATCH 18/75] Fix start_snapshotting function --- apps/explorer/lib/explorer/staking/contract_reader.ex | 4 ++-- apps/explorer/lib/explorer/staking/contract_state.ex | 8 ++++---- .../lib/explorer/staking/stake_snapshotting.ex | 10 ++++++---- .../priv/contracts_abi/posdao/ValidatorSetAuRa.json | 4 ++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index d2e70fc2cbac..88f241846f49 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -20,8 +20,8 @@ defmodule Explorer.Staking.ContractReader do pools_likelihood: {:staking, "getPoolsLikelihood", []}, validators: {:validator_set, "getValidators", []}, unremovable_validator: {:validator_set, "unremovableValidator", []}, - pending_validators: {:validator_set, "getPendingValidators", []}, - be_finalized_validators: {:validator_set, "validatorsToBeFinalized", []}, + # pending_validators: {:validator_set, "getPendingValidators", []}, + # be_finalized_validators: {:validator_set, "validatorsToBeFinalized", []}, validator_set_apply_block: {:validator_set, "validatorSetApplyBlock", []} ] end diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 31f1315ced81..18a2125d0db1 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -7,6 +7,8 @@ defmodule Explorer.Staking.ContractState do use GenServer + require Logger + alias Explorer.Chain alias Explorer.Chain.Events.{Publisher, Subscriber} alias Explorer.SmartContract.Reader @@ -118,8 +120,6 @@ defmodule Explorer.Staking.ContractState do end defp fetch_state(contracts, abi, block_number) do - previous_epoch = get(:epoch_number, 0) - global_responses = ContractReader.perform_requests(ContractReader.global_requests(), contracts, abi) token = get_token(global_responses.token_contract_address) @@ -268,11 +268,11 @@ defmodule Explorer.Staking.ContractState do timeout: :infinity }) - if previous_epoch && previous_epoch != 0 && previous_epoch != global_responses.epoch_number do + if global_responses.epoch_start_block == block_number + 1 do with( true <- :ets.insert(@table_name, is_snapshotted: false), {:ok, _} <- - StakeSnapshotting.start_snapshoting( + StakeSnapshotting.start_snapshotting( %{contracts: contracts, abi: abi, global_responses: global_responses}, block_number ) diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 63557c53633b..e75b27a4da81 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -7,22 +7,24 @@ defmodule Explorer.Staking.StakeSnapshotting do import Ecto.Query, only: [from: 2] + require Logger + alias Explorer.Chain alias Explorer.Chain.{StakingPool, StakingPoolsDelegator} alias Explorer.SmartContract.Reader alias Explorer.Staking.ContractReader - def start_snapshoting(%{contracts: contracts, abi: abi, global_responses: global_responses}, block_number) do + def start_snapshotting(%{contracts: contracts, abi: abi, global_responses: global_responses}, block_number) do %{ - "getPendingValidators" => {:ok, [pending_validators_mining_addresses]}, - "validatorsToBeFinalized" => {:ok, [be_finalized_validators_mining_addresses]} + "getPendingValidators" => {:ok, [pending_validators]}, + "validatorsToBeFinalized" => {:ok, [to_be_finalized_validators]} } = Reader.query_contract(contracts.validator_set, abi, %{ "getPendingValidators" => [], "validatorsToBeFinalized" => [] }) - pool_mining_addresses = Enum.uniq(pending_validators_mining_addresses ++ be_finalized_validators_mining_addresses) + pool_mining_addresses = Enum.uniq(pending_validators ++ to_be_finalized_validators) pool_staking_addresses = pool_mining_addresses diff --git a/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json b/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json index fcfd9237bc2a..7906f27317c5 100644 --- a/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/ValidatorSetAuRa.json @@ -557,7 +557,7 @@ "name": "getPendingValidators", "outputs": [ { - "name": "_miningAddress", + "name": "", "type": "address[]" } ], @@ -571,7 +571,7 @@ "name": "validatorsToBeFinalized", "outputs": [ { - "name": "_miningAddress", + "name": "miningAddresses", "type": "address[]" } ], From d6125b2c192a3d430bde03e6d90bd8d6566e6349 Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 20 Nov 2019 16:28:33 +0300 Subject: [PATCH 19/75] Fix round error for reward ratios --- .../lib/block_scout_web/channels/stakes_channel.ex | 4 ++-- .../stakes/_stakes_modal_delegators_list.html.eex | 8 ++++---- apps/explorer/lib/explorer/staking/contract_state.ex | 4 ++-- apps/explorer/lib/explorer/staking/stake_snapshotting.ex | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) 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 6857470b14db..5a26b0158e70 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 @@ -55,7 +55,7 @@ defmodule BlockScoutWeb.StakesChannel do pool = Chain.staking_pool(staking_address) token = ContractState.get(:token) - is_show_snapshotted_data = + show_snapshotted_data = pool.is_validator && ContractState.get(:validator_set_apply_block) > 0 && ContractState.get(:is_snapshotted) delegators = @@ -77,7 +77,7 @@ defmodule BlockScoutWeb.StakesChannel do pool: pool, delegators: delegators, token: token, - is_show_snapshotted_data: is_show_snapshotted_data + show_snapshotted_data: show_snapshotted_data ) {:reply, {:ok, %{html: html}}, socket} diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index 6572a842c3d0..7604a1d56acd 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -15,7 +15,7 @@
<%= amount_col_title = - if @is_show_snapshotted_data do + if @show_snapshotted_data do gettext("Current Stake Amount") <> "
(" <> gettext("Accounted Stake Amount") <> ")" else gettext("Current Stake Amount") @@ -27,7 +27,7 @@
<%= reward_col_title = - if @is_show_snapshotted_data do + if @show_snapshotted_data do gettext("Potential Reward Percent") <> "
(" <> gettext("Current Reward Percent") <> ")" else gettext("Potential Reward Percent") @@ -69,7 +69,7 @@
<%= format_token_amount(delegator.stake_amount, @token, symbol: false) %> - <%= if @is_show_snapshotted_data do %> + <%= if @show_snapshotted_data do %> ( <%= if delegator.snapshotted_stake_amount do @@ -98,7 +98,7 @@ %> <%= if reward.reward_ratio do %> <%= reward.reward_ratio %>% - <%= if @is_show_snapshotted_data do %> + <%= if @show_snapshotted_data do %> ( <%= if reward.snapshotted_reward_ratio do diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 18a2125d0db1..a7ddbdbfbdec 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -221,7 +221,7 @@ defmodule Explorer.Staking.ContractState do if staking_response.is_active do ratio(staking_response.total_staked_amount, staked_total) end, - validator_reward_ratio: pool_reward_response.validator_share / 10_000, + validator_reward_ratio: Float.floor(pool_reward_response.validator_share / 10_000, 2), likelihood: ratio(likelihood[staking_address] || 0, total_likelihood), block_reward_ratio: staking_response.block_reward / 10_000, is_deleted: false, @@ -257,7 +257,7 @@ defmodule Explorer.Staking.ContractState do delegator_address_hash: delegator_address, pool_address_hash: pool_address, is_active: is_active, - reward_ratio: delegator_reward_response.delegator_share / 10_000 + reward_ratio: Float.floor(delegator_reward_response.delegator_share / 10_000, 2) }) end) diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index e75b27a4da81..62f1bbfd7634 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -97,7 +97,7 @@ defmodule Explorer.Staking.StakeSnapshotting do %{ staking_address_hash: staking_address, delegators_count: length(staking_response.active_delegators), - snapshotted_validator_reward_ratio: pool_reward_response.validator_share / 10_000 + snapshotted_validator_reward_ratio: Float.floor(pool_reward_response.validator_share / 10_000, 2) } |> Map.merge( Map.take(staking_response, [ @@ -125,7 +125,7 @@ defmodule Explorer.Staking.StakeSnapshotting do delegator_address_hash: delegator_address, pool_address_hash: pool_address, is_active: is_active, - snapshotted_reward_ratio: delegator_reward_response.delegator_share / 10_000 + snapshotted_reward_ratio: Float.floor(delegator_reward_response.delegator_share / 10_000, 2) }) end) From 89f10c074f49034e690f33a3e0d638a6367bd11c Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 21 Nov 2019 11:05:31 +0300 Subject: [PATCH 20/75] Add links to addresses in Delegators window --- .../assets/css/components/stakes/_stakes.scss | 5 +++++ .../lib/block_scout_web/channels/stakes_channel.ex | 1 + .../templates/stakes/_stakes_modal_delegators_list.html.eex | 6 +++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/css/components/stakes/_stakes.scss b/apps/block_scout_web/assets/css/components/stakes/_stakes.scss index 7334e5211a07..a01e58efead5 100644 --- a/apps/block_scout_web/assets/css/components/stakes/_stakes.scss +++ b/apps/block_scout_web/assets/css/components/stakes/_stakes.scss @@ -93,6 +93,11 @@ $stakes-stats-item-border-color: #fff !default; .stakes-tr-banned & { color: $stakes-banned-color; } + + a { + text-decoration: none; + color: $stakes-address-color; + } } .stakes-address-active { 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 5a26b0158e70..98127830cf3f 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 @@ -75,6 +75,7 @@ defmodule BlockScoutWeb.StakesChannel do View.render_to_string(StakesView, "_stakes_modal_delegators_list.html", account: socket.assigns[:account], pool: pool, + conn: socket, delegators: delegators, token: token, show_snapshotted_data: show_snapshotted_data diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index 7604a1d56acd..305250871b4f 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -47,7 +47,11 @@
- <%= BlockScoutWeb.AddressView.trimmed_hash(delegator.delegator_address_hash) %> + <%= link( + BlockScoutWeb.AddressView.trimmed_hash(delegator.delegator_address_hash), + to: address_path(@conn, :show, delegator.delegator_address_hash), + target: "_blank" + ) %> <%= if delegator.delegator_address_hash == @pool.staking_address_hash and @pool.is_validator do %> <%= render BlockScoutWeb.CommonComponentsView, "_check_tooltip.html", text: gettext("This is a validator") %> From 64650a38948dc882e1024e0d69aa3dc7ae330fe5 Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 21 Nov 2019 14:58:55 +0300 Subject: [PATCH 21/75] Fix tooltip in Delegators window --- .../channels/stakes_channel.ex | 18 +++--- .../_stakes_modal_delegators_list.html.eex | 54 ++++++++++++------ apps/block_scout_web/priv/gettext/default.pot | 53 ++++++++++++------ .../priv/gettext/en/LC_MESSAGES/default.po | 55 ++++++++++++------- 4 files changed, 118 insertions(+), 62 deletions(-) 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 98127830cf3f..4045608014d7 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 @@ -51,22 +51,22 @@ defmodule BlockScoutWeb.StakesChannel do {:reply, {:ok, %{html: html}}, socket} end - def handle_in("render_delegators_list", %{"address" => staking_address}, socket) do - pool = Chain.staking_pool(staking_address) + def handle_in("render_delegators_list", %{"address" => pool_staking_address}, socket) do + pool = Chain.staking_pool(pool_staking_address) token = ContractState.get(:token) show_snapshotted_data = pool.is_validator && ContractState.get(:validator_set_apply_block) > 0 && ContractState.get(:is_snapshotted) - delegators = - staking_address + stakers = + pool_staking_address |> Chain.staking_pool_delegators() - |> Enum.sort_by(fn delegator -> - delegator_address = to_string(delegator.delegator_address_hash) + |> Enum.sort_by(fn staker -> + staker_address = to_string(staker.delegator_address_hash) cond do - delegator_address == staking_address -> 0 - delegator_address == socket.assigns[:account] -> 1 + staker_address == pool_staking_address -> 0 + staker_address == socket.assigns[:account] -> 1 true -> 2 end end) @@ -76,7 +76,7 @@ defmodule BlockScoutWeb.StakesChannel do account: socket.assigns[:account], pool: pool, conn: socket, - delegators: delegators, + stakers: stakers, token: token, show_snapshotted_data: show_snapshotted_data ) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index 305250871b4f..61b0e3f3dff7 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -10,7 +10,21 @@
- <%= render BlockScoutWeb.StakesView, "_stakes_th.html", title: gettext("Staker's Address"), tooltip: gettext("All pool participant addresses. The top address belongs to the validator.") %> + <%= + pool_type = + if @pool.is_validator do + gettext("validator") + else + gettext("candidate") + end + + render( + BlockScoutWeb.StakesView, + "_stakes_th.html", + title: gettext("Staker's Address"), + tooltip: gettext("All pool participant addresses. The top address belongs to the %{pool_type}.", pool_type: pool_type) + ) + %>
<%= @@ -41,22 +55,30 @@
- <%= for {delegator, index} <- Enum.with_index(@delegators, 1) do %> + <%= for {staker, index} <- Enum.with_index(@stakers, 1) do %>
<%= index %>
- <%= link( - BlockScoutWeb.AddressView.trimmed_hash(delegator.delegator_address_hash), - to: address_path(@conn, :show, delegator.delegator_address_hash), - target: "_blank" - ) %> + <%= + link( + BlockScoutWeb.AddressView.trimmed_hash(staker.delegator_address_hash), + to: address_path(@conn, :show, staker.delegator_address_hash), + target: "_blank" + ) + %> - <%= if delegator.delegator_address_hash == @pool.staking_address_hash and @pool.is_validator do %> - <%= render BlockScoutWeb.CommonComponentsView, "_check_tooltip.html", text: gettext("This is a validator") %> + <%= if staker.delegator_address_hash == @pool.staking_address_hash do %> + <%= + render( + BlockScoutWeb.CommonComponentsView, + "_check_tooltip.html", + text: gettext("This is a %{pool_type}. The rest addresses are delegators of its pool.", pool_type: pool_type) + ) + %> <% end %> - <%= if to_string(delegator.delegator_address_hash) == @account do %> + <%= if to_string(staker.delegator_address_hash) == @account do %>
- <%= format_token_amount(delegator.stake_amount, @token, symbol: false) %> + <%= format_token_amount(staker.stake_amount, @token, symbol: false) %> <%= if @show_snapshotted_data do %> ( <%= - if delegator.snapshotted_stake_amount do - format_token_amount(delegator.snapshotted_stake_amount, @token, symbol: false) + if staker.snapshotted_stake_amount do + format_token_amount(staker.snapshotted_stake_amount, @token, symbol: false) else 0 end @@ -88,15 +110,15 @@
<% reward = - if delegator.delegator_address_hash == @pool.staking_address_hash do + if staker.delegator_address_hash == @pool.staking_address_hash do %{ reward_ratio: @pool.validator_reward_ratio, snapshotted_reward_ratio: @pool.snapshotted_validator_reward_ratio } else %{ - reward_ratio: delegator.reward_ratio, - snapshotted_reward_ratio: delegator.snapshotted_reward_ratio + reward_ratio: staker.reward_ratio, + snapshotted_reward_ratio: staker.snapshotted_reward_ratio } end %> diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 7ff21b689b3d..4f743a23c308 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -1903,12 +1903,6 @@ msgstr "" msgid "Active Pools" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:13 -msgid "All pool participant addresses. The top address belongs to the validator." -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_withdraw.html.eex:18 msgid "Already Ordered:" @@ -1925,7 +1919,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:24 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:38 msgid "Amount of STAKE placed by an address" msgstr "" @@ -2028,7 +2022,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:63 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:89 msgid "It's me!" msgstr "" @@ -2039,7 +2033,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:65 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:91 msgid "ME" msgstr "" @@ -2099,8 +2093,8 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:31 -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:33 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:45 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:47 msgid "Potential Reward Percent" msgstr "" @@ -2116,7 +2110,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:39 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 msgid "Reward distribution is based on stake amount. Validator receives a minimum of 30%." msgstr "" @@ -2162,7 +2156,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:13 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:24 msgid "Staker's Address" msgstr "" @@ -2205,7 +2199,6 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_rows.html.eex:5 -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 msgid "This is a validator" msgstr "" @@ -2276,20 +2269,20 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:19 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:33 msgid "Accounted Stake Amount" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:31 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:45 msgid "Current Reward Percent" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:19 -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:21 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:33 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:35 msgid "Current Stake Amount" msgstr "" @@ -2297,3 +2290,27 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:49 msgid "Share of Pool’s Reward" msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:77 +msgid "This is a %{pool_type}. The rest addresses are delegators of its pool." +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:18 +msgid "candidate" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:16 +msgid "validator" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:25 +msgid "All pool participant addresses. The top address belongs to the %{pool_type}." +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 382e5571e1ee..26f8c10c8b9b 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -1903,12 +1903,6 @@ msgstr "" msgid "Active Pools" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:13 -msgid "All pool participant addresses. The top address belongs to the validator." -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_withdraw.html.eex:18 msgid "Already Ordered:" @@ -1925,7 +1919,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:24 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:38 msgid "Amount of STAKE placed by an address" msgstr "" @@ -2028,7 +2022,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:63 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:89 msgid "It's me!" msgstr "" @@ -2039,7 +2033,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:65 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:91 msgid "ME" msgstr "" @@ -2099,8 +2093,8 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:31 -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:33 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:45 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:47 msgid "Potential Reward Percent" msgstr "" @@ -2116,7 +2110,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:39 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 msgid "Reward distribution is based on stake amount. Validator receives a minimum of 30%." msgstr "" @@ -2162,7 +2156,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:13 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:24 msgid "Staker's Address" msgstr "" @@ -2205,7 +2199,6 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_rows.html.eex:5 -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 msgid "This is a validator" msgstr "" @@ -2276,20 +2269,20 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:19 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:33 msgid "Accounted Stake Amount" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:31 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:45 msgid "Current Reward Percent" msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:19 -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:21 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:33 +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:35 msgid "Current Stake Amount" msgstr "" @@ -2297,3 +2290,27 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:49 msgid "Share of Pool’s Reward" msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:77 +msgid "This is a %{pool_type}. The rest addresses are delegators of its pool." +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:18 +msgid "candidate" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:16 +msgid "validator" +msgstr "" + +#, elixir-format, fuzzy +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:25 +msgid "All pool participant addresses. The top address belongs to the %{pool_type}." +msgstr "" From c5b69dace9ffbcdebc566c0a4fb79a15b3859561 Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 21 Nov 2019 15:49:37 +0300 Subject: [PATCH 22/75] Rename some DB fields --- .../channels/stakes_channel.ex | 6 ++--- .../controllers/stakes_controller.ex | 4 ++-- .../templates/stakes/_rows.html.eex | 4 ++-- .../_stakes_modal_delegators_list.html.eex | 10 ++++----- .../stakes/_stakes_modal_move.html.eex | 2 +- .../stakes/_stakes_modal_pool_info.html.eex | 2 +- apps/explorer/lib/explorer/chain.ex | 22 +++++++++---------- .../import/runner/staking_pools_delegators.ex | 6 ++--- .../lib/explorer/chain/staking_pool.ex | 2 +- .../explorer/chain/staking_pools_delegator.ex | 14 ++++++------ .../lib/explorer/staking/contract_state.ex | 4 ++-- .../explorer/staking/stake_snapshotting.ex | 4 ++-- ...112839_create_staking_pools_delegators.exs | 8 +++---- ...0190807111216_remove_duplicate_indexes.exs | 4 ++-- .../chain/staking_pools_delegator_test.exs | 2 +- apps/explorer/test/support/factory.ex | 4 ++-- 16 files changed, 49 insertions(+), 49 deletions(-) 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 4045608014d7..7c11511d6d09 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 @@ -62,7 +62,7 @@ defmodule BlockScoutWeb.StakesChannel do pool_staking_address |> Chain.staking_pool_delegators() |> Enum.sort_by(fn staker -> - staker_address = to_string(staker.delegator_address_hash) + staker_address = to_string(staker.address_hash) cond do staker_address == pool_staking_address -> 0 @@ -148,7 +148,7 @@ defmodule BlockScoutWeb.StakesChannel do token = ContractState.get(:token) min_from_stake = - if delegator_from.delegator_address_hash == delegator_from.pool_address_hash do + if delegator_from.address_hash == delegator_from.staking_address_hash do ContractState.get(:min_candidate_stake) else ContractState.get(:min_delegator_stake) @@ -201,7 +201,7 @@ defmodule BlockScoutWeb.StakesChannel do delegator = Chain.staking_pool_delegator(staking_address, socket.assigns.account) min_stake = - if delegator.delegator_address_hash == delegator.pool_address_hash do + if delegator.address_hash == delegator.staking_address_hash do ContractState.get(:min_candidate_stake) else ContractState.get(:min_delegator_stake) 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 f28519102feb..6ca15827e96a 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 @@ -25,7 +25,7 @@ defmodule BlockScoutWeb.StakesController do account = if account_address = conn.assigns[:account] do account_address - |> Chain.get_total_staked() + |> Chain.get_total_staked_and_ordered() |> Map.merge(%{ address: account_address, balance: Chain.fetch_last_token_balance(account_address, token.contract_address_hash), @@ -141,7 +141,7 @@ defmodule BlockScoutWeb.StakesController do end defp stake_allowed?(pool, delegator) do - Decimal.positive?(pool.self_staked_amount) or delegator.delegator_address_hash == pool.staking_address_hash + Decimal.positive?(pool.self_staked_amount) or delegator.address_hash == pool.staking_address_hash end defp move_allowed?(nil), do: false diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex index 8ac2afb7c77e..2aa0b50325c1 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex @@ -36,7 +36,7 @@ <%= gettext("Banned until block #%{banned_until} (%{estimated_unban_day})", banned_until: @pool.banned_until, estimated_unban_day: estimated_unban_day(@pool.banned_until, @average_block_time)) %> <%= if @delegator && - @delegator.delegator_address_hash != @pool.staking_address_hash && + @delegator.address_hash != @pool.staking_address_hash && @pool.are_delegators_banned && @pool.banned_until != @pool.banned_delegators_until do %> <%= raw(".
") %> @@ -47,7 +47,7 @@ <%= if !@pool.is_banned || (!@pool.are_delegators_banned && @delegator && - @delegator.delegator_address_hash != @pool.staking_address_hash + @delegator.address_hash != @pool.staking_address_hash ) do %>
<%= if @buttons.move do %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index 61b0e3f3dff7..bb9824bf7b59 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -63,13 +63,13 @@ <%= link( - BlockScoutWeb.AddressView.trimmed_hash(staker.delegator_address_hash), - to: address_path(@conn, :show, staker.delegator_address_hash), + BlockScoutWeb.AddressView.trimmed_hash(staker.address_hash), + to: address_path(@conn, :show, staker.address_hash), target: "_blank" ) %> - <%= if staker.delegator_address_hash == @pool.staking_address_hash do %> + <%= if staker.address_hash == @pool.staking_address_hash do %> <%= render( BlockScoutWeb.CommonComponentsView, @@ -78,7 +78,7 @@ ) %> <% end %> - <%= if to_string(staker.delegator_address_hash) == @account do %> + <%= if to_string(staker.address_hash) == @account do %>
<% reward = - if staker.delegator_address_hash == @pool.staking_address_hash do + if staker.address_hash == @pool.staking_address_hash do %{ reward_ratio: @pool.validator_reward_ratio, snapshotted_reward_ratio: @pool.snapshotted_validator_reward_ratio diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_move.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_move.html.eex index 7283a661119e..84cc730e97e4 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_move.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_move.html.eex @@ -22,7 +22,7 @@ <%= for %{pool: pool} <- @pools, pool.staking_address_hash != @pool_from.staking_address_hash, - Decimal.positive?(pool.self_staked_amount) or pool.staking_address_hash == @delegator_from.delegator_address_hash do %> + Decimal.positive?(pool.self_staked_amount) or pool.staking_address_hash == @delegator_from.address_hash do %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex index ece74027c6e9..674a443ee661 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex @@ -47,7 +47,7 @@ render BlockScoutWeb.StakesView, "_stakes_validator_info_item.html", title: gettext("Share of Pool’s Reward"), - value: "#{@validator.block_reward_ratio}%" + value: "#{@validator.validator_reward_percent}%" %> <%= render BlockScoutWeb.StakesView, diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 4f743a23c308..dff65478da6f 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2108,12 +2108,6 @@ msgstr "" msgid "Remove My Pool" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 -msgid "Reward distribution is based on stake amount. Validator receives a minimum of 30%." -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_title.html.eex:8 msgid "Show banned only" @@ -2314,3 +2308,9 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:25 msgid "All pool participant addresses. The top address belongs to the %{pool_type}." msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 +msgid "Reward distribution is based on stake amount. Validator receives a minimum of %{min}%." +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 26f8c10c8b9b..f145192ae491 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2108,12 +2108,6 @@ msgstr "" msgid "Remove My Pool" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 -msgid "Reward distribution is based on stake amount. Validator receives a minimum of 30%." -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_title.html.eex:8 msgid "Show banned only" @@ -2309,8 +2303,14 @@ msgstr "" msgid "validator" msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:25 msgid "All pool participant addresses. The top address belongs to the %{pool_type}." msgstr "" + +#, elixir-format, fuzzy +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 +msgid "Reward distribution is based on stake amount. Validator receives a minimum of %{min}%." +msgstr "" diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 6caf7d3849df..60e11e50ad69 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -130,7 +130,7 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do is_unremovable: fragment("EXCLUDED.is_unremovable"), are_delegators_banned: fragment("EXCLUDED.are_delegators_banned"), likelihood: fragment("EXCLUDED.likelihood"), - block_reward_ratio: fragment("EXCLUDED.block_reward_ratio"), + validator_reward_percent: fragment("EXCLUDED.validator_reward_percent"), stakes_ratio: fragment("EXCLUDED.stakes_ratio"), validator_reward_ratio: fragment("EXCLUDED.validator_reward_ratio"), self_staked_amount: fragment("EXCLUDED.self_staked_amount"), diff --git a/apps/explorer/lib/explorer/chain/staking_pool.ex b/apps/explorer/lib/explorer/chain/staking_pool.ex index 92b97bde5f55..c7ee0ecaeb7c 100644 --- a/apps/explorer/lib/explorer/chain/staking_pool.ex +++ b/apps/explorer/lib/explorer/chain/staking_pool.ex @@ -24,7 +24,7 @@ defmodule Explorer.Chain.StakingPool do is_unremovable: boolean, are_delegators_banned: boolean, likelihood: Decimal.t(), - block_reward_ratio: Decimal.t(), + validator_reward_percent: Decimal.t(), stakes_ratio: Decimal.t(), validator_reward_ratio: Decimal.t(), snapshotted_validator_reward_ratio: Decimal.t(), @@ -41,7 +41,7 @@ defmodule Explorer.Chain.StakingPool do @attrs ~w( is_active delegators_count total_staked_amount self_staked_amount snapshotted_total_staked_amount snapshotted_self_staked_amount is_validator was_validator_count is_banned are_delegators_banned ban_reason was_banned_count banned_until banned_delegators_until likelihood - stakes_ratio validator_reward_ratio snapshotted_validator_reward_ratio staking_address_hash mining_address_hash block_reward_ratio + stakes_ratio validator_reward_ratio snapshotted_validator_reward_ratio staking_address_hash mining_address_hash validator_reward_percent is_unremovable )a @req_attrs ~w( @@ -60,7 +60,7 @@ defmodule Explorer.Chain.StakingPool do field(:is_unremovable, :boolean, default: false) field(:are_delegators_banned, :boolean, default: false) field(:likelihood, :decimal) - field(:block_reward_ratio, :decimal) + field(:validator_reward_percent, :decimal) field(:stakes_ratio, :decimal) field(:validator_reward_ratio, :decimal) field(:snapshotted_validator_reward_ratio, :decimal) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index d41460abc2b1..d93128f99913 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -28,7 +28,7 @@ defmodule Explorer.Staking.ContractReader do def pool_staking_requests(staking_address) do [ active_delegators: {:staking, "poolDelegators", [staking_address]}, - block_reward: {:block_reward, "validatorRewardPercent", [staking_address]}, + validator_reward_percent: {:block_reward, "validatorRewardPercent", [staking_address]}, inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]}, is_active: {:staking, "isPoolActive", [staking_address]}, mining_address_hash: {:validator_set, "miningByStakingAddress", [staking_address]}, @@ -65,6 +65,12 @@ defmodule Explorer.Staking.ContractReader do ] end + def validator_min_reward_percent_request(epoch_number) do + [ + value: {:block_reward, "validatorMinRewardPercent", [epoch_number]} + ] + end + # args = [staking_epoch, validator_staked, total_staked, pool_reward \\ 10_00000] def validator_reward_requests(args) do [ diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 4de7e6ac52f9..3676cb6c8221 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -28,6 +28,7 @@ defmodule Explorer.Staking.ContractState do :validator_set_contract, :block_reward_contract, :validator_set_apply_block, + :validator_min_reward_percent, :is_snapshotted ] @@ -123,6 +124,9 @@ defmodule Explorer.Staking.ContractState do # read general info from the contracts (including pool list and validator list) 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( + ContractReader.validator_min_reward_percent_request(global_responses.epoch_number), contracts, abi + ).value start_snapshotting = (global_responses.epoch_start_block == block_number + 1) is_validator = Enum.into(global_responses.validators, %{}, &{hash_to_string(&1), true}) @@ -143,6 +147,7 @@ defmodule Explorer.Staking.ContractState do ]) |> Map.to_list() |> Enum.concat(token: token) + |> Enum.concat(validator_min_reward_percent: validator_min_reward_percent) :ets.insert(@table_name, settings) @@ -199,75 +204,79 @@ defmodule Explorer.Staking.ContractState do # get amounts for each of the stakers staker_responses = stakers - |> Enum.map(fn {pool_staking_address, staker_address, _} -> + |> Enum.map(fn {pool_staking_address, staker_address, _is_active} -> ContractReader.staker_requests(pool_staking_address, staker_address) end) |> ContractReader.perform_grouped_requests(stakers, contracts, abi) - # calculate total amount staked into all active pools - staked_total = Enum.sum(for {_, pool} <- pool_staking_responses, pool.is_active, do: pool.total_staked_amount) - - [likelihood_values, total_likelihood] = global_responses.pools_likelihood - - likelihood = - global_responses.pools_to_be_elected # array of pool addresses (staking addresses) - |> Enum.zip(likelihood_values) - |> Enum.into(%{}) - + # to keep sort order pool_staking_keys = Enum.map(pool_staking_responses, fn {key, _} -> key end) candidate_reward_responses = pool_staking_responses - |> Enum.map(fn {_address, response} -> + |> Enum.map(fn {_pool_staking_address, resp} -> ContractReader.validator_reward_requests([ global_responses.epoch_number, - response.self_staked_amount, - response.total_staked_amount, + resp.self_staked_amount, + resp.total_staked_amount, 1000_000 ]) end) |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) + # to keep sort order delegator_keys = Enum.map(staker_responses, fn {key, _} -> key end) delegator_reward_responses = staker_responses - |> Enum.map(fn {{pool_address, _, _}, response} -> - staking_response = pool_staking_responses[pool_address] + |> Enum.map(fn {{pool_staking_address, _staker_address, _is_active}, resp} -> + staking_resp = pool_staking_responses[pool_staking_address] ContractReader.delegator_reward_requests([ global_responses.epoch_number, - response.stake_amount, - staking_response.self_staked_amount, - staking_response.total_staked_amount, + resp.stake_amount, + staking_resp.self_staked_amount, + staking_resp.total_staked_amount, 1000_000 ]) end) |> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi) + # calculate total amount staked into all active pools + staked_total = Enum.sum(for {_, pool} <- pool_staking_responses, pool.is_active, do: pool.total_staked_amount) + + # calculate likelihood of becoming a validator on the next epoch + [likelihood_values, total_likelihood] = global_responses.pools_likelihood + + likelihood = + global_responses.pools_to_be_elected # array of pool addresses (staking addresses) + |> Enum.zip(likelihood_values) + |> Enum.into(%{}) + + # form entries for writing to the `staking_pools` table in DB pool_entries = - Enum.map(pools, fn staking_address -> - staking_response = pool_staking_responses[staking_address] - mining_response = pool_mining_responses[staking_address] - candidate_reward_response = candidate_reward_responses[staking_address] + Enum.map(pools, fn pool_staking_address -> + staking_resp = pool_staking_responses[pool_staking_address] + mining_resp = pool_mining_responses[pool_staking_address] + candidate_reward_resp = candidate_reward_responses[pool_staking_address] %{ - staking_address_hash: staking_address, - delegators_count: length(staking_response.active_delegators), + staking_address_hash: pool_staking_address, + delegators_count: length(staking_resp.active_delegators), stakes_ratio: - if staking_response.is_active do - ratio(staking_response.total_staked_amount, staked_total) + if staking_resp.is_active do + ratio(staking_resp.total_staked_amount, staked_total) end, - validator_reward_ratio: Float.floor(candidate_reward_response.validator_share / 10_000, 2), - likelihood: ratio(likelihood[staking_address] || 0, total_likelihood), - block_reward_ratio: staking_response.block_reward / 10_000, + validator_reward_ratio: Float.floor(candidate_reward_resp.validator_share / 10_000, 2), + likelihood: ratio(likelihood[pool_staking_address] || 0, total_likelihood), + validator_reward_percent: staking_resp.validator_reward_percent / 10_000, is_deleted: false, - is_validator: is_validator[staking_response.mining_address_hash] || false, - is_unremovable: hash_to_string(staking_address) == unremovable_validator, - ban_reason: binary_to_string(mining_response.ban_reason) + is_validator: is_validator[staking_resp.mining_address_hash] || false, + is_unremovable: hash_to_string(pool_staking_address) == unremovable_validator, + ban_reason: binary_to_string(mining_resp.ban_reason) } |> Map.merge( - Map.take(staking_response, [ + Map.take(staking_resp, [ :is_active, :mining_address_hash, :self_staked_amount, @@ -275,7 +284,7 @@ defmodule Explorer.Staking.ContractState do ]) ) |> Map.merge( - Map.take(mining_response, [ + Map.take(mining_resp, [ :are_delegators_banned, :banned_delegators_until, :banned_until, @@ -286,6 +295,7 @@ defmodule Explorer.Staking.ContractState do ) end) + # form entries for writing to the `staking_pools_delegators` table in DB delegator_entries = Enum.map(staker_responses, fn {{pool_address, delegator_address, is_active}, response} -> delegator_reward_response = delegator_reward_responses[{pool_address, delegator_address, is_active}] diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 13f2ef7ffed8..5f126ec30da6 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -97,9 +97,12 @@ defmodule Explorer.Staking.StakeSnapshotting do |> Enum.zip(stakers) |> Map.new(fn {key, val} -> {val, key} end) + # to keep sort order + pool_staking_keys = Enum.map(pool_staking_responses, fn {key, _} -> key end) + validator_reward_responses = pool_staking_responses - |> Enum.map(fn {_address, resp} -> + |> Enum.map(fn {_pool_staking_address, resp} -> ContractReader.validator_reward_requests([ epoch_number, resp.snapshotted_self_staked_amount, @@ -107,36 +110,39 @@ defmodule Explorer.Staking.StakeSnapshotting do 1000_000 ]) end) - |> ContractReader.perform_grouped_requests(pool_staking_addresses, contracts, abi) + |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) + + # to keep sort order + delegator_keys = Enum.map(staker_responses, fn {key, _} -> key end) delegator_reward_responses = staker_responses - |> Enum.map(fn {{pool_address, _delegator_address}, response} -> - staking_response = pool_staking_responses[pool_address] + |> Enum.map(fn {{pool_staking_address, _staker_address}, resp} -> + staking_resp = pool_staking_responses[pool_staking_address] ContractReader.delegator_reward_requests([ epoch_number, - response.snapshotted_stake_amount, - staking_response.snapshotted_self_staked_amount, - staking_response.snapshotted_total_staked_amount, + resp.snapshotted_stake_amount, + staking_resp.snapshotted_self_staked_amount, + staking_resp.snapshotted_total_staked_amount, 1000_000 ]) end) - |> ContractReader.perform_grouped_requests(stakers, contracts, abi) + |> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi) pool_entries = - Enum.map(pool_staking_addresses, fn staking_address -> - staking_response = pool_staking_responses[staking_address] - mining_response = pool_mining_responses[staking_address] - validator_reward_response = validator_reward_responses[staking_address] + Enum.map(pool_staking_addresses, fn pool_staking_address -> + staking_resp = pool_staking_responses[pool_staking_address] + mining_resp = pool_mining_responses[pool_staking_address] + validator_reward_resp = validator_reward_responses[pool_staking_address] %{ - staking_address_hash: staking_address, - delegators_count: length(staking_response.active_delegators), - snapshotted_validator_reward_ratio: Float.floor(validator_reward_response.validator_share / 10_000, 2) + staking_address_hash: pool_staking_address, + delegators_count: length(staking_resp.active_delegators), + snapshotted_validator_reward_ratio: Float.floor(validator_reward_resp.validator_share / 10_000, 2) } |> Map.merge( - Map.take(staking_response, [ + Map.take(staking_resp, [ :mining_address_hash, :self_staked_amount, :snapshotted_self_staked_amount, @@ -145,7 +151,7 @@ defmodule Explorer.Staking.StakeSnapshotting do ]) ) |> Map.merge( - Map.take(mining_response, [ + Map.take(mining_resp, [ :banned_until, :was_banned_count, :was_validator_count @@ -154,13 +160,13 @@ defmodule Explorer.Staking.StakeSnapshotting do end) delegator_entries = - Enum.map(staker_responses, fn {{pool_staking_address, staker_address}, response} -> - delegator_reward_response = delegator_reward_responses[{pool_staking_address, staker_address}] + Enum.map(staker_responses, fn {{pool_staking_address, staker_address}, resp} -> + delegator_reward_resp = delegator_reward_responses[{pool_staking_address, staker_address}] - Map.merge(response, %{ + Map.merge(resp, %{ address_hash: staker_address, staking_address_hash: pool_staking_address, - snapshotted_reward_ratio: Float.floor(delegator_reward_response.delegator_share / 10_000, 2) + snapshotted_reward_ratio: Float.floor(delegator_reward_resp.delegator_share / 10_000, 2) }) end) diff --git a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json index 6cabc8bcb233..234873d325c2 100644 --- a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json @@ -181,6 +181,25 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "validatorMinRewardPercent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], diff --git a/apps/explorer/priv/repo/migrations/20190718175620_add_block_reward_to_pools.exs b/apps/explorer/priv/repo/migrations/20190718175620_add_block_reward_to_pools.exs deleted file mode 100644 index b84376ab6e41..000000000000 --- a/apps/explorer/priv/repo/migrations/20190718175620_add_block_reward_to_pools.exs +++ /dev/null @@ -1,9 +0,0 @@ -defmodule Explorer.Repo.Migrations.AddBlockRewardToPools do - use Ecto.Migration - - def change do - alter table(:staking_pools) do - add(:block_reward_ratio, :decimal, precision: 5, scale: 2) - end - end -end diff --git a/apps/explorer/priv/repo/migrations/20190718175620_add_validator_reward_percent_to_pools.exs b/apps/explorer/priv/repo/migrations/20190718175620_add_validator_reward_percent_to_pools.exs new file mode 100644 index 000000000000..6a8e698e239c --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20190718175620_add_validator_reward_percent_to_pools.exs @@ -0,0 +1,9 @@ +defmodule Explorer.Repo.Migrations.AddValidatorRewardPercentToPools do + use Ecto.Migration + + def change do + alter table(:staking_pools) do + add(:validator_reward_percent, :decimal, precision: 5, scale: 2) + end + end +end From 94700997cbb8f0357e8e2fae64a40725657f76e2 Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 28 Nov 2019 17:46:17 +0300 Subject: [PATCH 27/75] Fix delegators counter and other improvements --- .../channels/stakes_channel.ex | 6 +-- apps/explorer/lib/explorer/chain.ex | 25 ++++++++--- apps/explorer/lib/explorer/chain/import.ex | 4 +- .../chain/import/runner/staking_pools.ex | 41 ++++++++++++++----- .../import/runner/staking_pools_delegators.ex | 26 +++++++----- .../lib/explorer/staking/contract_state.ex | 29 ++++++++++++- .../explorer/staking/stake_snapshotting.ex | 11 +++-- ...add_index_for_snapshotted_stake_amount.exs | 12 ++++++ 8 files changed, 116 insertions(+), 38 deletions(-) create mode 100644 apps/explorer/priv/repo/migrations/20191128144250_add_index_for_snapshotted_stake_amount.exs 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 501070492f5c..778a7f3356f8 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 @@ -55,13 +55,11 @@ defmodule BlockScoutWeb.StakesChannel do pool = Chain.staking_pool(pool_staking_address) token = ContractState.get(:token) validator_min_reward_percent = ContractState.get(:validator_min_reward_percent) - - show_snapshotted_data = - pool.is_validator && ContractState.get(:validator_set_apply_block) > 0 && ContractState.get(:is_snapshotted) + show_snapshotted_data = ContractState.show_snapshotted_data(pool.is_validator) stakers = pool_staking_address - |> Chain.staking_pool_delegators() + |> Chain.staking_pool_delegators(show_snapshotted_data) |> Enum.sort_by(fn staker -> staker_address = to_string(staker.address_hash) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 944c5e4b36d8..f4555fefec9a 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -3641,11 +3641,26 @@ defmodule Explorer.Chain do Repo.get_by(StakingPool, staking_address_hash: staking_address_hash) end - def staking_pool_delegators(staking_address_hash) do - StakingPoolsDelegator - |> where(staking_address_hash: ^staking_address_hash, is_active: true) - |> order_by(desc: :stake_amount) - |> Repo.all() + def staking_pool_delegators(staking_address_hash, show_snapshotted_data) do + from( + d in StakingPoolsDelegator, + where: + d.staking_address_hash == ^staking_address_hash and + (d.is_active == true or ^show_snapshotted_data and d.snapshotted_stake_amount > 0 and d.is_active != true), + order_by: + [desc: d.stake_amount] + ) |> Repo.all() + end + + def staking_pool_snapshotted_inactive_delegators_count(staking_address_hash) do + from( + d in StakingPoolsDelegator, + where: + d.staking_address_hash == ^staking_address_hash and + d.snapshotted_stake_amount > 0 and + d.is_active != true, + select: fragment("count(*)") + ) |> Repo.one() end def staking_pool_delegator(staking_address_hash, address_hash) do diff --git a/apps/explorer/lib/explorer/chain/import.ex b/apps/explorer/lib/explorer/chain/import.ex index b682e1adf15c..92721981f5e3 100644 --- a/apps/explorer/lib/explorer/chain/import.ex +++ b/apps/explorer/lib/explorer/chain/import.ex @@ -3,6 +3,8 @@ defmodule Explorer.Chain.Import do Bulk importing of data into `Explorer.Repo` """ + require Logger + alias Ecto.Changeset alias Explorer.Chain.Events.Publisher alias Explorer.Chain.Import @@ -246,7 +248,7 @@ defmodule Explorer.Chain.Import do defp validate_runner_option_params_required(runner_option_key, _), do: {:error, {:required, [runner_option_key, :params]}} - @local_options ~w(on_conflict params with timeout)a + @local_options ~w(on_conflict params with timeout clear_snapshotted_values)a defp validate_runner_options_known(runner_option_key, options) do unknown_option_keys = Map.keys(options) -- @local_options diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 60e11e50ad69..5d127f96f09f 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -36,17 +36,27 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do insert_options = options |> Map.get(option_key(), %{}) - |> Map.take(~w(on_conflict timeout)a) + |> Map.take(~w(on_conflict timeout clear_snapshotted_values)a) |> Map.put_new(:timeout, @timeout) |> Map.put(:timestamps, timestamps) - # Enforce ShareLocks tables order (see docs: sharelocks.md) + clear_snapshotted_values = case Map.fetch(insert_options, :clear_snapshotted_values) do + {:ok, v} -> v + :error -> false + end + + multi = if not clear_snapshotted_values do + # Enforce ShareLocks tables order (see docs: sharelocks.md) + Multi.run(multi, :acquire_all_staking_pools, fn repo, _ -> + acquire_all_staking_pools(repo) + end) + else + multi + end + multi - |> Multi.run(:acquire_all_staking_pools, fn repo, _ -> - acquire_all_staking_pools(repo) - end) |> Multi.run(:mark_as_deleted, fn repo, _ -> - mark_as_deleted(repo, changes_list, insert_options) + mark_as_deleted(repo, changes_list, insert_options, clear_snapshotted_values) end) |> Multi.run(:insert_staking_pools, fn repo, _ -> insert(repo, changes_list, insert_options) @@ -70,16 +80,27 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do {:ok, pools} end - defp mark_as_deleted(repo, changes_list, %{timeout: timeout}) when is_list(changes_list) do - addresses = Enum.map(changes_list, & &1.staking_address_hash) - - query = + defp mark_as_deleted(repo, changes_list, %{timeout: timeout}, clear_snapshotted_values) when is_list(changes_list) do + query = if clear_snapshotted_values do + from( + pool in StakingPool, + update: [ + set: [ + snapshotted_self_staked_amount: nil, + snapshotted_total_staked_amount: nil, + snapshotted_validator_reward_ratio: nil + ] + ] + ) + else + addresses = Enum.map(changes_list, & &1.staking_address_hash) from( pool in StakingPool, where: pool.staking_address_hash not in ^addresses, # ShareLocks order already enforced by `acquire_all_staking_pools` (see docs: sharelocks.md) update: [set: [is_deleted: true, is_active: false]] ) + end try do {_, result} = repo.update_all(query, [], timeout: timeout) diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex index a772ad3c3033..e6f37ed55f89 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex @@ -37,12 +37,12 @@ defmodule Explorer.Chain.Import.Runner.StakingPoolsDelegators do insert_options = options |> Map.get(option_key(), %{}) - |> Map.take(~w(on_conflict timeout)a) + |> Map.take(~w(on_conflict timeout clear_snapshotted_values)a) |> Map.put_new(:timeout, @timeout) |> Map.put(:timestamps, timestamps) multi - |> Multi.run(:delete_delegators, fn repo, _ -> + |> Multi.run(:clear_delegators, fn repo, _ -> mark_as_deleted(repo, insert_options) end) |> Multi.run(:insert_staking_pools_delegators, fn repo, _ -> @@ -53,17 +53,23 @@ defmodule Explorer.Chain.Import.Runner.StakingPoolsDelegators do @impl Import.Runner def timeout, do: @timeout - defp mark_as_deleted(repo, %{timeout: timeout}) do - query = + defp mark_as_deleted(repo, %{timeout: timeout} = options) do + clear_snapshotted_values = case Map.fetch(options, :clear_snapshotted_values) do + {:ok, v} -> v + :error -> false + end + + query = if clear_snapshotted_values do from( d in StakingPoolsDelegator, - update: [ - set: [ - is_active: false, - is_deleted: true - ] - ] + update: [set: [snapshotted_reward_ratio: nil, snapshotted_stake_amount: nil]] ) + else + from( + d in StakingPoolsDelegator, + update: [set: [is_active: false, is_deleted: true]] + ) + end try do {_, result} = repo.update_all(query, [], timeout: timeout) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 3676cb6c8221..95ac6e318c80 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -253,16 +253,27 @@ defmodule Explorer.Staking.ContractState do |> Enum.zip(likelihood_values) |> Enum.into(%{}) + is_snapshotted = get(:is_snapshotted) + # form entries for writing to the `staking_pools` table in DB pool_entries = Enum.map(pools, fn pool_staking_address -> staking_resp = pool_staking_responses[pool_staking_address] mining_resp = pool_mining_responses[pool_staking_address] candidate_reward_resp = candidate_reward_responses[pool_staking_address] + is_validator = is_validator[staking_resp.mining_address_hash] || false + + delegators_count = + length(staking_resp.active_delegators) + + if show_snapshotted_data(is_validator, global_responses.validator_set_apply_block, is_snapshotted) do + Chain.staking_pool_snapshotted_inactive_delegators_count(pool_staking_address) + else + 0 + end %{ staking_address_hash: pool_staking_address, - delegators_count: length(staking_resp.active_delegators), + delegators_count: delegators_count, stakes_ratio: if staking_resp.is_active do ratio(staking_resp.total_staked_amount, staked_total) @@ -271,7 +282,7 @@ defmodule Explorer.Staking.ContractState do likelihood: ratio(likelihood[pool_staking_address] || 0, total_likelihood), validator_reward_percent: staking_resp.validator_reward_percent / 10_000, is_deleted: false, - is_validator: is_validator[staking_resp.mining_address_hash] || false, + is_validator: is_validator, is_unremovable: hash_to_string(pool_staking_address) == unremovable_validator, ban_reason: binary_to_string(mining_resp.ban_reason) } @@ -330,6 +341,20 @@ defmodule Explorer.Staking.ContractState do Publisher.broadcast(:staking_update) end + def show_snapshotted_data(is_validator, validator_set_apply_block \\ nil, is_snapshotted \\ nil) do + validator_set_apply_block = if validator_set_apply_block !== nil do + validator_set_apply_block + else + get(:validator_set_apply_block) + end + is_snapshotted = if is_snapshotted !== nil do + is_snapshotted + else + get(:is_snapshotted) + end + is_validator && validator_set_apply_block > 0 && is_snapshotted + end + defp get_token(address) do with {:ok, address_hash} <- Chain.string_to_address_hash(address), {:ok, token} <- Chain.token_from_address_hash(address_hash) do diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 5f126ec30da6..10678db53885 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -63,12 +63,11 @@ defmodule Explorer.Staking.StakeSnapshotting do |> Enum.zip(pool_staking_addresses) |> Map.new(fn {key, val} -> {val, key} end) - # form a flat list of all stakers in the form {pool_staking_address, staker_address} + # form a flat list of all active stakers in the form {pool_staking_address, staker_address} stakers = Enum.flat_map(pool_staking_responses, fn {pool_staking_address, resp} -> [{pool_staking_address, pool_staking_address}] ++ - Enum.map(resp.active_delegators, &{pool_staking_address, &1}) ++ - Enum.map(resp.inactive_delegators, &{pool_staking_address, &1}) + Enum.map(resp.active_delegators, &{pool_staking_address, &1}) end) # get amounts for each of the stakers @@ -138,7 +137,7 @@ defmodule Explorer.Staking.StakeSnapshotting do %{ staking_address_hash: pool_staking_address, - delegators_count: length(staking_resp.active_delegators), + delegators_count: 0, snapshotted_validator_reward_ratio: Float.floor(validator_reward_resp.validator_share / 10_000, 2) } |> Map.merge( @@ -171,8 +170,8 @@ defmodule Explorer.Staking.StakeSnapshotting do end) case Chain.import(%{ - staking_pools: %{params: pool_entries, on_conflict: staking_pools_update()}, - staking_pools_delegators: %{params: delegator_entries, on_conflict: staking_pools_delegators_update()}, + 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}, timeout: :infinity }) do {:ok, _} -> :ets.insert(ets_table_name, is_snapshotted: true) diff --git a/apps/explorer/priv/repo/migrations/20191128144250_add_index_for_snapshotted_stake_amount.exs b/apps/explorer/priv/repo/migrations/20191128144250_add_index_for_snapshotted_stake_amount.exs new file mode 100644 index 000000000000..e7a0836235d9 --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20191128144250_add_index_for_snapshotted_stake_amount.exs @@ -0,0 +1,12 @@ +defmodule Explorer.Repo.Migrations.AddIndexForSnapshottedStakeAmount do + use Ecto.Migration + + def change do + create( + index(:staking_pools_delegators, [:staking_address_hash, :snapshotted_stake_amount, :is_active], + unique: false, + name: :snapshotted_stake_amount_index + ) + ) + end +end From c23305776189254472cb3ec639da19e795e87b34 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 29 Nov 2019 11:28:56 +0300 Subject: [PATCH 28/75] Add runner-specific options --- apps/explorer/lib/explorer/chain/import.ex | 16 +++++++++++----- .../explorer/lib/explorer/chain/import/runner.ex | 7 +++++++ .../chain/import/runner/staking_pools.ex | 3 +++ .../import/runner/staking_pools_delegators.ex | 3 +++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/import.ex b/apps/explorer/lib/explorer/chain/import.ex index 92721981f5e3..b80ec3b3d7c7 100644 --- a/apps/explorer/lib/explorer/chain/import.ex +++ b/apps/explorer/lib/explorer/chain/import.ex @@ -3,8 +3,6 @@ defmodule Explorer.Chain.Import do Bulk importing of data into `Explorer.Repo` """ - require Logger - alias Ecto.Changeset alias Explorer.Chain.Events.Publisher alias Explorer.Chain.Import @@ -227,8 +225,15 @@ defmodule Explorer.Chain.Import do defp validate_runner_options(runner, options) when is_map(options) do option_key = runner.option_key() + runner_specific_options = + if Map.has_key?(Enum.into(runner.__info__(:functions), %{}), :runner_specific_options) do + apply(runner, :runner_specific_options, []) + else + [] + end + case {validate_runner_option_params_required(option_key, options), - validate_runner_options_known(option_key, options)} do + validate_runner_options_known(option_key, options, runner_specific_options)} do {:ignore, :ok} -> :ignore {:ignore, {:error, _} = error} -> error {:ok, :ok} -> {:ok, {runner, options}} @@ -248,10 +253,11 @@ defmodule Explorer.Chain.Import do defp validate_runner_option_params_required(runner_option_key, _), do: {:error, {:required, [runner_option_key, :params]}} - @local_options ~w(on_conflict params with timeout clear_snapshotted_values)a + @local_options ~w(on_conflict params with timeout)a - defp validate_runner_options_known(runner_option_key, options) do + defp validate_runner_options_known(runner_option_key, options, runner_specific_options) do unknown_option_keys = Map.keys(options) -- @local_options + unknown_option_keys = unknown_option_keys -- runner_specific_options if Enum.empty?(unknown_option_keys) do :ok diff --git a/apps/explorer/lib/explorer/chain/import/runner.ex b/apps/explorer/lib/explorer/chain/import/runner.ex index 9600646a64ec..4aed5748d50c 100644 --- a/apps/explorer/lib/explorer/chain/import/runner.ex +++ b/apps/explorer/lib/explorer/chain/import/runner.ex @@ -50,4 +50,11 @@ defmodule Explorer.Chain.Import.Runner do @callback ecto_schema_module() :: module() @callback run(Multi.t(), changes_list, %{optional(atom()) => term()}) :: Multi.t() @callback timeout() :: timeout() + + @doc """ + The optional list of runner-specific options. + """ + @callback runner_specific_options() :: [atom()] + + @optional_callbacks runner_specific_options: 0 end diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 5d127f96f09f..55b3bc9d0f8a 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -23,6 +23,9 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do @impl Import.Runner def option_key, do: :staking_pools + @impl Import.Runner + def runner_specific_options, do: [:clear_snapshotted_values] + @impl Import.Runner def imported_table_row do %{ diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex index e6f37ed55f89..992cd8cf83da 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex @@ -24,6 +24,9 @@ defmodule Explorer.Chain.Import.Runner.StakingPoolsDelegators do @impl Import.Runner def option_key, do: :staking_pools_delegators + @impl Import.Runner + def runner_specific_options, do: [:clear_snapshotted_values] + @impl Import.Runner def imported_table_row do %{ From c27052d092cbfaa5635a7b185b79e53d5b0b2f5d Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 29 Nov 2019 17:33:56 +0300 Subject: [PATCH 29/75] Update BlockReward contract ERC balance --- .../lib/explorer/staking/contract_reader.ex | 39 ++--- .../lib/explorer/staking/contract_state.ex | 140 +++++++++++++----- .../explorer/staking/stake_snapshotting.ex | 26 +++- 3 files changed, 135 insertions(+), 70 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index d93128f99913..f1ccb7724386 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -1,26 +1,25 @@ defmodule Explorer.Staking.ContractReader do @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 def global_requests do [ - token_contract_address: {:staking, "erc677TokenContract", []}, - min_candidate_stake: {:staking, "candidateMinStake", []}, - min_delegator_stake: {:staking, "delegatorMinStake", []}, + active_pools: {:staking, "getPools", []}, + epoch_end_block: {:staking, "stakingEpochEndBlock", []}, epoch_number: {:staking, "stakingEpoch", []}, epoch_start_block: {:staking, "stakingEpochStartBlock", []}, - epoch_end_block: {:staking, "stakingEpochEndBlock", []}, - staking_allowed: {:staking, "areStakeAndWithdrawAllowed", []}, - active_pools: {:staking, "getPools", []}, inactive_pools: {:staking, "getPoolsInactive", []}, - pools_to_be_elected: {:staking, "getPoolsToBeElected", []}, + min_candidate_stake: {:staking, "candidateMinStake", []}, + min_delegator_stake: {:staking, "delegatorMinStake", []}, 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", []}, + validators: {:validator_set, "getValidators", []}, validator_set_apply_block: {:validator_set, "validatorSetApplyBlock", []} ] end @@ -28,23 +27,23 @@ defmodule Explorer.Staking.ContractReader do def pool_staking_requests(staking_address) do [ active_delegators: {:staking, "poolDelegators", [staking_address]}, - validator_reward_percent: {:block_reward, "validatorRewardPercent", [staking_address]}, inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]}, is_active: {:staking, "isPoolActive", [staking_address]}, mining_address_hash: {:validator_set, "miningByStakingAddress", [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 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]}, ban_reason: {:validator_set, "banReason", [mining_address]}, banned_until: {:validator_set, "bannedUntil", [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]} ] end @@ -85,18 +84,6 @@ defmodule Explorer.Staking.ContractReader do ] 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 requests |> generate_requests(contracts) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 95ac6e318c80..49ddde374606 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -1,7 +1,7 @@ defmodule Explorer.Staking.ContractState do @moduledoc """ 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. """ @@ -13,25 +13,28 @@ defmodule Explorer.Staking.ContractState do alias Explorer.Chain.Events.{Publisher, Subscriber} alias Explorer.SmartContract.Reader alias Explorer.Staking.{ContractReader, StakeSnapshotting} + alias Explorer.Token.{BalanceReader, MetadataRetriever} @table_name __MODULE__ @table_keys [ - :token_contract_address, - :token, - :min_candidate_stake, - :min_delegator_stake, + :block_reward_contract, + :epoch_end_block, :epoch_number, :epoch_start_block, - :epoch_end_block, + :is_snapshotted, + :min_candidate_stake, + :min_delegator_stake, :staking_allowed, :staking_contract, - :validator_set_contract, - :block_reward_contract, - :validator_set_apply_block, + :token_contract_address, + :token, :validator_min_reward_percent, - :is_snapshotted + :validator_set_apply_block, + :validator_set_contract ] + @token_renew_frequency 10 # frequency in blocks + defstruct [ :seen_block, :contracts, @@ -91,13 +94,15 @@ defmodule Explorer.Staking.ContractState do abi: staking_abi ++ validator_set_abi ++ block_reward_abi } + token = get_token(token_contract_address) + :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}, + is_snapshotted: false, + staking_contract: %{abi: staking_abi, address: staking_contract_address}, token_contract_address: token_contract_address, - token: get_token(token_contract_address), - is_snapshotted: false + token: token, + validator_set_contract: %{abi: validator_set_abi, address: validator_set_contract_address} ) {:ok, state, {:continue, []}} @@ -123,14 +128,13 @@ defmodule Explorer.Staking.ContractState do defp fetch_state(contracts, abi, block_number) do # read general info from the contracts (including pool list and validator list) 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( ContractReader.validator_min_reward_percent_request(global_responses.epoch_number), contracts, abi ).value - start_snapshotting = (global_responses.epoch_start_block == block_number + 1) - is_validator = Enum.into(global_responses.validators, %{}, &{hash_to_string(&1), true}) - unremovable_validator = global_responses.unremovable_validator + epoch_finished = (global_responses.epoch_start_block == block_number + 1) + is_validator = Enum.into(global_responses.validators, %{}, &{address_bytes_to_string(&1), true}) # save the general info to ETS (excluding pool list and validator list) settings = @@ -146,23 +150,32 @@ defmodule Explorer.Staking.ContractState do :validator_set_apply_block ]) |> Map.to_list() - |> Enum.concat(token: token) |> 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) # form the list of all pools - validators = if start_snapshotting do + validators = if epoch_finished do %{ - "getPendingValidators" => {:ok, [pending_validators]}, - "validatorsToBeFinalized" => {:ok, [to_be_finalized_validators]} + "getPendingValidators" => {:ok, [validators_pending]}, + "validatorsToBeFinalized" => {:ok, [validators_to_be_finalized]} } = Reader.query_contract(contracts.validator_set, abi, %{ "getPendingValidators" => [], "validatorsToBeFinalized" => [] }) - validators_pending = Enum.uniq(pending_validators ++ to_be_finalized_validators) - # get the list of all validators (the current and pending) + validators_pending = Enum.uniq(validators_pending ++ validators_to_be_finalized) %{ + # get the list of all validators (the current and pending) all: Enum.uniq(global_responses.validators ++ validators_pending), pending: validators_pending } @@ -170,30 +183,33 @@ defmodule Explorer.Staking.ContractState do %{all: global_responses.validators} end + # miningToStakingAddress mapping mining_to_staking_address = 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, 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( Map.values(mining_to_staking_address) ++ global_responses.active_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 = pools |> Enum.map(&ContractReader.pool_staking_requests/1) |> ContractReader.perform_grouped_requests(pools, contracts, abi) + # read pool info from the contracts by its mining address pool_mining_responses = pools |> Enum.map(&ContractReader.pool_mining_requests(pool_staking_responses[&1].mining_address_hash)) |> 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 = Enum.flat_map(pool_staking_responses, fn {pool_staking_address, resp} -> [{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}) end) - # get amounts for each of the stakers + # read info of each staker from the contracts staker_responses = stakers |> Enum.map(fn {pool_staking_address, staker_address, _is_active} -> @@ -209,9 +225,11 @@ defmodule Explorer.Staking.ContractState do end) |> ContractReader.perform_grouped_requests(stakers, contracts, abi) - # to keep sort order - pool_staking_keys = Enum.map(pool_staking_responses, fn {key, _} -> key end) + # to keep sort order when using `perform_grouped_requests` (see below) + 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 = pool_staking_responses |> Enum.map(fn {_pool_staking_address, resp} -> @@ -224,9 +242,11 @@ defmodule Explorer.Staking.ContractState do end) |> 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) + # 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 = staker_responses |> 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 [likelihood_values, total_likelihood] = global_responses.pools_likelihood - likelihood = global_responses.pools_to_be_elected # array of pool addresses (staking addresses) |> Enum.zip(likelihood_values) @@ -283,7 +302,7 @@ defmodule Explorer.Staking.ContractState do validator_reward_percent: staking_resp.validator_reward_percent / 10_000, is_deleted: false, 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) } |> Map.merge( @@ -319,6 +338,7 @@ defmodule Explorer.Staking.ContractState do }) end) + # perform SQL queries {:ok, _} = Chain.import(%{ staking_pools: %{params: pool_entries}, @@ -326,9 +346,44 @@ defmodule Explorer.Staking.ContractState do 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, [ - %{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_mining_responses, 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 + # notify the UI about new block Publisher.broadcast(:staking_update) end @@ -367,7 +423,19 @@ defmodule Explorer.Staking.ContractState do defp ratio(_numerator, 0), do: 0 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"] defp abi(file_name) do diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 10678db53885..07c40cc525a5 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -1,6 +1,6 @@ defmodule Explorer.Staking.StakeSnapshotting do @moduledoc """ - Makes snapshots of staked amounts + Makes snapshots of staked amounts. """ import Ecto.Query, only: [from: 2] @@ -12,7 +12,8 @@ defmodule Explorer.Staking.StakeSnapshotting do alias Explorer.Staking.ContractReader 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_mining_responses, cached_staker_responses, @@ -27,7 +28,8 @@ defmodule Explorer.Staking.StakeSnapshotting do pending_validators_mining_addresses |> 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 pool_staking_responses = pool_staking_addresses @@ -46,7 +48,7 @@ defmodule Explorer.Staking.StakeSnapshotting do |> Enum.zip(pool_staking_addresses) |> 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 pool_mining_responses = pool_staking_addresses @@ -63,14 +65,15 @@ defmodule Explorer.Staking.StakeSnapshotting do |> Enum.zip(pool_staking_addresses) |> 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 = Enum.flat_map(pool_staking_responses, fn {pool_staking_address, resp} -> [{pool_staking_address, pool_staking_address}] ++ Enum.map(resp.active_delegators, &{pool_staking_address, &1}) end) - # get amounts for each of the stakers + # read info of each staker from the contracts. # use `cached_staker_responses` when possible staker_responses = stakers @@ -96,9 +99,11 @@ defmodule Explorer.Staking.StakeSnapshotting do |> Enum.zip(stakers) |> 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) + # 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 = pool_staking_responses |> Enum.map(fn {_pool_staking_address, resp} -> @@ -111,9 +116,11 @@ defmodule Explorer.Staking.StakeSnapshotting do end) |> 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) + # 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 = staker_responses |> Enum.map(fn {{pool_staking_address, _staker_address}, resp} -> @@ -129,6 +136,7 @@ defmodule Explorer.Staking.StakeSnapshotting do end) |> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi) + # form entries for updating the `staking_pools` table in DB pool_entries = Enum.map(pool_staking_addresses, fn pool_staking_address -> staking_resp = pool_staking_responses[pool_staking_address] @@ -158,6 +166,7 @@ defmodule Explorer.Staking.StakeSnapshotting do ) end) + # form entries for updating the `staking_pools_delegators` table in DB delegator_entries = Enum.map(staker_responses, fn {{pool_staking_address, staker_address}, resp} -> delegator_reward_resp = delegator_reward_responses[{pool_staking_address, staker_address}] @@ -169,6 +178,7 @@ defmodule Explorer.Staking.StakeSnapshotting do }) end) + # perform SQL queries case Chain.import(%{ 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}, From 23ccf1d642d2e18eb2ac8213868f517affa5d4be Mon Sep 17 00:00:00 2001 From: Vadim Date: Mon, 2 Dec 2019 16:47:04 +0300 Subject: [PATCH 30/75] 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 ddafbcb1e2be..7886312aac5a 100644 --- a/apps/block_scout_web/assets/js/pages/address.js +++ b/apps/block_scout_web/assets/js/pages/address.js @@ -59,6 +59,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) { @@ -72,7 +80,7 @@ const elements = { render ($el, state, oldState) { if (oldState.balance === state.balance) return $el.empty().append(state.balanceCard) - loadTokenBalanceDropdown() + loadTokenBalance(state.fetchedCoinBalanceBlockNumber) updateAllCalculatedUsdValues() } }, @@ -127,6 +135,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 6f0dd3a195b2..f94b91c12aea 100644 --- a/apps/block_scout_web/lib/block_scout_web/notifier.ex +++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex @@ -28,6 +28,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 @@ -163,6 +168,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 79372575e5e9..ca10623ddb1d 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 c7e01eef3ae1..87026bfb913d 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 651491a308e8..33ee89a60096 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 49ddde374606..fc8ebdac7d5a 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"] From 697be30cb2510f5770ba1f06fe814a358f631eef Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 3 Dec 2019 12:16:28 +0300 Subject: [PATCH 31/75] Remove an excess code from snapshotting --- .../lib/explorer/staking/contract_state.ex | 2 -- .../explorer/staking/stake_snapshotting.ex | 32 ++++--------------- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index fc8ebdac7d5a..180c76fd4423 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -109,7 +109,6 @@ defmodule Explorer.Staking.ContractState do end def handle_continue(_, state) do - fetch_state(state.contracts, state.abi, state.seen_block) {:noreply, state} end @@ -394,7 +393,6 @@ defmodule Explorer.Staking.ContractState do %{contracts: contracts, abi: abi, ets_table_name: @table_name}, global_responses.epoch_number, pool_staking_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)), validators.pending, # mining addresses of pending validators mining_to_staking_address, diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 07c40cc525a5..8b0da7634c0c 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -15,7 +15,6 @@ defmodule Explorer.Staking.StakeSnapshotting do %{contracts: contracts, abi: abi, ets_table_name: ets_table_name}, epoch_number, cached_pool_staking_responses, - cached_pool_mining_responses, cached_staker_responses, pending_validators_mining_addresses, mining_to_staking_address, @@ -48,23 +47,6 @@ defmodule Explorer.Staking.StakeSnapshotting do |> Enum.zip(pool_staking_addresses) |> Map.new(fn {key, val} -> {val, key} end) - # read pool info from the contracts by its mining address. - # use `cached_pool_mining_responses` when possible - pool_mining_responses = - pool_staking_addresses - |> Enum.map(fn staking_address_hash -> - case Map.fetch(cached_pool_mining_responses, staking_address_hash) do - {:ok, resp} -> - resp - :error -> - pool_staking_responses[staking_address_hash].mining_address_hash - |> ContractReader.pool_mining_requests() - |> ContractReader.perform_requests(contracts, abi) - end - end) - |> Enum.zip(pool_staking_addresses) - |> Map.new(fn {key, val} -> {val, key} end) - # get a flat list of all stakers of each validator # in the form of {pool_staking_address, staker_address} stakers = @@ -140,7 +122,6 @@ defmodule Explorer.Staking.StakeSnapshotting do pool_entries = Enum.map(pool_staking_addresses, fn pool_staking_address -> staking_resp = pool_staking_responses[pool_staking_address] - mining_resp = pool_mining_responses[pool_staking_address] validator_reward_resp = validator_reward_responses[pool_staking_address] %{ @@ -157,13 +138,11 @@ defmodule Explorer.Staking.StakeSnapshotting do :total_staked_amount ]) ) - |> Map.merge( - Map.take(mining_resp, [ - :banned_until, - :was_banned_count, - :was_validator_count - ]) - ) + |> Map.merge(%{ + banned_until: 0, + was_banned_count: 0, + was_validator_count: 0 + }) end) # form entries for updating the `staking_pools_delegators` table in DB @@ -174,6 +153,7 @@ defmodule Explorer.Staking.StakeSnapshotting do Map.merge(resp, %{ address_hash: staker_address, staking_address_hash: pool_staking_address, + is_active: false, snapshotted_reward_ratio: Float.floor(delegator_reward_resp.delegator_share / 10_000, 2) }) end) From 94dbefee75ba9a0f3f58f55ad12395cf0cc13a1a Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 3 Dec 2019 13:28:16 +0300 Subject: [PATCH 32/75] Remove excess JSON RPCs from snapshotting --- .../lib/explorer/chain/staking_pool.ex | 2 +- .../lib/explorer/staking/contract_reader.ex | 8 +- .../lib/explorer/staking/contract_state.ex | 1 - .../explorer/staking/stake_snapshotting.ex | 78 +++++++++---------- 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/staking_pool.ex b/apps/explorer/lib/explorer/chain/staking_pool.ex index c7ee0ecaeb7c..af91c6c4d545 100644 --- a/apps/explorer/lib/explorer/chain/staking_pool.ex +++ b/apps/explorer/lib/explorer/chain/staking_pool.ex @@ -107,7 +107,7 @@ defmodule Explorer.Chain.StakingPool do defp validate_staked_amount(changeset) do if get_field(changeset, :total_staked_amount) < get_field(changeset, :self_staked_amount) do - add_error(changeset, :total_staked_amount, "must be greater than self_staked_amount") + add_error(changeset, :total_staked_amount, "must be greater or equal to self_staked_amount") else changeset end diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index f1ccb7724386..26a7302c4039 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -24,9 +24,15 @@ defmodule Explorer.Staking.ContractReader do ] end + def active_delegators_request(staking_address) do + [ + active_delegators: {:staking, "poolDelegators", [staking_address]} + ] + end + def pool_staking_requests(staking_address) do [ - active_delegators: {:staking, "poolDelegators", [staking_address]}, + active_delegators: active_delegators_request(staking_address)[:active_delegators], inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]}, is_active: {:staking, "isPoolActive", [staking_address]}, mining_address_hash: {:validator_set, "miningByStakingAddress", [staking_address]}, diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 180c76fd4423..80c5207a9b97 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -393,7 +393,6 @@ defmodule Explorer.Staking.ContractState do %{contracts: contracts, abi: abi, ets_table_name: @table_name}, global_responses.epoch_number, pool_staking_responses, - Map.new(Enum.map(staker_responses, fn {key, resp} -> {pool_staking_address, staker_address, _} = key; {{pool_staking_address, staker_address}, resp} end)), validators.pending, # mining addresses of pending validators mining_to_staking_address, block_number # the last block of the finished staking epoch diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 8b0da7634c0c..35dc4df81fc4 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -15,7 +15,6 @@ defmodule Explorer.Staking.StakeSnapshotting do %{contracts: contracts, abi: abi, ets_table_name: ets_table_name}, epoch_number, cached_pool_staking_responses, - cached_staker_responses, pending_validators_mining_addresses, mining_to_staking_address, block_number @@ -27,6 +26,11 @@ defmodule Explorer.Staking.StakeSnapshotting do pending_validators_mining_addresses |> Enum.map(&mining_to_staking_address[&1]) + staking_to_mining_address = + pool_staking_addresses + |> Enum.zip(pending_validators_mining_addresses) + |> Map.new() + # get snapshotted amounts and other pool info for each # pending validator by their staking address. # use `cached_pool_staking_responses` when possible @@ -38,7 +42,8 @@ defmodule Explorer.Staking.StakeSnapshotting do Map.merge(resp, ContractReader.perform_requests(snapshotted_pool_amounts_requests(staking_address_hash, block_number), contracts, abi)) :error -> ContractReader.perform_requests( - ContractReader.pool_staking_requests(staking_address_hash) ++ snapshotted_pool_amounts_requests(staking_address_hash, block_number), + ContractReader.active_delegators_request(staking_address_hash) ++ + snapshotted_pool_amounts_requests(staking_address_hash, block_number), contracts, abi ) @@ -55,28 +60,15 @@ defmodule Explorer.Staking.StakeSnapshotting do Enum.map(resp.active_delegators, &{pool_staking_address, &1}) end) - # read info of each staker from the contracts. - # use `cached_staker_responses` when possible + # read info of each staker from the contracts staker_responses = stakers - |> Enum.map(fn {pool_staking_address, staker_address} = key -> - case Map.fetch(cached_staker_responses, key) do - {:ok, resp} -> - Map.merge( - resp, - ContractReader.perform_requests( - snapshotted_staker_amount_request(pool_staking_address, staker_address, block_number), - contracts, - abi - ) - ) - :error -> - ContractReader.perform_requests( - ContractReader.staker_requests(pool_staking_address, staker_address) ++ snapshotted_staker_amount_request(pool_staking_address, staker_address, block_number), - contracts, - abi - ) - end + |> Enum.map(fn {pool_staking_address, staker_address} -> + ContractReader.perform_requests( + snapshotted_staker_amount_request(pool_staking_address, staker_address, block_number), + contracts, + abi + ) end) |> Enum.zip(stakers) |> Map.new(fn {key, val} -> {val, key} end) @@ -125,24 +117,22 @@ defmodule Explorer.Staking.StakeSnapshotting do validator_reward_resp = validator_reward_responses[pool_staking_address] %{ + banned_until: 0, + is_active: false, + is_banned: false, + is_unremovable: false, + is_validator: false, staking_address_hash: pool_staking_address, delegators_count: 0, - snapshotted_validator_reward_ratio: Float.floor(validator_reward_resp.validator_share / 10_000, 2) - } - |> Map.merge( - Map.take(staking_resp, [ - :mining_address_hash, - :self_staked_amount, - :snapshotted_self_staked_amount, - :snapshotted_total_staked_amount, - :total_staked_amount - ]) - ) - |> Map.merge(%{ - banned_until: 0, + mining_address_hash: address_bytes_to_string(staking_to_mining_address[pool_staking_address]), + self_staked_amount: 0, + snapshotted_self_staked_amount: staking_resp.snapshotted_self_staked_amount, + snapshotted_total_staked_amount: staking_resp.snapshotted_total_staked_amount, + snapshotted_validator_reward_ratio: Float.floor(validator_reward_resp.validator_share / 10_000, 2), + total_staked_amount: 0, was_banned_count: 0, was_validator_count: 0 - }) + } end) # form entries for updating the `staking_pools_delegators` table in DB @@ -150,12 +140,18 @@ defmodule Explorer.Staking.StakeSnapshotting do Enum.map(staker_responses, fn {{pool_staking_address, staker_address}, resp} -> delegator_reward_resp = delegator_reward_responses[{pool_staking_address, staker_address}] - Map.merge(resp, %{ + %{ address_hash: staker_address, - staking_address_hash: pool_staking_address, is_active: false, - snapshotted_reward_ratio: Float.floor(delegator_reward_resp.delegator_share / 10_000, 2) - }) + max_ordered_withdraw_allowed: 0, + max_withdraw_allowed: 0, + ordered_withdraw: 0, + ordered_withdraw_epoch: 0, + snapshotted_reward_ratio: Float.floor(delegator_reward_resp.delegator_share / 10_000, 2), + snapshotted_stake_amount: resp.snapshotted_stake_amount, + stake_amount: 0, + staking_address_hash: pool_staking_address + } end) # perform SQL queries @@ -169,6 +165,8 @@ defmodule Explorer.Staking.StakeSnapshotting do end end + defp address_bytes_to_string(hash), do: "0x" <> Base.encode16(hash, case: :lower) + defp snapshotted_pool_amounts_requests(pool_staking_address, block_number) do [ snapshotted_total_staked_amount: {:staking, "stakeAmountTotal", [pool_staking_address], block_number}, From fd6a237fee2f773272c7d6635d05d6fe0e3df9fd Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 3 Dec 2019 14:40:03 +0300 Subject: [PATCH 33/75] Explicit block number in snapshotting --- apps/explorer/lib/explorer/staking/contract_reader.ex | 8 ++++---- apps/explorer/lib/explorer/staking/contract_state.ex | 6 ++++-- apps/explorer/lib/explorer/staking/stake_snapshotting.ex | 8 ++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 26a7302c4039..6bbf44da9e92 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -24,15 +24,15 @@ defmodule Explorer.Staking.ContractReader do ] end - def active_delegators_request(staking_address) do + def active_delegators_request(staking_address, block_number) do [ - active_delegators: {:staking, "poolDelegators", [staking_address]} + active_delegators: {:staking, "poolDelegators", [staking_address], block_number} ] end - def pool_staking_requests(staking_address) do + def pool_staking_requests(staking_address, block_number) do [ - active_delegators: active_delegators_request(staking_address)[:active_delegators], + active_delegators: active_delegators_request(staking_address, block_number)[:active_delegators], inactive_delegators: {:staking, "poolDelegatorsInactive", [staking_address]}, is_active: {:staking, "isPoolActive", [staking_address]}, mining_address_hash: {:validator_set, "miningByStakingAddress", [staking_address]}, diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 80c5207a9b97..3bbe28b2ef37 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -199,7 +199,9 @@ defmodule Explorer.Staking.ContractState do # read pool info from the contracts by its staking address pool_staking_responses = pools - |> Enum.map(&ContractReader.pool_staking_requests/1) + |> Enum.map(fn staking_address_hash -> + ContractReader.pool_staking_requests(staking_address_hash, block_number) + end) |> ContractReader.perform_grouped_requests(pools, contracts, abi) # read pool info from the contracts by its mining address @@ -395,7 +397,7 @@ defmodule Explorer.Staking.ContractState do pool_staking_responses, validators.pending, # mining addresses of pending validators mining_to_staking_address, - block_number # the last block of the finished staking epoch + global_responses.epoch_start_block - 1 # the last block of the finished staking epoch ]) end diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 35dc4df81fc4..2bcce55c8846 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -31,7 +31,7 @@ defmodule Explorer.Staking.StakeSnapshotting do |> Enum.zip(pending_validators_mining_addresses) |> Map.new() - # get snapshotted amounts and other pool info for each + # get snapshotted amounts and active delegator list for the pool for each # pending validator by their staking address. # use `cached_pool_staking_responses` when possible pool_staking_responses = @@ -42,7 +42,7 @@ defmodule Explorer.Staking.StakeSnapshotting do Map.merge(resp, ContractReader.perform_requests(snapshotted_pool_amounts_requests(staking_address_hash, block_number), contracts, abi)) :error -> ContractReader.perform_requests( - ContractReader.active_delegators_request(staking_address_hash) ++ + ContractReader.active_delegators_request(staking_address_hash, block_number) ++ snapshotted_pool_amounts_requests(staking_address_hash, block_number), contracts, abi @@ -60,7 +60,7 @@ defmodule Explorer.Staking.StakeSnapshotting do Enum.map(resp.active_delegators, &{pool_staking_address, &1}) end) - # read info of each staker from the contracts + # read info about each staker from the contracts staker_responses = stakers |> Enum.map(fn {pool_staking_address, staker_address} -> @@ -161,7 +161,7 @@ defmodule Explorer.Staking.StakeSnapshotting do timeout: :infinity }) do {:ok, _} -> :ets.insert(ets_table_name, is_snapshotted: true) - _ -> Logger.error("Cannot finish snapshotting started at block #{block_number}") + _ -> Logger.error("Cannot successfully finish snapshotting for the epoch #{epoch_number - 1}") end end From 23e16bf5859cd50f1eb9b35fa7becfff2958d8ab Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 3 Dec 2019 17:17:52 +0300 Subject: [PATCH 34/75] Restore snapshots after restart --- .../lib/explorer/staking/contract_state.ex | 80 ++++++++++++------- .../explorer/staking/stake_snapshotting.ex | 12 +-- 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 3bbe28b2ef37..fa83a7f73155 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -21,9 +21,10 @@ defmodule Explorer.Staking.ContractState do :epoch_end_block, :epoch_number, :epoch_start_block, - :is_snapshotted, + :is_snapshotting, :min_candidate_stake, :min_delegator_stake, + :snapshotted_epoch_number, :staking_allowed, :staking_contract, :token_contract_address, @@ -98,7 +99,8 @@ defmodule Explorer.Staking.ContractState do :ets.insert(@table_name, block_reward_contract: %{abi: block_reward_abi, address: block_reward_contract_address}, - is_snapshotted: false, + is_snapshotting: false, + snapshotted_epoch_number: -1, staking_contract: %{abi: staking_abi, address: staking_contract_address}, token_contract_address: token_contract_address, token: token, @@ -132,8 +134,9 @@ defmodule Explorer.Staking.ContractState do ContractReader.validator_min_reward_percent_request(global_responses.epoch_number), contracts, abi ).value - epoch_finished = (global_responses.epoch_start_block == block_number + 1) + epoch_very_beginning = (global_responses.epoch_start_block == block_number + 1) is_validator = Enum.into(global_responses.validators, %{}, &{address_bytes_to_string(&1), true}) + start_snapshotting = (global_responses.epoch_number > get(:snapshotted_epoch_number) && global_responses.epoch_number > 0 && not get(:is_snapshotting)) # save the general info to ETS (excluding pool list and validator list) settings = @@ -163,21 +166,27 @@ defmodule Explorer.Staking.ContractState do :ets.insert(@table_name, settings) - # form the list of all pools - validators = if epoch_finished do - %{ - "getPendingValidators" => {:ok, [validators_pending]}, - "validatorsToBeFinalized" => {:ok, [validators_to_be_finalized]} - } = Reader.query_contract(contracts.validator_set, abi, %{ - "getPendingValidators" => [], - "validatorsToBeFinalized" => [] - }) - validators_pending = Enum.uniq(validators_pending ++ validators_to_be_finalized) - %{ - # get the list of all validators (the current and pending) - all: Enum.uniq(global_responses.validators ++ validators_pending), - pending: validators_pending - } + # form the list of validator pools + validators = if start_snapshotting do + if global_responses.validator_set_apply_block == 0 do + %{ + "getPendingValidators" => {:ok, [validators_pending]}, + "validatorsToBeFinalized" => {:ok, [validators_to_be_finalized]} + } = Reader.query_contract(contracts.validator_set, abi, %{ + "getPendingValidators" => [], + "validatorsToBeFinalized" => [] + }) + validators_pending = Enum.uniq(validators_pending ++ validators_to_be_finalized) + %{ + all: Enum.uniq(global_responses.validators ++ validators_pending), + for_snapshot: validators_pending + } + else + %{ + all: global_responses.validators, + for_snapshot: global_responses.validators + } + end else %{all: global_responses.validators} end @@ -273,7 +282,7 @@ defmodule Explorer.Staking.ContractState do |> Enum.zip(likelihood_values) |> Enum.into(%{}) - is_snapshotted = get(:is_snapshotted) + snapshotted_epoch_number = get(:snapshotted_epoch_number) # form entries for writing to the `staking_pools` table in DB pool_entries = @@ -285,7 +294,7 @@ defmodule Explorer.Staking.ContractState do delegators_count = length(staking_resp.active_delegators) + - if show_snapshotted_data(is_validator, global_responses.validator_set_apply_block, is_snapshotted) do + if show_snapshotted_data(is_validator, global_responses.validator_set_apply_block, snapshotted_epoch_number, global_responses.epoch_number) do Chain.staking_pool_snapshotted_inactive_delegators_count(pool_staking_address) else 0 @@ -347,7 +356,7 @@ defmodule Explorer.Staking.ContractState do timeout: :infinity }) - if epoch_finished do + if epoch_very_beginning or start_snapshotting do # update ERC balance of the BlockReward contract token = get(:token) if token != nil do @@ -389,15 +398,23 @@ defmodule Explorer.Staking.ContractState do :on_demand ) end + end + if start_snapshotting do # start snapshotting at the beginning of the staking epoch + cached_pool_staking_responses = if epoch_very_beginning do + pool_staking_responses + else + %{} + end + spawn(StakeSnapshotting, :do_snapshotting, [ %{contracts: contracts, abi: abi, ets_table_name: @table_name}, global_responses.epoch_number, - pool_staking_responses, - validators.pending, # mining addresses of pending validators + cached_pool_staking_responses, + validators.for_snapshot, # mining addresses of pending/current validators mining_to_staking_address, - global_responses.epoch_start_block - 1 # the last block of the finished staking epoch + global_responses.epoch_start_block - 1 # the last block of the previous staking epoch ]) end @@ -405,18 +422,23 @@ defmodule Explorer.Staking.ContractState do Publisher.broadcast(:staking_update) end - def show_snapshotted_data(is_validator, validator_set_apply_block \\ nil, is_snapshotted \\ nil) do + def show_snapshotted_data(is_validator, validator_set_apply_block \\ nil, snapshotted_epoch_number \\ nil, epoch_number \\ nil) do validator_set_apply_block = if validator_set_apply_block !== nil do validator_set_apply_block else get(:validator_set_apply_block) end - is_snapshotted = if is_snapshotted !== nil do - is_snapshotted + snapshotted_epoch_number = if snapshotted_epoch_number !== nil do + snapshotted_epoch_number + else + get(:snapshotted_epoch_number) + end + epoch_number = if epoch_number !== nil do + epoch_number else - get(:is_snapshotted) + get(:epoch_number) end - is_validator && validator_set_apply_block > 0 && is_snapshotted + is_validator && validator_set_apply_block > 0 && snapshotted_epoch_number === epoch_number end defp get_token(address) do diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 2bcce55c8846..e3f480db8ec9 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -15,20 +15,20 @@ defmodule Explorer.Staking.StakeSnapshotting do %{contracts: contracts, abi: abi, ets_table_name: ets_table_name}, epoch_number, cached_pool_staking_responses, - pending_validators_mining_addresses, + pools_mining_addresses, mining_to_staking_address, block_number ) do - :ets.insert(ets_table_name, is_snapshotted: false) + :ets.insert(ets_table_name, is_snapshotting: true) # get staking addresses for the pending validators pool_staking_addresses = - pending_validators_mining_addresses + pools_mining_addresses |> Enum.map(&mining_to_staking_address[&1]) staking_to_mining_address = pool_staking_addresses - |> Enum.zip(pending_validators_mining_addresses) + |> Enum.zip(pools_mining_addresses) |> Map.new() # get snapshotted amounts and active delegator list for the pool for each @@ -160,9 +160,11 @@ defmodule Explorer.Staking.StakeSnapshotting do staking_pools_delegators: %{params: delegator_entries, on_conflict: staking_pools_delegators_update(), clear_snapshotted_values: true}, timeout: :infinity }) do - {:ok, _} -> :ets.insert(ets_table_name, is_snapshotted: true) + {:ok, _} -> :ets.insert(ets_table_name, snapshotted_epoch_number: epoch_number) _ -> Logger.error("Cannot successfully finish snapshotting for the epoch #{epoch_number - 1}") end + + :ets.insert(ets_table_name, is_snapshotting: false) end defp address_bytes_to_string(hash), do: "0x" <> Base.encode16(hash, case: :lower) From d6afcb343d9414803f506d6d31f484002926f005 Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 5 Dec 2019 12:16:23 +0300 Subject: [PATCH 35/75] Enhance ContractState.get_token function --- .../lib/explorer/staking/contract_state.ex | 50 ++++++++++++++++--- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index fa83a7f73155..e60e5f498462 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -95,15 +95,13 @@ defmodule Explorer.Staking.ContractState do abi: staking_abi ++ validator_set_abi ++ block_reward_abi } - token = get_token(token_contract_address) - :ets.insert(@table_name, block_reward_contract: %{abi: block_reward_abi, address: block_reward_contract_address}, is_snapshotting: false, snapshotted_epoch_number: -1, staking_contract: %{abi: staking_abi, address: staking_contract_address}, token_contract_address: token_contract_address, - token: token, + token: get_token(token_contract_address), validator_set_contract: %{abi: validator_set_abi, address: validator_set_contract_address} ) @@ -442,11 +440,49 @@ defmodule Explorer.Staking.ContractState do end defp get_token(address) do - with {:ok, address_hash} <- Chain.string_to_address_hash(address), - {:ok, token} <- Chain.token_from_address_hash(address_hash) do - token + if address == "0x0000000000000000000000000000000000000000" do + nil # the token address is empty, so return nil else - _ -> nil + with {:ok, address_hash} <- Chain.string_to_address_hash(address) do + # the token address has correct format, so try to read the token + # from DB or from its contract + case Chain.token_from_address_hash(address_hash) do + {:ok, token} -> + token # the token is read from DB + _ -> + # the token doesn't exist in DB, so try + # to read it from a contract and then write to DB + token_functions = MetadataRetriever.get_functions_of(address) + + if map_size(token_functions) > 0 do + # the token is successfully read from its contract + token_params = Map.merge(token_functions, %{ + contract_address_hash: address, + type: "ERC-20" + }) + + # try to write the token info to DB + import_result = Chain.import(%{ + addresses: %{params: [%{hash: address}], on_conflict: :nothing}, + tokens: %{params: [token_params]} + }) + + with {:ok, _} <- import_result do + # the token is successfully added to DB, so return it as a result + case Chain.token_from_address_hash(address_hash) do + {:ok, token} -> token + _ -> nil + end + else + _ -> nil # cannot write the token info to DB + end + else + nil # cannot read the token info from its contract + end + end + else + _ -> nil # the token address has incorrect format + end end end From 5a0bcdf0e362074230e4ba99d64513926115c77e Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 5 Dec 2019 14:42:43 +0300 Subject: [PATCH 36/75] Add comments for stakes controller --- .../lib/block_scout_web/controllers/stakes_controller.ex | 7 +++++++ 1 file changed, 7 insertions(+) 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 6ca15827e96a..db018663d743 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 @@ -15,6 +15,9 @@ defmodule BlockScoutWeb.StakesController do render_template(assigns.filter, conn, params) end + # this is called when account in MetaMask is changed on client side (see `staking_update` event handled in `StakesChannel`), + # when a new block appears (see `staking_update` event handled in `StakesChannel`), + # or when the page is loaded for the first time or reloaded by a user (i.e. it is called by the `render_template(filter, conn, _)`) def render_top(conn) do epoch_number = ContractState.get(:epoch_number, 0) epoch_end_block = ContractState.get(:epoch_end_block, 0) @@ -43,6 +46,8 @@ defmodule BlockScoutWeb.StakesController do ) end + # this is called when account in MetaMask is changed on client side + # or when UI periodically reloads the pool list (e.g. once per 10 blocks) defp render_template(filter, conn, %{"type" => "JSON"} = params) do [paging_options: options] = paging_options(params) @@ -114,6 +119,8 @@ defmodule BlockScoutWeb.StakesController do ) end + # this is called when the page is loaded for the first time + # or when it is reloaded by a user defp render_template(filter, conn, _) do render(conn, "index.html", top: render_top(conn), From bbcc42ffc99c2ee4e0451717c8912829b8ffef76 Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 5 Dec 2019 17:13:30 +0300 Subject: [PATCH 37/75] Improve autorefreshing of Validators tab --- .../block_scout_web/assets/js/pages/stakes.js | 26 +++++++++++-------- .../channels/stakes_channel.ex | 6 +++-- .../lib/block_scout_web/notifier.ex | 13 +++------- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index f31ef1c2d196..ef0b8fdf9612 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -17,18 +17,19 @@ import { openClaimWithdrawalModal } from './stakes/claim_withdrawal' import { openWarningModal } from '../lib/modals' export const initialState = { - channel: null, - web3: null, account: null, + blockRewardContract: null, + channel: null, + lastBlockNumber: 0, + lastEpochNumber: 0, network: null, + refreshInterval: null, + stakingAllowed: false, stakingContract: null, - blockRewardContract: null, tokenDecimals: 0, tokenSymbol: '', - refreshInterval: null, - lastEpochNumber: 0, - lastBlockNumber: 0, - stakingAllowed: false + validatorSetApplyBlock: 0, + web3: null } // 100 - id of xDai network, 101 - id of xDai test network @@ -72,9 +73,10 @@ export function reducer (state = initialState, action) { } case 'RECEIVED_UPDATE': { return Object.assign({}, state, { - lastEpochNumber: action.lastEpochNumber, lastBlockNumber: action.lastBlockNumber, - stakingAllowed: action.stakingAllowed + lastEpochNumber: action.lastEpochNumber, + stakingAllowed: action.stakingAllowed, + validatorSetApplyBlock: action.validatorSetApplyBlock }) } case 'RECEIVED_CONTRACTS': { @@ -130,13 +132,15 @@ if ($stakesPage.length) { if ( msg.staking_allowed !== state.stakingAllowed || msg.epoch_number > state.lastEpochNumber || + msg.validator_set_apply_block != state.validatorSetApplyBlock || (state.refreshInterval && msg.block_number >= state.lastBlockNumber + state.refreshInterval) ) { store.dispatch({ type: 'RECEIVED_UPDATE', - lastEpochNumber: msg.epoch_number, lastBlockNumber: msg.block_number, - stakingAllowed: msg.staking_allowed + lastEpochNumber: msg.epoch_number, + stakingAllowed: msg.staking_allowed, + validatorSetApplyBlock: msg.validator_set_apply_block }) refreshPage(store) } 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 778a7f3356f8..9f66194ba018 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 @@ -27,8 +27,9 @@ defmodule BlockScoutWeb.StakesChannel do "staking_update", %{ block_number: BlockNumber.get_max(), + epoch_number: ContractState.get(:epoch_number, 0), staking_allowed: ContractState.get(:staking_allowed, false), - epoch_number: ContractState.get(:epoch_number, 0) + validator_set_apply_block: ContractState.get(:validator_set_apply_block, 0) }, socket ) @@ -251,9 +252,10 @@ defmodule BlockScoutWeb.StakesChannel do def handle_out("staking_update", data, socket) do push(socket, "staking_update", %{ - epoch_number: data.epoch_number, block_number: data.block_number, + epoch_number: data.epoch_number, staking_allowed: data.staking_allowed, + validator_set_apply_block: data.validator_set_apply_block, top_html: StakesController.render_top(socket) }) 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 f94b91c12aea..60d3ffc91a7f 100644 --- a/apps/block_scout_web/lib/block_scout_web/notifier.ex +++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex @@ -100,16 +100,11 @@ defmodule BlockScoutWeb.Notifier do end def handle_event({:chain_event, :staking_update}) do - epoch_number = ContractState.get(:epoch_number, 0) - epoch_end_block = ContractState.get(:epoch_end_block, 0) - staking_allowed = ContractState.get(:staking_allowed, false) - block_number = BlockNumber.get_max() - Endpoint.broadcast("stakes:staking_update", "staking_update", %{ - epoch_number: epoch_number, - epoch_end_block: epoch_end_block, - staking_allowed: staking_allowed, - block_number: block_number + block_number: BlockNumber.get_max(), + epoch_number: ContractState.get(:epoch_number, 0), + staking_allowed: ContractState.get(:staking_allowed, false), + validator_set_apply_block: ContractState.get(:validator_set_apply_block, 0) }) end From 5390ba1944501f61b7599cf80abd1f86966e2886 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 6 Dec 2019 12:46:23 +0300 Subject: [PATCH 38/75] Improve the displaying of Stakes Ratio --- .../lib/block_scout_web/templates/stakes/_rows.html.eex | 2 +- .../templates/stakes/_stakes_modal_pool_info.html.eex | 2 +- ...info_item.html.eex => _stakes_pool_info_item.html.eex} | 0 .../templates/stakes/_stakes_progress.html.eex | 2 +- apps/block_scout_web/priv/gettext/default.pot | 6 ++++++ .../priv/gettext/en/LC_MESSAGES/default.po | 8 +++++++- apps/explorer/lib/explorer/chain.ex | 2 +- apps/explorer/lib/explorer/staking/contract_state.ex | 2 ++ 8 files changed, 19 insertions(+), 5 deletions(-) rename apps/block_scout_web/lib/block_scout_web/templates/stakes/{_stakes_validator_info_item.html.eex => _stakes_pool_info_item.html.eex} (100%) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex index 2aa0b50325c1..201c011cca61 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows.html.eex @@ -23,7 +23,7 @@ <%= if @pools_type == :inactive do %> <%= if @pool.is_banned, do: gettext("Yes"), else: gettext("No") %> <% else %> - <%= if @pool.stakes_ratio, do: "#{@pool.stakes_ratio}%" %> + <%= if @pool.is_active, do: "#{@pool.stakes_ratio}%", else: gettext("(inactive pool)") %> <% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex index 674a443ee661..828154550ab5 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex @@ -41,7 +41,7 @@ render BlockScoutWeb.StakesView, "_stakes_validator_info_item.html", title: gettext("Stakes Ratio"), - value: if(@validator.stakes_ratio, do: "#{@validator.stakes_ratio}%") + value: if(@validator.is_active, do: "#{@validator.stakes_ratio}%") %> <%= render BlockScoutWeb.StakesView, diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_validator_info_item.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_pool_info_item.html.eex similarity index 100% rename from apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_validator_info_item.html.eex rename to apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_pool_info_item.html.eex diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex index e4a48a7d6cbc..b63194b4180d 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_progress.html.eex @@ -24,7 +24,7 @@

<%= gettext("Stakes Ratio") %>

- <%= @pool.stakes_ratio %>% + <%= if @pool.is_active, do: "#{@pool.stakes_ratio}%", else: gettext("(inactive pool)") %>

diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index dff65478da6f..9eb2cec9516c 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2314,3 +2314,9 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 msgid "Reward distribution is based on stake amount. Validator receives a minimum of %{min}%." msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_rows.html.eex:26 +#: lib/block_scout_web/templates/stakes/_stakes_progress.html.eex:27 +msgid "(inactive pool)" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index f145192ae491..9eb2cec9516c 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2309,8 +2309,14 @@ msgstr "" msgid "All pool participant addresses. The top address belongs to the %{pool_type}." msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:53 msgid "Reward distribution is based on stake amount. Validator receives a minimum of %{min}%." msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_rows.html.eex:26 +#: lib/block_scout_web/templates/stakes/_stakes_progress.html.eex:27 +msgid "(inactive pool)" +msgstr "" diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index f4555fefec9a..dd166eff638b 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -3600,7 +3600,7 @@ defmodule Explorer.Chain do paging_query = base_query |> limit(^paging_options.page_size) - |> order_by(desc: :stakes_ratio, asc: :staking_address_hash) + |> order_by(desc: :stakes_ratio, desc: :is_active) case paging_options.key do {value, address_hash} -> diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index e60e5f498462..4b858be75290 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -304,6 +304,8 @@ defmodule Explorer.Staking.ContractState do stakes_ratio: if staking_resp.is_active do ratio(staking_resp.total_staked_amount, staked_total) + else + 0 end, validator_reward_ratio: Float.floor(candidate_reward_resp.validator_share / 10_000, 2), likelihood: ratio(likelihood[pool_staking_address] || 0, total_likelihood), From f37728dbc7da0279d17257044a1ea2417f63ab10 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 6 Dec 2019 15:58:29 +0300 Subject: [PATCH 39/75] Add pool list autorefresh informer --- .../assets/css/components/_stakes_table.scss | 7 +++ .../block_scout_web/assets/js/pages/stakes.js | 50 +++++++++++++++---- apps/block_scout_web/config/config.exs | 2 +- .../controllers/stakes_controller.ex | 2 +- .../templates/stakes/_table.html.eex | 2 + apps/block_scout_web/priv/gettext/default.pot | 10 ++++ .../priv/gettext/en/LC_MESSAGES/default.po | 10 ++++ 7 files changed, 72 insertions(+), 11 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/_stakes_table.scss b/apps/block_scout_web/assets/css/components/_stakes_table.scss index ded5ae30f0a3..a39da533e5fd 100644 --- a/apps/block_scout_web/assets/css/components/_stakes_table.scss +++ b/apps/block_scout_web/assets/css/components/_stakes_table.scss @@ -86,6 +86,13 @@ $stakes-link-color: $primary !default; padding: 0 15px; min-width: 930px; min-height: 311px; + + .refresh-informer { + text-align: right; + padding-top: 15px; + padding-right: 15px; + display: none; + } } .stakes-table-th { diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index ef0b8fdf9612..5e277bce8f86 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -16,6 +16,8 @@ import { openWithdrawStakeModal } from './stakes/withdraw_stake' import { openClaimWithdrawalModal } from './stakes/claim_withdrawal' import { openWarningModal } from '../lib/modals' +const stakesPageSelector = '[data-page="stakes"]' + export const initialState = { account: null, blockRewardContract: null, @@ -87,11 +89,26 @@ export function reducer (state = initialState, action) { tokenSymbol: action.tokenSymbol }) } + case 'FINISH_REQUEST': { + $(stakesPageSelector).fadeTo(0, 1) + return state + } default: return state } } +function reloadPoolList(msg, store) { + store.dispatch({ + type: 'RECEIVED_UPDATE', + lastBlockNumber: msg.block_number, + lastEpochNumber: msg.epoch_number, + stakingAllowed: msg.staking_allowed, + validatorSetApplyBlock: msg.validator_set_apply_block + }) + refreshPage(store) +} + const elements = { '[data-page="stakes"]': { load ($el) { @@ -106,7 +123,7 @@ const elements = { } } -const $stakesPage = $('[data-page="stakes"]') +const $stakesPage = $(stakesPageSelector) const $stakesTop = $('[data-selector="stakes-top"]') if ($stakesPage.length) { const store = createAsyncLoadStore(reducer, initialState, 'dataset.identifierPool') @@ -115,6 +132,8 @@ if ($stakesPage.length) { const channel = subscribeChannel('stakes:staking_update') store.dispatch({ type: 'CHANNEL_CONNECTED', channel }) + const $refreshInformer = $('.refresh-informer', $stakesPage) + channel.on('staking_update', msg => { // hide tooltip on tooltip triggering element reloading // due to issues with bootstrap tooltips https://github.com/twbs/bootstrap/issues/13133 @@ -129,21 +148,34 @@ if ($stakesPage.length) { $stakesPage.find('[pool-filter-my]').prop('checked', false); } + let lastBlockNumber = state.lastBlockNumber + if ( msg.staking_allowed !== state.stakingAllowed || msg.epoch_number > state.lastEpochNumber || msg.validator_set_apply_block != state.validatorSetApplyBlock || (state.refreshInterval && msg.block_number >= state.lastBlockNumber + state.refreshInterval) ) { - store.dispatch({ - type: 'RECEIVED_UPDATE', - lastBlockNumber: msg.block_number, - lastEpochNumber: msg.epoch_number, - stakingAllowed: msg.staking_allowed, - validatorSetApplyBlock: msg.validator_set_apply_block - }) - refreshPage(store) + reloadPoolList(msg, store) + lastBlockNumber = msg.block_number } + + const refreshGap = msg.block_number - lastBlockNumber + $refreshInformer.find('span').html(refreshGap) + if (refreshGap > 0) { + $refreshInformer.show() + } else { + $refreshInformer.hide() + } + + const $refreshInformerLink = $refreshInformer.find('a') + $refreshInformerLink.off('click') + $refreshInformerLink.on('click', (event) => { + event.preventDefault() + $refreshInformer.hide() + $stakesPage.fadeTo(0, 0.5) + reloadPoolList(msg, store) + }) }) channel.on('contracts', msg => { diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs index aca84ae52bd4..6598c4e25774 100644 --- a/apps/block_scout_web/config/config.exs +++ b/apps/block_scout_web/config/config.exs @@ -21,7 +21,7 @@ config :block_scout_web, BlockScoutWeb.Chain, logo_footer: System.get_env("LOGO_FOOTER"), has_emission_funds: false, staking_enabled: not is_nil(System.get_env("POS_STAKING_CONTRACT")), - staking_table_refresh_interval: 10 + staking_pool_list_refresh_interval: 5 # how often (in blocks) the list of pools should autorefresh in UI (zero turns off autorefreshing) 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/controllers/stakes_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex index db018663d743..59131fec9f01 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 @@ -127,7 +127,7 @@ defmodule BlockScoutWeb.StakesController do pools_type: filter, current_path: current_path(conn), average_block_time: AverageBlockTime.average_block_time(), - refresh_interval: Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:staking_table_refresh_interval] + refresh_interval: Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:staking_pool_list_refresh_interval] ) end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_table.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_table.html.eex index 7149d8c84210..82bb92882a3f 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_table.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_table.html.eex @@ -29,5 +29,7 @@
+ +
<%= raw gettext("The table refreshed block(s) ago.") %> <%= gettext("Refresh now") %>
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 9eb2cec9516c..6bb983e3b513 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2320,3 +2320,13 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_progress.html.eex:27 msgid "(inactive pool)" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_table.html.eex:33 +msgid "Refresh now" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_table.html.eex:33 +msgid "The table refreshed block(s) ago." +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 9eb2cec9516c..6bb983e3b513 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2320,3 +2320,13 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_progress.html.eex:27 msgid "(inactive pool)" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_table.html.eex:33 +msgid "Refresh now" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_table.html.eex:33 +msgid "The table refreshed block(s) ago." +msgstr "" From 0c34010169ce7e0d6d5796639da32d2e442e4159 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 6 Dec 2019 17:12:40 +0300 Subject: [PATCH 40/75] Add check for staking token definition --- .../block_scout_web/assets/js/pages/stakes.js | 50 +++++++++++++++---- .../assets/js/pages/stakes/utils.js | 16 ++++-- .../assets/js/pages/stakes/validator_info.js | 2 +- .../channels/stakes_channel.ex | 2 + .../lib/block_scout_web/notifier.ex | 1 + .../templates/stakes/_stakes_address.html.eex | 2 +- .../stakes/_stakes_modal_pool_info.html.eex | 16 +++--- .../stakes/_stakes_progress.html.eex | 2 +- 8 files changed, 66 insertions(+), 25 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index 5e277bce8f86..54ae816f9997 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -6,7 +6,7 @@ import { subscribeChannel } from '../socket' import { connectElements } from '../lib/redux_helpers.js' import { createAsyncLoadStore, refreshPage } from '../lib/async_listing_load' import Web3 from 'web3' -import { openValidatorInfoModal } from './stakes/validator_info' +import { openPoolInfoModal } from './stakes/validator_info' import { openDelegatorsListModal } from './stakes/delegators_list' import { openBecomeCandidateModal } from './stakes/become_candidate' import { openRemovePoolModal } from './stakes/remove_pool' @@ -14,6 +14,7 @@ import { openMakeStakeModal } from './stakes/make_stake' import { openMoveStakeModal } from './stakes/move_stake' import { openWithdrawStakeModal } from './stakes/withdraw_stake' import { openClaimWithdrawalModal } from './stakes/claim_withdrawal' +import { checkForTokenDefinition } from './stakes/utils' import { openWarningModal } from '../lib/modals' const stakesPageSelector = '[data-page="stakes"]' @@ -27,6 +28,7 @@ export const initialState = { network: null, refreshInterval: null, stakingAllowed: false, + stakingTokenDefined: false, stakingContract: null, tokenDecimals: 0, tokenSymbol: '', @@ -78,6 +80,7 @@ export function reducer (state = initialState, action) { lastBlockNumber: action.lastBlockNumber, lastEpochNumber: action.lastEpochNumber, stakingAllowed: action.stakingAllowed, + stakingTokenDefined: action.stakingTokenDefined, validatorSetApplyBlock: action.validatorSetApplyBlock }) } @@ -104,6 +107,7 @@ function reloadPoolList(msg, store) { lastBlockNumber: msg.block_number, lastEpochNumber: msg.epoch_number, stakingAllowed: msg.staking_allowed, + stakingTokenDefined: msg.staking_token_defined, validatorSetApplyBlock: msg.validator_set_apply_block }) refreshPage(store) @@ -195,14 +199,42 @@ if ($stakesPage.length) { }) $(document.body) - .on('click', '.js-validator-info', event => openValidatorInfoModal(event, store)) - .on('click', '.js-delegators-list', event => openDelegatorsListModal(event, store)) - .on('click', '.js-become-candidate', () => openBecomeCandidateModal(store)) - .on('click', '.js-remove-pool', () => openRemovePoolModal(store)) - .on('click', '.js-make-stake', event => openMakeStakeModal(event, store)) - .on('click', '.js-move-stake', event => openMoveStakeModal(event, store)) - .on('click', '.js-withdraw-stake', event => openWithdrawStakeModal(event, store)) - .on('click', '.js-claim-withdrawal', event => openClaimWithdrawalModal(event, store)) + .on('click', '.js-pool-info', event => { + if (checkForTokenDefinition(store)) { + openPoolInfoModal(event, store) + } + }) + .on('click', '.js-delegators-list', event => { + openDelegatorsListModal(event, store) + }) + .on('click', '.js-become-candidate', () => { + if (checkForTokenDefinition(store)) { + openBecomeCandidateModal(store) + } + }) + .on('click', '.js-remove-pool', () => { + openRemovePoolModal(store) + }) + .on('click', '.js-make-stake', event => { + if (checkForTokenDefinition(store)) { + openMakeStakeModal(event, store) + } + }) + .on('click', '.js-move-stake', event => { + if (checkForTokenDefinition(store)) { + openMoveStakeModal(event, store) + } + }) + .on('click', '.js-withdraw-stake', event => { + if (checkForTokenDefinition(store)) { + openWithdrawStakeModal(event, store) + } + }) + .on('click', '.js-claim-withdrawal', event => { + if (checkForTokenDefinition(store)) { + openClaimWithdrawalModal(event, store) + } + }) $stakesPage .on('change', '[pool-filter-banned]', () => updateFilters(store, 'banned')) diff --git a/apps/block_scout_web/assets/js/pages/stakes/utils.js b/apps/block_scout_web/assets/js/pages/stakes/utils.js index fe8e54349317..2d1a97dbbe5e 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/utils.js +++ b/apps/block_scout_web/assets/js/pages/stakes/utils.js @@ -3,7 +3,7 @@ import Chart from 'chart.js' import { refreshPage } from '../../lib/async_listing_load' import { openErrorModal, openSuccessModal, openWarningModal } from '../../lib/modals' -export async function makeContractCall (call, store) { +export async function makeContractCall(call, store) { let gas, timeout let resultShown = false const account = store.getState().account @@ -52,7 +52,7 @@ export async function makeContractCall (call, store) { } } -export function setupChart ($canvas, self, total) { +export function setupChart($canvas, self, total) { const primaryColor = $('.stakes-progress-graph-thing-for-getting-color').css('color') const backgroundColors = [ primaryColor, @@ -83,12 +83,18 @@ export function setupChart ($canvas, self, total) { }) } -export function isSupportedNetwork (store) { - if (store.getState().network.authorized) { +export function checkForTokenDefinition(store) { + if (store.getState().stakingTokenDefined) { return true } + openWarningModal('Token unavailable', 'Token contract is not defined yet. Please try later.') + return false +} +export function isSupportedNetwork(store) { + if (store.getState().network.authorized) { + return true + } openWarningModal('Unauthorized', 'Connect to the xDai Chain for staking.
Instructions') - return false } diff --git a/apps/block_scout_web/assets/js/pages/stakes/validator_info.js b/apps/block_scout_web/assets/js/pages/stakes/validator_info.js index 6a8942cb80f5..9fb035b9aaf5 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/validator_info.js +++ b/apps/block_scout_web/assets/js/pages/stakes/validator_info.js @@ -1,7 +1,7 @@ import $ from 'jquery' import { openModal } from '../../lib/modals' -export function openValidatorInfoModal (event, store) { +export function openPoolInfoModal (event, store) { const address = $(event.target).closest('[data-address]').data('address') store.getState().channel 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 9f66194ba018..f1d6989d2692 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 @@ -29,6 +29,7 @@ defmodule BlockScoutWeb.StakesChannel do block_number: BlockNumber.get_max(), epoch_number: ContractState.get(:epoch_number, 0), staking_allowed: ContractState.get(:staking_allowed, false), + staking_token_defined: ContractState.get(:token, nil) != nil, validator_set_apply_block: ContractState.get(:validator_set_apply_block, 0) }, socket @@ -255,6 +256,7 @@ defmodule BlockScoutWeb.StakesChannel do block_number: data.block_number, epoch_number: data.epoch_number, staking_allowed: data.staking_allowed, + staking_token_defined: data.staking_token_defined, validator_set_apply_block: data.validator_set_apply_block, top_html: StakesController.render_top(socket) }) 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 60d3ffc91a7f..c33d0b9979d3 100644 --- a/apps/block_scout_web/lib/block_scout_web/notifier.ex +++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex @@ -104,6 +104,7 @@ defmodule BlockScoutWeb.Notifier do block_number: BlockNumber.get_max(), epoch_number: ContractState.get(:epoch_number, 0), staking_allowed: ContractState.get(:staking_allowed, false), + staking_token_defined: ContractState.get(:token, nil) != nil, validator_set_apply_block: ContractState.get(:validator_set_apply_block, 0) }) end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_address.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_address.html.eex index e46c445d84b8..bec16ba6fcb0 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_address.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_address.html.eex @@ -1,4 +1,4 @@ -
+
<%= BlockScoutWeb.AddressView.trimmed_hash(@address) %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex index 828154550ab5..44c67adb0558 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex @@ -27,49 +27,49 @@
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 6bb983e3b513..ecc253854606 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2330,3 +2330,30 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_table.html.eex:33 msgid "The table refreshed block(s) ago." msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 +#: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 +msgid "Claim Reward" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9 +msgid "Searching for pools you ever staked into. Please, wait..." +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:247 +msgid "

Unable to find the pools in a reasonable time. Please, contact Support.

" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:244 +msgid "

Unknown error. Please, contact Support.

" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:4 +msgid "Unable to find any pools you staked into." +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 6bb983e3b513..ecc253854606 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2330,3 +2330,30 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_table.html.eex:33 msgid "The table refreshed block(s) ago." msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 +#: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 +msgid "Claim Reward" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9 +msgid "Searching for pools you ever staked into. Please, wait..." +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:247 +msgid "

Unable to find the pools in a reasonable time. Please, contact Support.

" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:244 +msgid "

Unknown error. Please, contact Support.

" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:4 +msgid "Unable to find any pools you staked into." +msgstr "" From 6261dbdeb98f4bd243a826b69eb6eecdf3c91e9b Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 10 Dec 2019 16:28:48 +0300 Subject: [PATCH 42/75] Simplify render_claim_reward handling; remove UI freeze --- .../assets/js/pages/stakes/claim_reward.js | 18 +++++++++------- .../channels/stakes_channel.ex | 21 +++++++------------ .../_stakes_modal_claim_reward.html.eex | 2 +- apps/block_scout_web/priv/gettext/default.pot | 20 +++++------------- .../priv/gettext/en/LC_MESSAGES/default.po | 20 +++++------------- 5 files changed, 29 insertions(+), 52 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 1b776b4269cf..46013d4dd0c5 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -33,14 +33,18 @@ export function openClaimRewardModal(store) { closeButton.hide() lockModal($modal) + channel.on('claim_reward_pools', msg_pools => { + channel.off('claim_reward_pools') + closeButton.show() + unlockModal($modal) + clearInterval(dotCounterInterval) + modalBody.html(msg_pools.html) + }) $modal.on('shown.bs.modal', () => { - const timeout = 15000; // ms - channel.push('render_claim_reward', { timeout: timeout }, timeout * 2).receive('ok', msg_pools => { - closeButton.show() - unlockModal($modal) - clearInterval(dotCounterInterval) - modalBody.html(msg_pools.html) - }) + channel.push('render_claim_reward', {}) + }) + $modal.on('hidden.bs.modal', () => { + $(this).remove() }) openModal($modal); 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 2975bfb540d6..b9e15950dd5e 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 @@ -11,8 +11,6 @@ defmodule BlockScoutWeb.StakesChannel do alias Explorer.Staking.ContractState alias Phoenix.View - import BlockScoutWeb.Gettext - intercept(["staking_update"]) def join("stakes:staking_update", _params, socket) do @@ -236,16 +234,8 @@ defmodule BlockScoutWeb.StakesChannel do html = if data["preload"] do View.render_to_string(StakesView, "_stakes_modal_claim_reward.html", %{}) else - task = Task.async(__MODULE__, :find_claim_reward_pools, []) - case Task.yield(task, data["timeout"]) do - {:ok, html} -> - html - {:exit, _} -> - gettext("

Unknown error. Please, contact Support.

") - nil -> - Task.shutdown(task, :brutal_kill) - gettext("

Unable to find the pools in a reasonable time. Please, contact Support.

") - end + Task.async(__MODULE__, :find_claim_reward_pools, [socket]) + "OK" end result = %{html: html} {:reply, {:ok, result}, socket} @@ -285,10 +275,13 @@ defmodule BlockScoutWeb.StakesChannel do {:noreply, socket} end - def find_claim_reward_pools() do + def find_claim_reward_pools(socket) do pools = [] :timer.sleep(20000) # emulate working - View.render_to_string(StakesView, "_stakes_modal_claim_reward_content.html", pools: pools) + html = View.render_to_string(StakesView, "_stakes_modal_claim_reward_content.html", pools: pools) + push(socket, "claim_reward_pools", %{ + html: html + }) end defp push_staking_contract(socket) do diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex index b7523ead1fa7..96b80f101720 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex @@ -6,7 +6,7 @@
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index ecc253854606..c91d4452ee85 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2337,23 +2337,13 @@ msgstr "" msgid "Claim Reward" msgstr "" -#, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9 -msgid "Searching for pools you ever staked into. Please, wait..." -msgstr "" - -#, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:247 -msgid "

Unable to find the pools in a reasonable time. Please, contact Support.

" -msgstr "" - -#, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:244 -msgid "

Unknown error. Please, contact Support.

" -msgstr "" - #, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:4 msgid "Unable to find any pools you staked into." msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9 +msgid "Searching for pools you have ever staked into. Please, wait..." +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index ecc253854606..3b9f29a387f6 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2337,23 +2337,13 @@ msgstr "" msgid "Claim Reward" msgstr "" -#, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9 -msgid "Searching for pools you ever staked into. Please, wait..." -msgstr "" - -#, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:247 -msgid "

Unable to find the pools in a reasonable time. Please, contact Support.

" -msgstr "" - -#, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:244 -msgid "

Unknown error. Please, contact Support.

" -msgstr "" - #, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:4 msgid "Unable to find any pools you staked into." msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9 +msgid "Searching for pools you have ever staked into. Please, wait..." +msgstr "" From 485efd04654e70dcc42984fef28dc5c21aa65b7e Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 11 Dec 2019 14:13:26 +0300 Subject: [PATCH 43/75] Prevent running parallel Claim Reward tasks --- .../assets/js/pages/stakes/claim_reward.js | 6 ++- .../channels/stakes_channel.ex | 40 +++++++++++++++---- apps/block_scout_web/priv/gettext/default.pot | 5 +++ .../priv/gettext/en/LC_MESSAGES/default.po | 7 +++- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 46013d4dd0c5..e0cc2dee11a9 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -1,5 +1,5 @@ import $ from 'jquery' -import { openModal, openWarningModal, lockModal, unlockModal } from '../../lib/modals' +import { openModal, openErrorModal, openWarningModal, lockModal, unlockModal } from '../../lib/modals' import { isSupportedNetwork } from './utils' export function openClaimRewardModal(store) { @@ -41,7 +41,9 @@ export function openClaimRewardModal(store) { modalBody.html(msg_pools.html) }) $modal.on('shown.bs.modal', () => { - channel.push('render_claim_reward', {}) + channel.push('render_claim_reward', {}).receive('error', (error) => { + openErrorModal('Claim Reward', error.reason) + }) }) $modal.on('hidden.bs.modal', () => { $(this).remove() 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 b9e15950dd5e..2863db48b78b 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 @@ -11,6 +11,8 @@ defmodule BlockScoutWeb.StakesChannel do alias Explorer.Staking.ContractState alias Phoenix.View + import BlockScoutWeb.Gettext + intercept(["staking_update"]) def join("stakes:staking_update", _params, socket) do @@ -231,14 +233,24 @@ defmodule BlockScoutWeb.StakesChannel do end def handle_in("render_claim_reward", data, socket) do - html = if data["preload"] do - View.render_to_string(StakesView, "_stakes_modal_claim_reward.html", %{}) + if socket.assigns[:searching_claim_reward_pools] do + {:reply, {:error, %{reason: gettext("Pools searching is already in progress")}}, socket} else - Task.async(__MODULE__, :find_claim_reward_pools, [socket]) - "OK" + result = if data["preload"] do + %{ + html: View.render_to_string(StakesView, "_stakes_modal_claim_reward.html", %{}), + socket: socket + } + else + task = Task.async(__MODULE__, :find_claim_reward_pools, [socket]) + %{ + html: "OK", + socket: assign(socket, :searching_claim_reward_pools, task) + } + end + + {:reply, {:ok, %{html: result.html}}, result.socket} end - result = %{html: html} - {:reply, {:ok, result}, socket} end def handle_in("render_claim_withdrawal", %{"address" => staking_address}, socket) do @@ -262,6 +274,20 @@ defmodule BlockScoutWeb.StakesChannel do {:reply, {:ok, result}, socket} end + def handle_info({:DOWN, ref, :process, pid, :normal}, socket) do + task = socket.assigns[:searching_claim_reward_pools] + socket = if task && task.ref == ref && task.pid == pid do + assign(socket, :searching_claim_reward_pools, nil) + else + socket + end + {:noreply, socket} + end + + def handle_info(_, socket) do + {:noreply, socket} + end + def handle_out("staking_update", data, socket) do push(socket, "staking_update", %{ block_number: data.block_number, @@ -277,7 +303,7 @@ defmodule BlockScoutWeb.StakesChannel do def find_claim_reward_pools(socket) do pools = [] - :timer.sleep(20000) # emulate working + :timer.sleep(5000) # emulate working html = View.render_to_string(StakesView, "_stakes_modal_claim_reward_content.html", pools: pools) push(socket, "claim_reward_pools", %{ html: html diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index c91d4452ee85..0b847b9f4181 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2347,3 +2347,8 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9 msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:237 +msgid "Pools searching is already in progress" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 3b9f29a387f6..0b847b9f4181 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2343,7 +2343,12 @@ msgstr "" msgid "Unable to find any pools you staked into." msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9 msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:237 +msgid "Pools searching is already in progress" +msgstr "" From ee303aa95695d8728a4b4623cf2e1598524bb529 Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 11 Dec 2019 17:50:03 +0300 Subject: [PATCH 44/75] Don't allow parallel Claim Reward tasks for the same staker --- .../assets/js/pages/stakes/claim_reward.js | 10 +-- .../channels/stakes_channel.ex | 83 +++++++++++++------ apps/block_scout_web/priv/gettext/default.pot | 9 +- .../priv/gettext/en/LC_MESSAGES/default.po | 9 +- 4 files changed, 75 insertions(+), 36 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index e0cc2dee11a9..c676c6161634 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -5,13 +5,7 @@ import { isSupportedNetwork } from './utils' export function openClaimRewardModal(store) { if (!isSupportedNetwork(store)) return - const state = store.getState(); - - if (!state.account) { - openWarningModal('Unauthorized', 'Please login with MetaMask') - return - } - + const state = store.getState() const channel = state.channel channel.push('render_claim_reward', { preload: true }).receive('ok', msg => { @@ -50,5 +44,7 @@ export function openClaimRewardModal(store) { }) openModal($modal); + }).receive('error', (error) => { + openErrorModal('Claim Reward', error.reason) }) } 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 2863db48b78b..beea45501bea 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 @@ -13,12 +13,21 @@ defmodule BlockScoutWeb.StakesChannel do import BlockScoutWeb.Gettext + @searching_claim_reward_pools :searching_claim_reward_pools + intercept(["staking_update"]) def join("stakes:staking_update", _params, socket) do {:ok, %{}, socket} end + def terminate(_, socket) do + s = socket.assigns[@searching_claim_reward_pools] + if s != nil do + :ets.delete(ContractState, searching_claim_reward_pools_key(s.staker)) + end + end + def handle_in("set_account", account, socket) do socket = socket @@ -233,23 +242,36 @@ defmodule BlockScoutWeb.StakesChannel do end def handle_in("render_claim_reward", data, socket) do - if socket.assigns[:searching_claim_reward_pools] do - {:reply, {:error, %{reason: gettext("Pools searching is already in progress")}}, socket} + staker = socket.assigns[:account] + + search_in_progress = if socket.assigns[@searching_claim_reward_pools] do + true else - result = if data["preload"] do - %{ - html: View.render_to_string(StakesView, "_stakes_modal_claim_reward.html", %{}), - socket: socket - } - else - task = Task.async(__MODULE__, :find_claim_reward_pools, [socket]) - %{ - html: "OK", - socket: assign(socket, :searching_claim_reward_pools, task) - } + with [{_, true}] <- :ets.lookup(ContractState, searching_claim_reward_pools_key(staker)) do + true end + end + + cond do + search_in_progress == true -> + {:reply, {:error, %{reason: gettext("Pools searching is already in progress for this address")}}, socket} + staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" -> + {:reply, {:error, %{reason: gettext("Unknown staker address. Please, choose your account in MetaMask")}}, socket} + true -> + result = if data["preload"] do + %{ + html: View.render_to_string(StakesView, "_stakes_modal_claim_reward.html", %{}), + socket: socket + } + else + task = Task.async(__MODULE__, :find_claim_reward_pools, [socket, staker]) + %{ + html: "OK", + socket: assign(socket, @searching_claim_reward_pools, %{task: task, staker: staker}) + } + end - {:reply, {:ok, %{html: result.html}}, result.socket} + {:reply, {:ok, %{html: result.html}}, result.socket} end end @@ -274,10 +296,11 @@ defmodule BlockScoutWeb.StakesChannel do {:reply, {:ok, result}, socket} end - def handle_info({:DOWN, ref, :process, pid, :normal}, socket) do - task = socket.assigns[:searching_claim_reward_pools] - socket = if task && task.ref == ref && task.pid == pid do - assign(socket, :searching_claim_reward_pools, nil) + def handle_info({:DOWN, ref, :process, pid, _reason}, socket) do + s = socket.assigns[@searching_claim_reward_pools] + socket = if s && s.task.ref == ref && s.task.pid == pid do + :ets.delete(ContractState, searching_claim_reward_pools_key(s.staker)) + assign(socket, @searching_claim_reward_pools, nil) else socket end @@ -301,13 +324,18 @@ defmodule BlockScoutWeb.StakesChannel do {:noreply, socket} end - def find_claim_reward_pools(socket) do - pools = [] - :timer.sleep(5000) # emulate working - html = View.render_to_string(StakesView, "_stakes_modal_claim_reward_content.html", pools: pools) - push(socket, "claim_reward_pools", %{ - html: html - }) + def find_claim_reward_pools(socket, staker) do + :ets.insert(ContractState, {searching_claim_reward_pools_key(staker), true}) + try do + pools = [] + :timer.sleep(15000) # emulate working + html = View.render_to_string(StakesView, "_stakes_modal_claim_reward_content.html", pools: pools) + push(socket, "claim_reward_pools", %{ + html: html + }) + after + :ets.delete(ContractState, searching_claim_reward_pools_key(staker)) + end end defp push_staking_contract(socket) do @@ -326,4 +354,9 @@ defmodule BlockScoutWeb.StakesChannel do assign(socket, :contract_sent, true) end end + + defp searching_claim_reward_pools_key(staker) do + staker = if staker == nil, do: "", else: staker + Atom.to_string(@searching_claim_reward_pools) <> "_" <> staker + end end diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 0b847b9f4181..b9f31d492e93 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2349,6 +2349,11 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:237 -msgid "Pools searching is already in progress" +#: lib/block_scout_web/channels/stakes_channel.ex:257 +msgid "Pools searching is already in progress for this address" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:259 +msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 0b847b9f4181..abe7b8543825 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2348,7 +2348,12 @@ msgstr "" msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" +#, elixir-format, fuzzy +#: lib/block_scout_web/channels/stakes_channel.ex:257 +msgid "Pools searching is already in progress for this address" +msgstr "" + #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:237 -msgid "Pools searching is already in progress" +#: lib/block_scout_web/channels/stakes_channel.ex:259 +msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" From b2ec8ff5147adff39d0df56eb888835fc114493b Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 12 Dec 2019 16:06:47 +0300 Subject: [PATCH 45/75] Find the pools an address have ever staked into --- .../channels/stakes_channel.ex | 76 +++++++++++++++++-- ...stakes_modal_claim_reward_content.html.eex | 15 +++- apps/block_scout_web/priv/gettext/default.pot | 16 +++- .../priv/gettext/en/LC_MESSAGES/default.po | 18 ++++- 4 files changed, 111 insertions(+), 14 deletions(-) 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 beea45501bea..f2576a768f51 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 @@ -251,12 +251,16 @@ defmodule BlockScoutWeb.StakesChannel do true end end + + staking_contract_address = try do ContractState.get(:staking_contract).address after end cond do search_in_progress == true -> {:reply, {:error, %{reason: gettext("Pools searching is already in progress for this address")}}, socket} staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" -> {: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 -> result = if data["preload"] do %{ @@ -264,7 +268,7 @@ defmodule BlockScoutWeb.StakesChannel do socket: socket } 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", socket: assign(socket, @searching_claim_reward_pools, %{task: task, staker: staker}) @@ -324,12 +328,44 @@ defmodule BlockScoutWeb.StakesChannel do {:noreply, socket} 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}) try do - pools = [] - :timer.sleep(15000) # emulate working - html = View.render_to_string(StakesView, "_stakes_modal_claim_reward_content.html", pools: pools) + staker_padded = + staker + |> 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", %{ html: html }) @@ -338,6 +374,32 @@ defmodule BlockScoutWeb.StakesChannel do 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 if socket.assigns[:contract_sent] do socket @@ -359,4 +421,8 @@ defmodule BlockScoutWeb.StakesChannel do staker = if staker == nil, do: "", else: staker Atom.to_string(@searching_claim_reward_pools) <> "_" <> staker end + + defp truncate_address("0x000000000000000000000000" <> truncated_address) do + "0x#{truncated_address}" + end end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex index 9884e9845e7c..38425c0b75ea 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex @@ -1,5 +1,16 @@ <%= if not Enum.empty?(@pools) do %> -

Pool list...

+

+ Pool list:
+ <%= for pool <- @pools do %> + <%= pool %>
+ <% end %> +

<% else %> -

<%= gettext("Unable to find any pools you staked into.") %>

+

+ <%= if @error do %> + <%= @error %> + <% else %> + <%= gettext("Unable to find any pools you staked into.") %> + <% end %> +

<% end %> \ No newline at end of file diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index b9f31d492e93..7ce256b3a576 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2339,7 +2339,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:4 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:13 msgid "Unable to find any pools you staked into." msgstr "" @@ -2349,11 +2349,21 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:257 +#: lib/block_scout_web/channels/stakes_channel.ex:259 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:259 +#: lib/block_scout_web/channels/stakes_channel.ex:261 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:398 +msgid "JSON RPC error" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:263 +msgid "Unknown address of Staking contract. Please, contact support" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index abe7b8543825..7ce256b3a576 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2339,7 +2339,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:4 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:13 msgid "Unable to find any pools you staked into." msgstr "" @@ -2348,12 +2348,22 @@ msgstr "" msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" -#, elixir-format, fuzzy -#: lib/block_scout_web/channels/stakes_channel.ex:257 +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:259 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:259 +#: lib/block_scout_web/channels/stakes_channel.ex:261 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:398 +msgid "JSON RPC error" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:263 +msgid "Unknown address of Staking contract. Please, contact support" +msgstr "" From 8c04a04c162b1c9ecd3e2feafc39eb2522c67c44 Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 12 Dec 2019 16:26:37 +0300 Subject: [PATCH 46/75] Fix find_claim_reward_pools function --- .../lib/block_scout_web/channels/stakes_channel.ex | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 f2576a768f51..a9263bbf80a7 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 @@ -351,10 +351,9 @@ defmodule BlockScoutWeb.StakesChannel 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) + nil, # don't filter by `toPoolStakingAddress` + "0x" <> staker_padded # filter by `staker` + ], json_rpc_named_arguments, 1) else {error, []} end From 84c22ba0de60aa8f285418ee55e940322d82a33d Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 13 Dec 2019 11:20:46 +0300 Subject: [PATCH 47/75] Cleanups --- .../channels/stakes_channel.ex | 14 +++++---- .../stakes/_stakes_modal_claim.html.eex | 29 ------------------- apps/block_scout_web/priv/gettext/default.pot | 14 +++++---- .../priv/gettext/en/LC_MESSAGES/default.po | 14 +++++---- .../lib/explorer/staking/contract_reader.ex | 18 ++++++------ .../lib/explorer/staking/contract_state.ex | 6 ++-- .../explorer/staking/stake_snapshotting.ex | 4 +-- 7 files changed, 40 insertions(+), 59 deletions(-) delete mode 100644 apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex 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 a9263bbf80a7..e15a1f36b29a 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 @@ -285,7 +285,7 @@ defmodule BlockScoutWeb.StakesChannel do delegator = Chain.staking_pool_delegator(staking_address, socket.assigns.account) html = - View.render_to_string(StakesView, "_stakes_modal_claim.html", + View.render_to_string(StakesView, "_stakes_modal_claim_withdrawal.html", token: token, delegator: delegator, pool: pool @@ -344,7 +344,7 @@ defmodule BlockScoutWeb.StakesChannel do "0x2273de02cb1f69ba6259d22c4bc22c60e4c94c193265ef6afee324a04a9b6d22", nil, # don't filter by `toPoolStakingAddress` "0x" <> staker_padded # filter by `staker` - ], json_rpc_named_arguments, 1) + ], json_rpc_named_arguments) # Search for `MovedStake` events {error, pools_moved_into} = if error == nil do @@ -353,15 +353,17 @@ defmodule BlockScoutWeb.StakesChannel do "0x4480d8e4b1e9095b94bf513961d26fe1d32386ebdd103d18fe8738cf4b2223ff", nil, # don't filter by `toPoolStakingAddress` "0x" <> staker_padded # filter by `staker` - ], json_rpc_named_arguments, 1) + ], json_rpc_named_arguments) else {error, []} end + pools = Enum.uniq(pools_staked_into ++ pools_moved_into) + html = View.render_to_string( StakesView, "_stakes_modal_claim_reward_content.html", - pools: Enum.uniq(pools_staked_into ++ pools_moved_into), + pools: pools, error: error ) @@ -373,7 +375,7 @@ defmodule BlockScoutWeb.StakesChannel do end end - defp find_claim_reward_pools_by_logs(staking_contract_address, topics, json_rpc_named_arguments, topic_index) do + defp find_claim_reward_pools_by_logs(staking_contract_address, topics, json_rpc_named_arguments) do result = EthereumJSONRPC.request(%{ id: 0, method: "eth_getLogs", @@ -387,7 +389,7 @@ defmodule BlockScoutWeb.StakesChannel do case result do {:ok, response} -> pools = Enum.uniq(Enum.map(response, fn event -> - truncate_address(Enum.at(event["topics"], topic_index)) + truncate_address(Enum.at(event["topics"], 1)) end)) {nil, pools} {:error, reason} -> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex deleted file mode 100644 index 9d4b74d307eb..000000000000 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex +++ /dev/null @@ -1,29 +0,0 @@ - \ No newline at end of file diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 7ce256b3a576..da29164c3c43 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -1972,12 +1972,14 @@ msgid "Choose Pool" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:7 +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex:7 msgid "Claim Ordered Withdraw" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:18 +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex:18 msgid "Claim the Amount" msgstr "" @@ -2228,7 +2230,8 @@ msgid "Withdraw after block #%{banned_delegators_until} (%{estimated_unban_day}) msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:22 +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex:22 msgid "Withdrawal orders made during an active staking epoch are available to claim after the epoch is complete." msgstr "" @@ -2257,7 +2260,8 @@ msgid "Your Mining Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:11 +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex:11 msgid "Your ordered amount" msgstr "" @@ -2359,7 +2363,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:398 +#: lib/block_scout_web/channels/stakes_channel.ex:399 msgid "JSON RPC error" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 7ce256b3a576..da29164c3c43 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -1972,12 +1972,14 @@ msgid "Choose Pool" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:7 +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex:7 msgid "Claim Ordered Withdraw" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:18 +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex:18 msgid "Claim the Amount" msgstr "" @@ -2228,7 +2230,8 @@ msgid "Withdraw after block #%{banned_delegators_until} (%{estimated_unban_day}) msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:22 +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex:22 msgid "Withdrawal orders made during an active staking epoch are available to claim after the epoch is complete." msgstr "" @@ -2257,7 +2260,8 @@ msgid "Your Mining Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim.html.eex:11 +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex:11 msgid "Your ordered amount" msgstr "" @@ -2359,7 +2363,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:398 +#: lib/block_scout_web/channels/stakes_channel.ex:399 msgid "JSON RPC error" msgstr "" diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 6bbf44da9e92..aa116ab0683d 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -30,6 +30,13 @@ defmodule Explorer.Staking.ContractReader do ] end + # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] + def delegator_reward_request(args) do + [ + delegator_share: {:block_reward, "delegatorShare", args} + ] + end + def pool_staking_requests(staking_address, block_number) do [ active_delegators: active_delegators_request(staking_address, block_number)[:active_delegators], @@ -64,7 +71,7 @@ defmodule Explorer.Staking.ContractReader do ] end - def staking_by_mining_requests(mining_address) do + def staking_by_mining_request(mining_address) do [ staking_address: {:validator_set, "stakingByMiningAddress", [mining_address]} ] @@ -77,19 +84,12 @@ defmodule Explorer.Staking.ContractReader do end # args = [staking_epoch, validator_staked, total_staked, pool_reward \\ 10_00000] - def validator_reward_requests(args) do + def validator_reward_request(args) do [ validator_share: {:block_reward, "validatorShare", args} ] end - # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] - def delegator_reward_requests(args) do - [ - delegator_share: {:block_reward, "delegatorShare", args} - ] - end - def perform_requests(requests, contracts, abi) do requests |> generate_requests(contracts) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 4b858be75290..12675fc9fb00 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -192,7 +192,7 @@ defmodule Explorer.Staking.ContractState do # miningToStakingAddress mapping mining_to_staking_address = validators.all - |> Enum.map(&ContractReader.staking_by_mining_requests/1) + |> Enum.map(&ContractReader.staking_by_mining_request/1) |> ContractReader.perform_grouped_requests(validators.all, contracts, abi) |> Map.new(fn {mining_address, resp} -> {mining_address, address_string_to_bytes(resp.staking_address).bytes} end) @@ -241,7 +241,7 @@ defmodule Explorer.Staking.ContractState do candidate_reward_responses = pool_staking_responses |> Enum.map(fn {_pool_staking_address, resp} -> - ContractReader.validator_reward_requests([ + ContractReader.validator_reward_request([ global_responses.epoch_number, resp.self_staked_amount, resp.total_staked_amount, @@ -260,7 +260,7 @@ defmodule Explorer.Staking.ContractState do |> Enum.map(fn {{pool_staking_address, _staker_address, _is_active}, resp} -> staking_resp = pool_staking_responses[pool_staking_address] - ContractReader.delegator_reward_requests([ + ContractReader.delegator_reward_request([ global_responses.epoch_number, resp.stake_amount, staking_resp.self_staked_amount, diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index e3f480db8ec9..43b8f026f446 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -81,7 +81,7 @@ defmodule Explorer.Staking.StakeSnapshotting do validator_reward_responses = pool_staking_responses |> Enum.map(fn {_pool_staking_address, resp} -> - ContractReader.validator_reward_requests([ + ContractReader.validator_reward_request([ epoch_number, resp.snapshotted_self_staked_amount, resp.snapshotted_total_staked_amount, @@ -100,7 +100,7 @@ defmodule Explorer.Staking.StakeSnapshotting do |> Enum.map(fn {{pool_staking_address, _staker_address}, resp} -> staking_resp = pool_staking_responses[pool_staking_address] - ContractReader.delegator_reward_requests([ + ContractReader.delegator_reward_request([ epoch_number, resp.snapshotted_stake_amount, staking_resp.snapshotted_self_staked_amount, From 07dfe65276997678827b2ab0df0d67aecee7811c Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 13 Dec 2019 11:21:16 +0300 Subject: [PATCH 48/75] Cleanups --- .../_stakes_modal_claim_withdrawal.html.eex | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex new file mode 100644 index 000000000000..9d4b74d307eb --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_withdrawal.html.eex @@ -0,0 +1,29 @@ + \ No newline at end of file From 5ebef02f4b7b481090c5cdf902183f544c55b024 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 13 Dec 2019 15:50:07 +0300 Subject: [PATCH 49/75] Fetch Claim Reward pools --- .../channels/stakes_channel.ex | 62 +++++++++++++---- ...stakes_modal_claim_reward_content.html.eex | 12 ++-- apps/block_scout_web/priv/gettext/default.pot | 4 +- .../priv/gettext/en/LC_MESSAGES/default.po | 4 +- .../lib/explorer/staking/contract_reader.ex | 68 +++++++++++++++++++ 5 files changed, 127 insertions(+), 23 deletions(-) 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 e15a1f36b29a..a93cd9829e9b 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 @@ -8,7 +8,7 @@ defmodule BlockScoutWeb.StakesChannel do alias Explorer.Chain alias Explorer.Chain.Cache.BlockNumber alias Explorer.Counters.AverageBlockTime - alias Explorer.Staking.ContractState + alias Explorer.Staking.{ContractReader, ContractState} alias Phoenix.View import BlockScoutWeb.Gettext @@ -331,11 +331,7 @@ defmodule BlockScoutWeb.StakesChannel do def find_claim_reward_pools(socket, staker, staking_contract_address) do :ets.insert(ContractState, {searching_claim_reward_pools_key(staker), true}) try do - staker_padded = - staker - |> String.replace_leading("0x", "") - |> String.pad_leading(64, ["0"]) - + staker_padded = address_pad_to_64(staker) json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments) # Search for `PlacedStake` events @@ -358,7 +354,39 @@ defmodule BlockScoutWeb.StakesChannel do {error, []} end - pools = Enum.uniq(pools_staked_into ++ pools_moved_into) + {error, pools} = if error == nil do + pools = Enum.uniq(pools_staked_into ++ pools_moved_into) + + pools_amounts = Enum.map(pools, fn pool_staking_address -> + ContractReader.call_get_reward_amount( + staking_contract_address, + [], + pool_staking_address, + staker, + json_rpc_named_arguments + ) + end) + + error = Enum.find_value(pools_amounts, fn result -> + case result do + {:error, reason} -> error_reason_to_string(reason) + _ -> nil + end + end) + + pools = if error != nil do + %{} + else + Enum.map(pools_amounts, fn {_, amounts} -> amounts end) + |> Enum.zip(pools) + |> Enum.filter(fn {amounts, _} -> amounts.token_reward_sum > 0 || amounts.native_reward_sum > 0 end) + |> Map.new(fn {val, key} -> {key, val} end) + end + + {error, pools} + else + {error, %{}} + end html = View.render_to_string( StakesView, @@ -393,11 +421,21 @@ defmodule BlockScoutWeb.StakesChannel do 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 + {error_reason_to_string(reason), []} + end + end + + defp address_pad_to_64(address) do + address + |> String.replace_leading("0x", "") + |> String.pad_leading(64, ["0"]) + end + + defp error_reason_to_string(reason) do + 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 diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex index 38425c0b75ea..be03cd4134eb 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex @@ -1,10 +1,8 @@ -<%= if not Enum.empty?(@pools) do %> -

- Pool list:
- <%= for pool <- @pools do %> - <%= pool %>
- <% end %> -

+<%= if map_size(@pools) > 0 do %> +

Pool list: + <%= for {pool_staking_address, amounts} <- @pools do %> +

<%= pool_staking_address %> (token_reward_sum = <%= amounts.token_reward_sum %>, native_reward_sum = <%= amounts.native_reward_sum %>)

+ <% end %> <% else %>

<%= if @error do %> diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index da29164c3c43..0033b3e22ab7 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2343,7 +2343,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:13 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:11 msgid "Unable to find any pools you staked into." msgstr "" @@ -2363,7 +2363,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:399 +#: lib/block_scout_web/channels/stakes_channel.ex:438 msgid "JSON RPC error" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index da29164c3c43..0033b3e22ab7 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2343,7 +2343,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:13 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:11 msgid "Unable to find any pools you staked into." msgstr "" @@ -2363,7 +2363,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:399 +#: lib/block_scout_web/channels/stakes_channel.ex:438 msgid "JSON RPC error" msgstr "" diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index aa116ab0683d..a8c63f9dcf45 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -30,6 +30,68 @@ defmodule Explorer.Staking.ContractReader do ] end + # makes a raw `eth_call` for the `getRewardAmount` function of the Staking contract: + # function getRewardAmount( + # uint256[] memory _stakingEpochs, + # address _poolStakingAddress, + # address _staker + # ) public view returns(uint256 tokenRewardSum, uint256 nativeRewardSum); + def call_get_reward_amount( + staking_contract_address, + staking_epochs, + pool_staking_address, + staker, + json_rpc_named_arguments + ) do + staking_epochs_joint = + staking_epochs + |> Enum.map(fn epoch -> + epoch + |> Integer.to_string(16) + |> String.pad_leading(64, ["0"]) + end) + |> Enum.join("") + + pool_staking_address = address_pad_to_64(pool_staking_address) + staker = address_pad_to_64(staker) + + staking_epochs_length = + Enum.count(staking_epochs) + |> Integer.to_string(16) + |> String.pad_leading(64, ["0"]) + + data = "0xfb367a9b" # `getRewardAmount` function signature + data = data <> String.pad_leading("60", 64, ["0"]) # offset to the `_stakingEpochs` array + data = data <> pool_staking_address # `_poolStakingAddress` parameter + data = data <> staker # `_staker` parameter + data = data <> staking_epochs_length # the length of `_stakingEpochs` array + data = data <> staking_epochs_joint # encoded `_stakingEpochs` array + + result = EthereumJSONRPC.request(%{ + id: 0, + method: "eth_call", + params: [%{ + to: staking_contract_address, + data: data + }] + }) |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments) + + case result do + {:ok, response} -> + response = String.replace_leading(response, "0x", "") + if String.length(response) != 64 * 2 do + {:error, "Invalid getRewardAmount response."} + else + {token_reward_sum, native_reward_sum} = String.split_at(response, 64) + token_reward_sum = String.to_integer(token_reward_sum, 16) + native_reward_sum = String.to_integer(native_reward_sum, 16) + {:ok, %{token_reward_sum: token_reward_sum, native_reward_sum: native_reward_sum}} + end + {:error, reason} -> + {:error, reason} + end + end + # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] def delegator_reward_request(args) do [ @@ -105,6 +167,12 @@ defmodule Explorer.Staking.ContractReader do |> parse_grouped_responses(keys, requests) end + defp address_pad_to_64(address) do + address + |> String.replace_leading("0x", "") + |> String.pad_leading(64, ["0"]) + end + defp generate_requests(functions, contracts) do Enum.map(functions, fn {_, {contract, function, args}} -> From 4491397fef8686560c0e3b2d3141f419097ea5d4 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 13 Dec 2019 17:32:34 +0300 Subject: [PATCH 50/75] Display drop-down list of Claim Reward pools with amounts --- .../channels/stakes_channel.ex | 5 ++- ...stakes_modal_claim_reward_content.html.eex | 24 ++++++++++--- .../lib/block_scout_web/views/address_view.ex | 6 +++- apps/block_scout_web/priv/gettext/default.pot | 36 +++++++++++-------- .../priv/gettext/en/LC_MESSAGES/default.po | 36 +++++++++++-------- 5 files changed, 73 insertions(+), 34 deletions(-) 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 a93cd9829e9b..ae0ad159c7bf 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 @@ -7,6 +7,7 @@ defmodule BlockScoutWeb.StakesChannel do alias BlockScoutWeb.{StakesController, StakesView} alias Explorer.Chain alias Explorer.Chain.Cache.BlockNumber + alias Explorer.Chain.Token alias Explorer.Counters.AverageBlockTime alias Explorer.Staking.{ContractReader, ContractState} alias Phoenix.View @@ -391,8 +392,10 @@ defmodule BlockScoutWeb.StakesChannel do html = View.render_to_string( StakesView, "_stakes_modal_claim_reward_content.html", + coin: %Token{symbol: Explorer.coin(), decimals: Decimal.new(18)}, + error: error, pools: pools, - error: error + token: ContractState.get(:token) ) push(socket, "claim_reward_pools", %{ diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex index be03cd4134eb..4c0a088568aa 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex @@ -1,8 +1,24 @@ <%= if map_size(@pools) > 0 do %> -

Pool list: - <%= for {pool_staking_address, amounts} <- @pools do %> -

<%= pool_staking_address %> (token_reward_sum = <%= amounts.token_reward_sum %>, native_reward_sum = <%= amounts.native_reward_sum %>)

- <% end %> +

<%= gettext("We found the following pools you can claim your reward from:") %>

+
+
+ +
+
<% else %>

<%= if @error do %> diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_view.ex index 15405beecbaf..02199b4d7374 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_view.ex @@ -227,7 +227,11 @@ defmodule BlockScoutWeb.AddressView do def trimmed_hash(%Hash{} = hash) do string_hash = to_string(hash) - "#{String.slice(string_hash, 0..5)}–#{String.slice(string_hash, -6..-1)}" + trimmed_hash(string_hash) + end + + def trimmed_hash(address) when is_binary(address) do + "#{String.slice(address, 0..5)}–#{String.slice(address, -6..-1)}" end def trimmed_hash(_), do: "" diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 0033b3e22ab7..26c657e32b3e 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -253,7 +253,7 @@ msgstr "" #: lib/block_scout_web/templates/address/_tabs.html.eex:32 #: lib/block_scout_web/templates/address/overview.html.eex:97 #: lib/block_scout_web/templates/address_validation/index.html.eex:13 -#: lib/block_scout_web/views/address_view.ex:311 +#: lib/block_scout_web/views/address_view.ex:315 msgid "Blocks Validated" msgstr "" @@ -307,13 +307,13 @@ msgstr "" #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:126 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:149 -#: lib/block_scout_web/views/address_view.ex:307 +#: lib/block_scout_web/views/address_view.ex:311 msgid "Code" msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/_tabs.html.eex:20 -#: lib/block_scout_web/views/address_view.ex:310 +#: lib/block_scout_web/views/address_view.ex:314 msgid "Coin Balance History" msgstr "" @@ -528,7 +528,7 @@ msgid "Decoded" msgstr "" #, elixir-format -#: lib/block_scout_web/views/address_view.ex:308 +#: lib/block_scout_web/views/address_view.ex:312 msgid "Decompiled Code" msgstr "" @@ -936,7 +936,7 @@ msgstr "" #: lib/block_scout_web/templates/address/_tabs.html.eex:8 #: lib/block_scout_web/templates/address_token/index.html.eex:8 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:9 -#: lib/block_scout_web/views/address_view.ex:304 +#: lib/block_scout_web/views/address_view.ex:308 msgid "Tokens" msgstr "" @@ -989,7 +989,7 @@ msgstr "" #: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:19 #: lib/block_scout_web/templates/transaction/_tabs.html.eex:11 #: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6 -#: lib/block_scout_web/views/address_view.ex:306 +#: lib/block_scout_web/views/address_view.ex:310 #: lib/block_scout_web/views/transaction_view.ex:314 msgid "Internal Transactions" msgstr "" @@ -1078,7 +1078,7 @@ msgstr "" #: lib/block_scout_web/templates/address_logs/index.html.eex:8 #: lib/block_scout_web/templates/transaction/_tabs.html.eex:17 #: lib/block_scout_web/templates/transaction_log/index.html.eex:8 -#: lib/block_scout_web/views/address_view.ex:312 +#: lib/block_scout_web/views/address_view.ex:316 #: lib/block_scout_web/views/transaction_view.ex:315 msgid "Logs" msgstr "" @@ -1270,7 +1270,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/_tabs.html.eex:58 #: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:25 -#: lib/block_scout_web/views/address_view.ex:309 +#: lib/block_scout_web/views/address_view.ex:313 #: lib/block_scout_web/views/tokens/overview_view.ex:37 msgid "Read Contract" msgstr "" @@ -1563,7 +1563,7 @@ msgstr "" #: lib/block_scout_web/templates/block_transaction/index.html.eex:18 #: lib/block_scout_web/templates/chain/show.html.eex:145 #: lib/block_scout_web/templates/layout/_topnav.html.eex:64 -#: lib/block_scout_web/views/address_view.ex:305 +#: lib/block_scout_web/views/address_view.ex:309 msgid "Transactions" msgstr "" @@ -1967,6 +1967,8 @@ msgid "Candidate’s Staked Amount" msgstr "" #, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:6 #: lib/block_scout_web/templates/stakes/_stakes_modal_move.html.eex:22 msgid "Choose Pool" msgstr "" @@ -2343,7 +2345,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:11 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 msgid "Unable to find any pools you staked into." msgstr "" @@ -2353,21 +2355,27 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:259 +#: lib/block_scout_web/channels/stakes_channel.ex:260 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:261 +#: lib/block_scout_web/channels/stakes_channel.ex:262 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:438 +#: lib/block_scout_web/channels/stakes_channel.ex:441 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:263 +#: lib/block_scout_web/channels/stakes_channel.ex:264 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:2 +msgid "We found the following pools you can claim your reward from:" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 0033b3e22ab7..26c657e32b3e 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -253,7 +253,7 @@ msgstr "" #: lib/block_scout_web/templates/address/_tabs.html.eex:32 #: lib/block_scout_web/templates/address/overview.html.eex:97 #: lib/block_scout_web/templates/address_validation/index.html.eex:13 -#: lib/block_scout_web/views/address_view.ex:311 +#: lib/block_scout_web/views/address_view.ex:315 msgid "Blocks Validated" msgstr "" @@ -307,13 +307,13 @@ msgstr "" #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:126 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:149 -#: lib/block_scout_web/views/address_view.ex:307 +#: lib/block_scout_web/views/address_view.ex:311 msgid "Code" msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/_tabs.html.eex:20 -#: lib/block_scout_web/views/address_view.ex:310 +#: lib/block_scout_web/views/address_view.ex:314 msgid "Coin Balance History" msgstr "" @@ -528,7 +528,7 @@ msgid "Decoded" msgstr "" #, elixir-format -#: lib/block_scout_web/views/address_view.ex:308 +#: lib/block_scout_web/views/address_view.ex:312 msgid "Decompiled Code" msgstr "" @@ -936,7 +936,7 @@ msgstr "" #: lib/block_scout_web/templates/address/_tabs.html.eex:8 #: lib/block_scout_web/templates/address_token/index.html.eex:8 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:9 -#: lib/block_scout_web/views/address_view.ex:304 +#: lib/block_scout_web/views/address_view.ex:308 msgid "Tokens" msgstr "" @@ -989,7 +989,7 @@ msgstr "" #: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:19 #: lib/block_scout_web/templates/transaction/_tabs.html.eex:11 #: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6 -#: lib/block_scout_web/views/address_view.ex:306 +#: lib/block_scout_web/views/address_view.ex:310 #: lib/block_scout_web/views/transaction_view.ex:314 msgid "Internal Transactions" msgstr "" @@ -1078,7 +1078,7 @@ msgstr "" #: lib/block_scout_web/templates/address_logs/index.html.eex:8 #: lib/block_scout_web/templates/transaction/_tabs.html.eex:17 #: lib/block_scout_web/templates/transaction_log/index.html.eex:8 -#: lib/block_scout_web/views/address_view.ex:312 +#: lib/block_scout_web/views/address_view.ex:316 #: lib/block_scout_web/views/transaction_view.ex:315 msgid "Logs" msgstr "" @@ -1270,7 +1270,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/_tabs.html.eex:58 #: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:25 -#: lib/block_scout_web/views/address_view.ex:309 +#: lib/block_scout_web/views/address_view.ex:313 #: lib/block_scout_web/views/tokens/overview_view.ex:37 msgid "Read Contract" msgstr "" @@ -1563,7 +1563,7 @@ msgstr "" #: lib/block_scout_web/templates/block_transaction/index.html.eex:18 #: lib/block_scout_web/templates/chain/show.html.eex:145 #: lib/block_scout_web/templates/layout/_topnav.html.eex:64 -#: lib/block_scout_web/views/address_view.ex:305 +#: lib/block_scout_web/views/address_view.ex:309 msgid "Transactions" msgstr "" @@ -1967,6 +1967,8 @@ msgid "Candidate’s Staked Amount" msgstr "" #, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:6 #: lib/block_scout_web/templates/stakes/_stakes_modal_move.html.eex:22 msgid "Choose Pool" msgstr "" @@ -2343,7 +2345,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:11 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 msgid "Unable to find any pools you staked into." msgstr "" @@ -2353,21 +2355,27 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:259 +#: lib/block_scout_web/channels/stakes_channel.ex:260 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:261 +#: lib/block_scout_web/channels/stakes_channel.ex:262 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:438 +#: lib/block_scout_web/channels/stakes_channel.ex:441 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:263 +#: lib/block_scout_web/channels/stakes_channel.ex:264 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:2 +msgid "We found the following pools you can claim your reward from:" +msgstr "" From ab527a120160422da877d5931aa5d7f3c88001bd Mon Sep 17 00:00:00 2001 From: Vadim Date: Mon, 16 Dec 2019 17:59:09 +0300 Subject: [PATCH 51/75] Retrieve epoch numbers for Claim Reward dialog popup --- .../channels/stakes_channel.ex | 44 +++++++++++++++++++ ...stakes_modal_claim_reward_content.html.eex | 14 +++--- apps/block_scout_web/priv/gettext/default.pot | 14 +++--- .../priv/gettext/en/LC_MESSAGES/default.po | 14 +++--- .../lib/explorer/staking/contract_reader.ex | 6 +++ .../contracts_abi/posdao/BlockRewardAuRa.json | 23 ++++++++++ 6 files changed, 96 insertions(+), 19 deletions(-) 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 ae0ad159c7bf..297040584f7f 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 @@ -378,9 +378,25 @@ defmodule BlockScoutWeb.StakesChannel do pools = if error != nil do %{} else + block_reward_contract = ContractState.get(:block_reward_contract) + Enum.map(pools_amounts, fn {_, amounts} -> amounts end) |> Enum.zip(pools) |> Enum.filter(fn {amounts, _} -> amounts.token_reward_sum > 0 || amounts.native_reward_sum > 0 end) + |> Enum.map(fn {amounts, pool_staking_address} -> + responses = + ContractReader.epochs_to_claim_reward_from_request(pool_staking_address, staker) + |> ContractReader.perform_requests(%{block_reward: block_reward_contract.address}, block_reward_contract.abi) + + epochs = + array_to_ranges(responses[:epochs]) + |> Enum.map(fn {first, last} -> + Integer.to_string(first) <> (if first != last, do: "-" <> Integer.to_string(last), else: "") + end) + data = Map.put(amounts, :epochs, Enum.join(epochs, ",")) + + {data, pool_staking_address} + end) |> Map.new(fn {val, key} -> {key, val} end) end @@ -434,6 +450,22 @@ defmodule BlockScoutWeb.StakesChannel do |> String.pad_leading(64, ["0"]) end + defp array_to_ranges(numbers, prev_ranges \\ []) do + length = Enum.count(numbers) + if length > 0 do + {first, last, next_index} = get_range(numbers) + ranges = prev_ranges ++ [{first, last}] + if next_index == 0 || next_index >= length do + ranges + else + Enum.slice(numbers, next_index, length - next_index) + |> array_to_ranges(ranges) + end + else + [] + end + end + defp error_reason_to_string(reason) do if is_map(reason) && Map.has_key?(reason, :message) && String.length(String.trim(reason.message)) > 0 do reason.message @@ -442,6 +474,18 @@ defmodule BlockScoutWeb.StakesChannel do end end + defp get_range(numbers) do + last_index = + Enum.with_index(numbers) + |> Enum.find_index(fn {n, i} -> + if i > 0, do: n != Enum.at(numbers, i - 1) + 1, else: false + end) + next_index = if last_index == nil, do: Enum.count(numbers), else: last_index + first = Enum.at(numbers, 0) + last = Enum.at(numbers, next_index - 1) + {first, last, next_index} + end + defp push_staking_contract(socket) do if socket.assigns[:contract_sent] do socket diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex index 4c0a088568aa..1dfec38f0033 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex @@ -4,14 +4,18 @@

@@ -9,12 +9,12 @@ token_reward_sum = format_token_amount(data.token_reward_sum, @token, digits: 5, ellipsize: false, symbol: false) native_reward_sum = format_token_amount(data.native_reward_sum, @coin, digits: 5, ellipsize: false, symbol: false) %> -
+ + <% else %>

diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index c8dfc23577e1..ebbd5ff1d3d0 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2339,6 +2339,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:52 #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 msgid "Claim Reward" msgstr "" @@ -2359,7 +2360,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:473 +#: lib/block_scout_web/channels/stakes_channel.ex:505 msgid "JSON RPC error" msgstr "" @@ -2368,14 +2369,68 @@ msgstr "" msgid "Unknown address of Staking contract. Please, contact support" msgstr "" +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:60 +msgid "Unable to find any pools you could claim a reward from." +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:33 +msgid "Claim for" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:37 +msgid "Epochs range(s) or enum, e.g.: 5-9,23-27,47,50" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:47 +msgid "Tx Gas Limit:" +msgstr "" + #, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:2 -msgid "We found the following pools you can claim your reward from:" +msgid "We found the following pools you can claim reward from:" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:31 -msgid "Unable to find any pools you could claim a reward from." +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:41 +msgid "You will receive:" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:34 +msgid "all epochs" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:35 +msgid "specified epochs only" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:11 +msgid "You can get your reward for all staking epochs during which the pool was a validator or specify separate epochs if Tx Gas Limit is too high. Tx Gas Limit depends on how long the pool was a validator and how many staking epochs you held your stake in the pool without movement." +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:44 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:49 +msgid "Recalculate" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 +msgid "The staking epochs for which the reward could be claimed:" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 3612181cf638..706428028504 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2339,6 +2339,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:52 #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 msgid "Claim Reward" msgstr "" @@ -2359,7 +2360,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:473 +#: lib/block_scout_web/channels/stakes_channel.ex:505 msgid "JSON RPC error" msgstr "" @@ -2368,14 +2369,68 @@ msgstr "" msgid "Unknown address of Staking contract. Please, contact support" msgstr "" +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:60 +msgid "Unable to find any pools you could claim a reward from." +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:33 +msgid "Claim for" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:37 +msgid "Epochs range(s) or enum, e.g.: 5-9,23-27,47,50" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:47 +msgid "Tx Gas Limit:" +msgstr "" + #, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:2 -msgid "We found the following pools you can claim your reward from:" +msgid "We found the following pools you can claim reward from:" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:41 +msgid "You will receive:" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:34 +msgid "all epochs" +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:35 +msgid "specified epochs only" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:11 +msgid "You can get your reward for all staking epochs during which the pool was a validator or specify separate epochs if Tx Gas Limit is too high. Tx Gas Limit depends on how long the pool was a validator and how many staking epochs you held your stake in the pool without movement." +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:44 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:49 +msgid "Recalculate" msgstr "" #, elixir-format, fuzzy #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:31 -msgid "Unable to find any pools you could claim a reward from." +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 +msgid "The staking epochs for which the reward could be claimed:" msgstr "" diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 3f31ab61c77c..f108b51a0e0a 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -92,6 +92,63 @@ defmodule Explorer.Staking.ContractReader do end end + # makes a raw `eth_estimateGas` for the `claimReward` function of the Staking contract: + # function claimReward( + # uint256[] memory _stakingEpochs, + # address _poolStakingAddress + # ) public; + def claim_reward_estimate_gas( + staking_contract_address, + staking_epochs, + pool_staking_address, + staker, + json_rpc_named_arguments + ) do + staking_epochs_joint = + staking_epochs + |> Enum.map(fn epoch -> + epoch + |> Integer.to_string(16) + |> String.pad_leading(64, ["0"]) + end) + |> Enum.join("") + + pool_staking_address = address_pad_to_64(pool_staking_address) + + staking_epochs_length = + Enum.count(staking_epochs) + |> Integer.to_string(16) + |> String.pad_leading(64, ["0"]) + + data = "0x3ea15d62" # `claimReward` function signature + data = data <> String.pad_leading("40", 64, ["0"]) # offset to the `_stakingEpochs` array + data = data <> pool_staking_address # `_poolStakingAddress` parameter + data = data <> staking_epochs_length # the length of `_stakingEpochs` array + data = data <> staking_epochs_joint # encoded `_stakingEpochs` array + + result = EthereumJSONRPC.request(%{ + id: 0, + method: "eth_estimateGas", + params: [%{ + from: staker, + to: staking_contract_address, + gasPrice: "0x3B9ACA00", # 1 gwei + data: data + }] + }) |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments) + + case result do + {:ok, response} -> + estimate = + response + |> String.replace_leading("0x", "") + |> String.to_integer(16) + {:ok, estimate} + {:error, reason} -> + {:error, reason} + end + end + # args = [staking_epoch, delegator_staked, validator_staked, total_staked, pool_reward \\ 10_00000] def delegator_reward_request(args) do [ From 02a44196fd11ec97289301d334260e7a58346c6b Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 18 Dec 2019 17:14:14 +0300 Subject: [PATCH 53/75] Prepare Recalculate button for Claim Reward --- .../assets/js/pages/stakes/claim_reward.js | 82 ++++++++++++++++++- .../channels/stakes_channel.ex | 1 + .../stakes/_stakes_btn_claim_reward.html.eex | 3 + .../stakes/_stakes_btn_recalculate.html.eex | 34 ++++++++ ...stakes_modal_claim_reward_content.html.eex | 5 +- apps/block_scout_web/priv/gettext/default.pot | 11 ++- .../priv/gettext/en/LC_MESSAGES/default.po | 13 ++- 7 files changed, 131 insertions(+), 18 deletions(-) create mode 100644 apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_recalculate.html.eex diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 106ed2b37485..18b0dbc759c4 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -54,13 +54,17 @@ function onPoolsFound($modal, $modalBody) { const $poolsDropdown = $('[pool-select]', $modalBody) const $epochChoiceRadio = $('input[name="epoch_choice"]', $modalBody) const $specifiedEpochsText = $('.specified-epochs', $modalBody) + let allowedEpochs = [] $poolsDropdown.on('change', () => { const data = $('option:selected', this).data() const $poolInfo = $('.selected-pool-info', $modalBody) + const epochs = data.epochs ? data.epochs : '' + + allowedEpochs = expandEpochsToArray(epochs) $poolsDropdown.blur() - $('textarea', $poolInfo).val(data.epochs ? data.epochs : '') + $('textarea', $poolInfo).val(epochs) $('#token-reward-sum', $poolInfo).html(data.tokenRewardSum ? data.tokenRewardSum : '0') $('#native-reward-sum', $poolInfo).html(data.nativeRewardSum ? data.nativeRewardSum : '0') $('#tx-gas-limit', $poolInfo).html(data.gasLimit ? '~' + data.gasLimit : '0') @@ -71,6 +75,80 @@ function onPoolsFound($modal, $modalBody) { }) $epochChoiceRadio.on('change', () => { - $specifiedEpochsText.toggleClass('hidden') + if ($('#epoch-choice-all', $modalBody).is(':checked')) { + $specifiedEpochsText.addClass('hidden') + showRecalcButton(false, $modalBody) + } else { + $specifiedEpochsText.removeClass('hidden') + $specifiedEpochsText.trigger('input') + } + }) + + $specifiedEpochsText.on('input', () => { + const filtered = filterSpecifiedEpochs($specifiedEpochsText.val()) + const pointedEpochs = expandEpochsToArray(filtered) + const needsRecalc = pointedEpochs.length > 0 && !isArrayIncludedToArray(allowedEpochs, pointedEpochs) + showRecalcButton(needsRecalc, $modalBody) + $specifiedEpochsText.val(filtered) }) } + +function showRecalcButton(show, $modalBody) { + const $itemsToStrikeOut = $('#token-reward-sum, #native-reward-sum, #tx-gas-limit', $modalBody) + const $recalculateButton = $('button.recalculate', $modalBody) + const $submitButton = $('button.submit', $modalBody) + if (show) { + $itemsToStrikeOut.css('text-decoration', 'line-through') + $recalculateButton.removeClass('hidden') + $submitButton.addClass('hidden') + } else { + $itemsToStrikeOut.css('text-decoration', '') + $recalculateButton.addClass('hidden') + $submitButton.removeClass('hidden') + } +} + +function expandEpochsToArray(epochs) { + let filtered = epochs.replace(/[-|,]$/g, '').trim() + if (filtered == '') return [] + let ranges = filtered.split(',') + ranges = ranges.map((v) => { + if (v.indexOf('-') > -1) { + v = v.split('-') + v[0] = parseInt(v[0]) + v[1] = parseInt(v[1]) + v.sort((a, b) => a - b) + const min = v[0] + const max = v[1] + let expanded = [] + for (let i = min; i <= max; i++) { + expanded.push(i) + } + return expanded + } else { + return parseInt(v) + } + }) + ranges = ranges.reduce((acc, val) => acc.concat(val), []) // similar to ranges.flat() + ranges.sort((a, b) => a - b) + ranges = [...new Set(ranges)] // make unique + ranges = ranges.filter(epoch => epoch != 0) + return ranges +} + +function filterSpecifiedEpochs(epochs) { + let filtered = epochs + filtered = filtered.replace(/[^0-9,-]+/g, '') + filtered = filtered.replace(/-{2,}/g, '-') + filtered = filtered.replace(/,{2,}/g, ',') + filtered = filtered.replace(/,-/g, ',') + filtered = filtered.replace(/-,/g, '-') + filtered = filtered.replace(/(-[0-9]+)-/g, '$1,') + filtered = filtered.replace(/^[,|-|0]/g, '') + return filtered +} + +function isArrayIncludedToArray(source, target) { + const filtered = target.filter(item => source.indexOf(item) != -1) + return filtered.length == source.length +} 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 daae4283c9f7..b37d144c2c72 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 @@ -399,6 +399,7 @@ defmodule BlockScoutWeb.StakesChannel do {data, pool_staking_address} end) + |> Enum.filter(fn {data, _} -> data.epochs != "" end) pools_gas_estimates = Enum.map(pools, fn {_data, pool_staking_address} -> result = ContractReader.claim_reward_estimate_gas( diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_claim_reward.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_claim_reward.html.eex index 96a04a09ba93..a36547d971c9 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_claim_reward.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_claim_reward.html.eex @@ -1,3 +1,6 @@ \ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_recalculate.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_recalculate.html.eex new file mode 100644 index 000000000000..9d8813f7d7df --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_recalculate.html.eex @@ -0,0 +1,34 @@ + \ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex index 81ca12b13050..1643b5da1cf2 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex @@ -41,15 +41,14 @@ <%= gettext("You will receive:") %>
<%= @token.symbol %>
<%= @coin.symbol %>
-

<%= gettext("Tx Gas Limit:") %>

-

- <%= render BlockScoutWeb.StakesView, "_stakes_btn_withdraw.html", text: gettext("Claim Reward"), extra_class: "full-width" %> + <%= render BlockScoutWeb.StakesView, "_stakes_btn_recalculate.html", text: gettext("Recalculate"), extra_class: "full-width recalculate hidden" %> + <%= render BlockScoutWeb.StakesView, "_stakes_btn_withdraw.html", text: gettext("Claim Reward"), extra_class: "full-width submit" %>
<% else %> diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index ebbd5ff1d3d0..3474c848d036 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2339,7 +2339,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:52 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:51 #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 msgid "Claim Reward" msgstr "" @@ -2360,7 +2360,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:505 +#: lib/block_scout_web/channels/stakes_channel.ex:506 msgid "JSON RPC error" msgstr "" @@ -2371,7 +2371,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:60 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:59 msgid "Unable to find any pools you could claim a reward from." msgstr "" @@ -2389,7 +2389,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:47 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:46 msgid "Tx Gas Limit:" msgstr "" @@ -2424,8 +2424,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:44 -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:49 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:50 msgid "Recalculate" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 706428028504..3474c848d036 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2339,7 +2339,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:52 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:51 #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 msgid "Claim Reward" msgstr "" @@ -2360,7 +2360,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:505 +#: lib/block_scout_web/channels/stakes_channel.ex:506 msgid "JSON RPC error" msgstr "" @@ -2371,7 +2371,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:60 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:59 msgid "Unable to find any pools you could claim a reward from." msgstr "" @@ -2389,7 +2389,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:47 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:46 msgid "Tx Gas Limit:" msgstr "" @@ -2424,12 +2424,11 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:44 -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:49 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:50 msgid "Recalculate" msgstr "" -#, elixir-format, fuzzy +#, elixir-format #: #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 msgid "The staking epochs for which the reward could be claimed:" From 32e13ab0550cd9d71772e877c5954885fb6fbb43 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 20 Dec 2019 17:29:37 +0300 Subject: [PATCH 54/75] Implement Recalculate button for Claim Reward --- .../assets/css/components/stakes/_stakes.scss | 2 +- apps/block_scout_web/assets/js/lib/modals.js | 27 ++- .../assets/js/lib/validation.js | 4 +- .../assets/js/pages/stakes/claim_reward.js | 187 +++++++++++++----- .../channels/stakes_channel.ex | 123 +++++++++--- .../stakes/_stakes_btn_claim_reward.html.eex | 2 +- .../stakes/_stakes_btn_recalculate.html.eex | 10 +- ...stakes_modal_claim_reward_content.html.eex | 11 +- .../templates/stakes/_stakes_top.html.eex | 4 +- apps/block_scout_web/priv/gettext/default.pot | 31 ++- .../priv/gettext/en/LC_MESSAGES/default.po | 31 ++- 11 files changed, 328 insertions(+), 104 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/stakes/_stakes.scss b/apps/block_scout_web/assets/css/components/stakes/_stakes.scss index a01e58efead5..dbde40d2b2ac 100644 --- a/apps/block_scout_web/assets/css/components/stakes/_stakes.scss +++ b/apps/block_scout_web/assets/css/components/stakes/_stakes.scss @@ -171,7 +171,7 @@ $stakes-stats-item-border-color: #fff !default; @include media-breakpoint-down(md) { grid-column-start: 2; grid-row-start: 2; - justify-self: end; + justify-self: left; } @include media-breakpoint-down(sm) { diff --git a/apps/block_scout_web/assets/js/lib/modals.js b/apps/block_scout_web/assets/js/lib/modals.js index e0310d5d31b5..6fbb4713609d 100644 --- a/apps/block_scout_web/assets/js/lib/modals.js +++ b/apps/block_scout_web/assets/js/lib/modals.js @@ -21,6 +21,10 @@ $(document.body).on('hide.bs.modal', e => { $currentModal = null }) +export function isModalLocked() { + return modalLocked +} + export function openModal ($modal) { // Hide all tooltips before showing a modal, // since they are sticking on top of modal @@ -48,7 +52,15 @@ export function lockModal ($modal, $submitButton = null) { $button .attr('data-text', $button.text()) .attr('disabled', true) - .html(spinner) + + const $span = $('span', $button) + + if ($span.length) { + $('svg', $button).hide() + $span.html(spinner) + } else { + $button.html(spinner) + } modalLocked = true } @@ -57,10 +69,17 @@ export function unlockModal ($modal, $submitButton = null) { $modal.find('.close-modal').attr('disabled', false) const $button = $submitButton || $modal.find('.btn-add-full') + const buttonText = $button.attr('data-text'); - $button - .text($button.attr('data-text')) - .attr('disabled', false) + $button.attr('disabled', false) + + const $span = $('span', $button) + if ($span.length) { + $('svg', $button).show() + $span.text(buttonText) + } else { + $button.text(buttonText) + } modalLocked = false } diff --git a/apps/block_scout_web/assets/js/lib/validation.js b/apps/block_scout_web/assets/js/lib/validation.js index 5574925f746c..c128cf22003c 100644 --- a/apps/block_scout_web/assets/js/lib/validation.js +++ b/apps/block_scout_web/assets/js/lib/validation.js @@ -49,14 +49,14 @@ function updateSubmit ($submit, errors) { $submit.prop('disabled', !$.isEmptyObject(errors)) } -function displayInputError ($input, message) { +export function displayInputError ($input, message) { const group = $input.parent('.input-group') group.addClass('input-status-error') group.find('.input-group-message').html(message) } -function hideInputError ($input) { +export function hideInputError ($input) { const group = $input.parent('.input-group') group.removeClass('input-status-error') diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 18b0dbc759c4..38a0fb2a36c0 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -1,5 +1,6 @@ import $ from 'jquery' -import { openModal, openErrorModal, openWarningModal, lockModal, unlockModal } from '../../lib/modals' +import { isModalLocked, lockModal, openErrorModal, openModal, unlockModal } from '../../lib/modals' +import { displayInputError, hideInputError } from '../../lib/validation' import { isSupportedNetwork } from './utils' export function openClaimRewardModal(store) { @@ -12,52 +13,75 @@ export function openClaimRewardModal(store) { const $modal = $(msg.html) const $closeButton = $modal.find('.close-modal') const $modalBody = $('.modal-body', $modal) - const $waitingMessageContainer = $modalBody.find('p') - let dotCounter = 0 - const dotCounterInterval = setInterval(() => { - let waitingMessage = $.trim($waitingMessageContainer.text()) - if (!waitingMessage.endsWith('.')) { - waitingMessage = waitingMessage + '.' - } - waitingMessage = waitingMessage.replace(/\.+$/g, " " + ".".repeat(dotCounter)) - $waitingMessageContainer.text(waitingMessage) - dotCounter = (dotCounter + 1) % 4 - }, 500) - - $closeButton.hide() - lockModal($modal) - channel.on('claim_reward_pools', msg_pools => { - channel.off('claim_reward_pools') - $closeButton.show() - unlockModal($modal) - clearInterval(dotCounterInterval) + const dotCounterInterval = poolsSearchingStarted() + + const ref = channel.on('claim_reward_pools', msg_pools => { $modalBody.html(msg_pools.html) - onPoolsFound($modal, $modalBody) + poolsSearchingFinished() }) $modal.on('shown.bs.modal', () => { - channel.push('render_claim_reward', {}).receive('error', (error) => { - openErrorModal('Claim Reward', error.reason) + channel.push('render_claim_reward', { + }).receive('error', (error) => { + poolsSearchingFinished(error.reason) + }).receive('timeout', () => { + poolsSearchingFinished('Connection timeout') }) }) $modal.on('hidden.bs.modal', () => { $modal.remove() }) + function poolsSearchingStarted() { + $closeButton.hide() + lockModal($modal) + + const $waitingMessageContainer = $modalBody.find('p') + let dotCounter = 0 + + return setInterval(() => { + let waitingMessage = $.trim($waitingMessageContainer.text()) + if (!waitingMessage.endsWith('.')) { + waitingMessage = waitingMessage + '.' + } + waitingMessage = waitingMessage.replace(/\.+$/g, " " + ".".repeat(dotCounter)) + $waitingMessageContainer.text(waitingMessage) + dotCounter = (dotCounter + 1) % 4 + }, 500) + } + function poolsSearchingFinished(error) { + channel.off('claim_reward_pools', ref) + $closeButton.show() + unlockModal($modal) + clearInterval(dotCounterInterval) + if (error) { + openErrorModal('Claim Reward', error) + } else { + onPoolsFound($modal, $modalBody, channel) + } + } openModal($modal); }).receive('error', (error) => { openErrorModal('Claim Reward', error.reason) + }).receive('timeout', () => { + openErrorModal('Claim Reward', 'Connection timeout') }) } -function onPoolsFound($modal, $modalBody) { - const $poolsDropdown = $('[pool-select]', $modalBody) +function onPoolsFound($modal, $modalBody, channel) { + const $poolsDropdown = $('select', $modalBody) const $epochChoiceRadio = $('input[name="epoch_choice"]', $modalBody) - const $specifiedEpochsText = $('.specified-epochs', $modalBody) + const $specifiedEpochsText = $('input.specified-epochs', $modalBody) + const $recalculateButton = $('button.recalculate', $modalBody) let allowedEpochs = [] $poolsDropdown.on('change', () => { + if (isModalLocked()) return false + const data = $('option:selected', this).data() + const tokenRewardSum = data.tokenRewardSum ? data.tokenRewardSum : '0' + const nativeRewardSum = data.nativeRewardSum ? data.nativeRewardSum : '0' + const gasLimit = data.gasLimit ? data.gasLimit : '0' const $poolInfo = $('.selected-pool-info', $modalBody) const epochs = data.epochs ? data.epochs : '' @@ -65,19 +89,22 @@ function onPoolsFound($modal, $modalBody) { $poolsDropdown.blur() $('textarea', $poolInfo).val(epochs) - $('#token-reward-sum', $poolInfo).html(data.tokenRewardSum ? data.tokenRewardSum : '0') - $('#native-reward-sum', $poolInfo).html(data.nativeRewardSum ? data.nativeRewardSum : '0') - $('#tx-gas-limit', $poolInfo).html(data.gasLimit ? '~' + data.gasLimit : '0') + $('#token-reward-sum', $poolInfo).html(tokenRewardSum).data('default', tokenRewardSum) + $('#native-reward-sum', $poolInfo).html(nativeRewardSum).data('default', nativeRewardSum) + $('#tx-gas-limit', $poolInfo).html('~' + gasLimit).data('default', gasLimit) $('#epoch-choice-all', $poolInfo).click() $specifiedEpochsText.val('') $poolInfo.removeClass('hidden') $('.modal-bottom-disclaimer', $modal).removeClass('hidden') + hideInputError($recalculateButton) }) $epochChoiceRadio.on('change', () => { + if (isModalLocked()) return false if ($('#epoch-choice-all', $modalBody).is(':checked')) { $specifiedEpochsText.addClass('hidden') - showRecalcButton(false, $modalBody) + showButton('submit', $modalBody) + hideInputError($recalculateButton) } else { $specifiedEpochsText.removeClass('hidden') $specifiedEpochsText.trigger('input') @@ -85,26 +112,99 @@ function onPoolsFound($modal, $modalBody) { }) $specifiedEpochsText.on('input', () => { + if (isModalLocked()) return false + const filtered = filterSpecifiedEpochs($specifiedEpochsText.val()) - const pointedEpochs = expandEpochsToArray(filtered) - const needsRecalc = pointedEpochs.length > 0 && !isArrayIncludedToArray(allowedEpochs, pointedEpochs) - showRecalcButton(needsRecalc, $modalBody) $specifiedEpochsText.val(filtered) + + const pointedEpochs = expandEpochsToArray(filtered) + const pointedEpochsAllowed = pointedEpochs.filter(item => allowedEpochs.indexOf(item) != -1) + + const needsRecalc = pointedEpochs.length > 0 && pointedEpochsAllowed.length != allowedEpochs.length + showButton(needsRecalc ? 'recalculate' : 'submit', $modalBody) + + if (needsRecalc && pointedEpochsAllowed.length == 0) { + $recalculateButton.prop('disabled', true) + displayInputError($recalculateButton, 'The specified staking epochs are not in the allowed range') + } else { + $recalculateButton.prop('disabled', false) + hideInputError($recalculateButton) + } + }) + + $recalculateButton.on('click', (e) => { + if (isModalLocked()) return false + e.preventDefault() + recalcStarted() + + const specifiedEpochs = $specifiedEpochsText.val().replace(/[-|,]$/g, '').trim() + $specifiedEpochsText.val(specifiedEpochs) + + const epochs = expandEpochsToArray(specifiedEpochs).filter(item => allowedEpochs.indexOf(item) != -1) + const poolStakingAddress = $poolsDropdown.val() + const ref = channel.on('claim_reward_recalculations', result => { + recalcFinished(result) + }) + channel.push('recalc_claim_reward', { + epochs, + pool_staking_address: poolStakingAddress + }).receive('error', (error) => { + recalcFinished({error: error.reason}) + }).receive('timeout', () => { + recalcFinished({error: 'Connection timeout'}) + }) + function recalcStarted() { + hideInputError($recalculateButton) + lockUI(true, $modal, $recalculateButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); + } + function recalcFinished(result) { + channel.off('claim_reward_recalculations', ref) + if (result.error) { + displayInputError($recalculateButton, result.error) + } else { + showButton('submit', $modalBody, result) + } + lockUI(false, $modal, $recalculateButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); + } }) } -function showRecalcButton(show, $modalBody) { - const $itemsToStrikeOut = $('#token-reward-sum, #native-reward-sum, #tx-gas-limit', $modalBody) +function lockUI(lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText) { + if (lock) { + lockModal($modal, $button) + } else { + unlockModal($modal, $button) + } + $poolsDropdown.prop('disabled', lock) + $epochChoiceRadio.prop('disabled', lock) + $specifiedEpochsText.prop('disabled', lock) +} + +function showButton(type, $modalBody, calculations) { const $recalculateButton = $('button.recalculate', $modalBody) const $submitButton = $('button.submit', $modalBody) - if (show) { - $itemsToStrikeOut.css('text-decoration', 'line-through') - $recalculateButton.removeClass('hidden') - $submitButton.addClass('hidden') - } else { - $itemsToStrikeOut.css('text-decoration', '') + + const $tokenRewardSum = $('#token-reward-sum', $modalBody) + const $nativeRewardSum = $('#native-reward-sum', $modalBody) + const $gasLimit = $('#tx-gas-limit', $modalBody) + + if (type == 'submit') { $recalculateButton.addClass('hidden') $submitButton.removeClass('hidden') + + const tokenRewardSum = !calculations ? $tokenRewardSum.data('default') : calculations.token_reward_sum + const nativeRewardSum = !calculations ? $nativeRewardSum.data('default') : calculations.native_reward_sum + const gasLimit = !calculations ? $gasLimit.data('default') : calculations.gas_limit + + $tokenRewardSum.text(tokenRewardSum).css('text-decoration', '') + $nativeRewardSum.text(nativeRewardSum).css('text-decoration', '') + $gasLimit.text('~' + gasLimit).css('text-decoration', '') + } else { + $recalculateButton.removeClass('hidden') + $submitButton.addClass('hidden'); + [$tokenRewardSum, $nativeRewardSum, $gasLimit].forEach( + $item => $item.css('text-decoration', 'line-through') + ) } } @@ -147,8 +247,3 @@ function filterSpecifiedEpochs(epochs) { filtered = filtered.replace(/^[,|-|0]/g, '') return filtered } - -function isArrayIncludedToArray(source, target) { - const filtered = target.filter(item => source.indexOf(item) != -1) - return filtered.length == source.length -} 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 b37d144c2c72..77e404ee22c1 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 @@ -4,7 +4,7 @@ defmodule BlockScoutWeb.StakesChannel do """ use BlockScoutWeb, :channel - alias BlockScoutWeb.{StakesController, StakesView} + alias BlockScoutWeb.{StakesController, StakesHelpers, StakesView} alias Explorer.Chain alias Explorer.Chain.Cache.BlockNumber alias Explorer.Chain.Token @@ -14,7 +14,7 @@ defmodule BlockScoutWeb.StakesChannel do import BlockScoutWeb.Gettext - @searching_claim_reward_pools :searching_claim_reward_pools + @claim_reward_long_op :claim_reward_long_op intercept(["staking_update"]) @@ -23,9 +23,9 @@ defmodule BlockScoutWeb.StakesChannel do end def terminate(_, socket) do - s = socket.assigns[@searching_claim_reward_pools] + s = socket.assigns[@claim_reward_long_op] if s != nil do - :ets.delete(ContractState, searching_claim_reward_pools_key(s.staker)) + :ets.delete(ContractState, claim_reward_long_op_key(s.staker)) end end @@ -244,19 +244,10 @@ defmodule BlockScoutWeb.StakesChannel do def handle_in("render_claim_reward", data, socket) do staker = socket.assigns[:account] - - search_in_progress = if socket.assigns[@searching_claim_reward_pools] do - true - else - with [{_, true}] <- :ets.lookup(ContractState, searching_claim_reward_pools_key(staker)) do - true - end - end - staking_contract_address = try do ContractState.get(:staking_contract).address after end cond do - search_in_progress == true -> + claim_reward_long_op_active(socket) == true -> {:reply, {:error, %{reason: gettext("Pools searching is already in progress for this address")}}, socket} staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" -> {:reply, {:error, %{reason: gettext("Unknown staker address. Please, choose your account in MetaMask")}}, socket} @@ -272,7 +263,7 @@ defmodule BlockScoutWeb.StakesChannel do task = Task.async(__MODULE__, :find_claim_reward_pools, [socket, staker, staking_contract_address]) %{ html: "OK", - socket: assign(socket, @searching_claim_reward_pools, %{task: task, staker: staker}) + socket: assign(socket, @claim_reward_long_op, %{task: task, staker: staker}) } end @@ -280,6 +271,30 @@ defmodule BlockScoutWeb.StakesChannel do end end + def handle_in("recalc_claim_reward", data, socket) do + epochs = data["epochs"] + pool_staking_address = data["pool_staking_address"] + staker = socket.assigns[:account] + staking_contract_address = try do ContractState.get(:staking_contract).address after end + + cond do + claim_reward_long_op_active(socket) == true -> + {:reply, {:error, %{reason: gettext("Reward calculating is already in progress for this address")}}, socket} + Enum.count(epochs) == 0 -> + {:reply, {:error, %{reason: gettext("Staking epochs are not specified or not in the allowed range")}}, socket} + pool_staking_address == nil || pool_staking_address == "" || pool_staking_address == "0x0000000000000000000000000000000000000000" -> + {:reply, {:error, %{reason: gettext("Unknown pool staking address. Please, contact support")}}, socket} + staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" -> + {: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 -> + task = Task.async(__MODULE__, :recalc_claim_reward, [socket, staking_contract_address, epochs, pool_staking_address, staker]) + socket = assign(socket, @claim_reward_long_op, %{task: task, staker: staker}) + {:reply, {:ok, %{html: "OK"}}, socket} + end + end + def handle_in("render_claim_withdrawal", %{"address" => staking_address}, socket) do pool = Chain.staking_pool(staking_address) token = ContractState.get(:token) @@ -302,10 +317,10 @@ defmodule BlockScoutWeb.StakesChannel do end def handle_info({:DOWN, ref, :process, pid, _reason}, socket) do - s = socket.assigns[@searching_claim_reward_pools] + s = socket.assigns[@claim_reward_long_op] socket = if s && s.task.ref == ref && s.task.pid == pid do - :ets.delete(ContractState, searching_claim_reward_pools_key(s.staker)) - assign(socket, @searching_claim_reward_pools, nil) + :ets.delete(ContractState, claim_reward_long_op_key(s.staker)) + assign(socket, @claim_reward_long_op, nil) else socket end @@ -330,7 +345,7 @@ defmodule BlockScoutWeb.StakesChannel do end def find_claim_reward_pools(socket, staker, staking_contract_address) do - :ets.insert(ContractState, {searching_claim_reward_pools_key(staker), true}) + :ets.insert(ContractState, {claim_reward_long_op_key(staker), true}) try do staker_padded = address_pad_to_64(staker) json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments) @@ -451,7 +466,71 @@ defmodule BlockScoutWeb.StakesChannel do html: html }) after - :ets.delete(ContractState, searching_claim_reward_pools_key(staker)) + :ets.delete(ContractState, claim_reward_long_op_key(staker)) + end + end + + def recalc_claim_reward(socket, staking_contract_address, epochs, pool_staking_address, staker) do + :ets.insert(ContractState, {claim_reward_long_op_key(staker), true}) + try do + json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments) + + amounts_result = ContractReader.call_get_reward_amount( + staking_contract_address, + epochs, + pool_staking_address, + staker, + json_rpc_named_arguments + ) + + {error, amounts} = case amounts_result do + {:ok, amounts} -> + {nil, amounts} + {:error, reason} -> + {error_reason_to_string(reason), %{token_reward_sum: 0, native_reward_sum: 0}} + end + + {error, gas_limit} = if error == nil do + estimate_gas_result = ContractReader.claim_reward_estimate_gas( + staking_contract_address, + epochs, + pool_staking_address, + staker, + json_rpc_named_arguments + ) + + case estimate_gas_result do + {:ok, gas_limit} -> + {nil, gas_limit} + {:error, reason} -> + {error_reason_to_string(reason), 0} + end + else + {error, 0} + end + + token = ContractState.get(:token) + coin = %Token{symbol: Explorer.coin(), decimals: Decimal.new(18)} + + push(socket, "claim_reward_recalculations", %{ + token_reward_sum: StakesHelpers.format_token_amount(amounts.token_reward_sum, token, digits: 5, ellipsize: false, symbol: false), + native_reward_sum: StakesHelpers.format_token_amount(amounts.native_reward_sum, coin, digits: 5, ellipsize: false, symbol: false), + gas_limit: gas_limit, + error: error + }) + after + :ets.delete(ContractState, claim_reward_long_op_key(staker)) + end + end + + defp claim_reward_long_op_active(socket) do + if socket.assigns[@claim_reward_long_op] do + true + else + staker = socket.assigns[:account] + with [{_, true}] <- :ets.lookup(ContractState, claim_reward_long_op_key(staker)) do + true + end end end @@ -536,9 +615,9 @@ defmodule BlockScoutWeb.StakesChannel do end end - defp searching_claim_reward_pools_key(staker) do + defp claim_reward_long_op_key(staker) do staker = if staker == nil, do: "", else: staker - Atom.to_string(@searching_claim_reward_pools) <> "_" <> staker + Atom.to_string(@claim_reward_long_op) <> "_" <> staker end defp truncate_address("0x000000000000000000000000" <> truncated_address) do diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_claim_reward.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_claim_reward.html.eex index a36547d971c9..4d5a672022af 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_claim_reward.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_btn_claim_reward.html.eex @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex index 1643b5da1cf2..4b7c48d0083e 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex @@ -2,8 +2,8 @@

<%= gettext("We found the following pools you can claim reward from:") %>

- + <%= for {pool_staking_address, data} <- @pools do %> <% token_reward_sum = format_token_amount(data.token_reward_sum, @token, digits: 5, ellipsize: false, symbol: false) @@ -47,8 +47,11 @@

- <%= render BlockScoutWeb.StakesView, "_stakes_btn_recalculate.html", text: gettext("Recalculate"), extra_class: "full-width recalculate hidden" %> - <%= render BlockScoutWeb.StakesView, "_stakes_btn_withdraw.html", text: gettext("Claim Reward"), extra_class: "full-width submit" %> +
+ <%= render BlockScoutWeb.StakesView, "_stakes_btn_recalculate.html", text: gettext("Recalculate"), extra_class: "full-width recalculate hidden" %> + <%= render BlockScoutWeb.StakesView, "_stakes_btn_withdraw.html", text: gettext("Claim Reward"), extra_class: "full-width submit" %> +
+
<% else %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_top.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_top.html.eex index 0bb2a893bc12..d6b19371696b 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_top.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_top.html.eex @@ -14,7 +14,7 @@ <% end %> <% else %> <%= - button_class = + button_class = "full-width " <> if @account[:pool] do "js-make-stake" else @@ -29,7 +29,7 @@ <% end %> <% end %> - <%= render BlockScoutWeb.StakesView, "_stakes_btn_claim_reward.html", text: gettext("Claim Reward") %> + <%= render BlockScoutWeb.StakesView, "_stakes_btn_claim_reward.html", text: gettext("Claim Reward"), extra_class: "full-width" %>
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 3474c848d036..92542329789a 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2339,7 +2339,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:51 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:52 #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 msgid "Claim Reward" msgstr "" @@ -2350,28 +2350,30 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:260 +#: lib/block_scout_web/channels/stakes_channel.ex:251 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:262 +#: lib/block_scout_web/channels/stakes_channel.ex:253 +#: lib/block_scout_web/channels/stakes_channel.ex:288 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:506 +#: lib/block_scout_web/channels/stakes_channel.ex:585 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:264 +#: lib/block_scout_web/channels/stakes_channel.ex:255 +#: lib/block_scout_web/channels/stakes_channel.ex:290 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:59 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:62 msgid "Unable to find any pools you could claim a reward from." msgstr "" @@ -2424,7 +2426,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:50 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:51 msgid "Recalculate" msgstr "" @@ -2433,3 +2435,18 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 msgid "The staking epochs for which the reward could be claimed:" msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:284 +msgid "Staking epochs are not specified or not in the allowed range" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:286 +msgid "Unknown pool staking address. Please, contact support" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:282 +msgid "Reward calculating is already in progress for this address" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 3474c848d036..f72b1e2a8193 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2339,7 +2339,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:51 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:52 #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 msgid "Claim Reward" msgstr "" @@ -2350,28 +2350,30 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:260 +#: lib/block_scout_web/channels/stakes_channel.ex:251 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:262 +#: lib/block_scout_web/channels/stakes_channel.ex:253 +#: lib/block_scout_web/channels/stakes_channel.ex:288 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:506 +#: lib/block_scout_web/channels/stakes_channel.ex:585 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:264 +#: lib/block_scout_web/channels/stakes_channel.ex:255 +#: lib/block_scout_web/channels/stakes_channel.ex:290 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:59 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:62 msgid "Unable to find any pools you could claim a reward from." msgstr "" @@ -2424,7 +2426,7 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:50 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:51 msgid "Recalculate" msgstr "" @@ -2433,3 +2435,18 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 msgid "The staking epochs for which the reward could be claimed:" msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:284 +msgid "Staking epochs are not specified or not in the allowed range" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:286 +msgid "Unknown pool staking address. Please, contact support" +msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/channels/stakes_channel.ex:282 +msgid "Reward calculating is already in progress for this address" +msgstr "" From 8bd49fe1790df5dbef390c51e44786a0302f830e Mon Sep 17 00:00:00 2001 From: Vadim Date: Mon, 23 Dec 2019 18:49:08 +0300 Subject: [PATCH 55/75] Handle disconnections on client side and remove excess requests --- .../assets/css/components/_modal_status.scss | 4 + apps/block_scout_web/assets/js/lib/modals.js | 26 +++- .../block_scout_web/assets/js/pages/stakes.js | 122 ++++++++++++----- .../assets/js/pages/stakes/claim_reward.js | 33 ++++- .../channels/stakes_channel.ex | 10 ++ .../controllers/stakes_controller.ex | 124 +++++++++--------- .../templates/stakes/_rows_loading.html.eex | 1 + apps/block_scout_web/priv/gettext/default.pot | 18 +-- .../priv/gettext/en/LC_MESSAGES/default.po | 20 +-- 9 files changed, 235 insertions(+), 123 deletions(-) create mode 100644 apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows_loading.html.eex diff --git a/apps/block_scout_web/assets/css/components/_modal_status.scss b/apps/block_scout_web/assets/css/components/_modal_status.scss index c750e1c9dcfe..1971adf9e0f7 100644 --- a/apps/block_scout_web/assets/css/components/_modal_status.scss +++ b/apps/block_scout_web/assets/css/components/_modal_status.scss @@ -66,6 +66,10 @@ $modal-status-graph-question: #329ae9 !default; line-height: 1.5; margin: 0 0 25px; text-align: center; + + &.m-b-0 { + margin-bottom: 0; + } } .modal-status-button-wrapper { diff --git a/apps/block_scout_web/assets/js/lib/modals.js b/apps/block_scout_web/assets/js/lib/modals.js index 6fbb4713609d..683d41e7fbe6 100644 --- a/apps/block_scout_web/assets/js/lib/modals.js +++ b/apps/block_scout_web/assets/js/lib/modals.js @@ -21,26 +21,44 @@ $(document.body).on('hide.bs.modal', e => { $currentModal = null }) +export function currentModal() { + return $currentModal +} + export function isModalLocked() { return modalLocked } -export function openModal ($modal) { +export function openModal($modal, unclosable) { // Hide all tooltips before showing a modal, // since they are sticking on top of modal $('.tooltip').tooltip('hide') + + if (unclosable) { + $('.close-modal, .modal-status-button-wrapper', $modal).addClass('hidden') + $('.modal-status-text', $modal).addClass('m-b-0') + } + if ($currentModal) { - modalLocked = false + if (!unclosable) { + modalLocked = false + } $currentModal .one('hidden.bs.modal', () => { $modal.modal('show') $currentModal = $modal + if (unclosable) { + modalLocked = true + } }) .modal('hide') } else { $modal.modal('show') $currentModal = $modal + if (unclosable) { + modalLocked = true + } } } @@ -84,11 +102,11 @@ export function unlockModal ($modal, $submitButton = null) { modalLocked = false } -export function openErrorModal (title, text) { +export function openErrorModal (title, text, unclosable) { const $modal = $('#errorStatusModal') $modal.find('.modal-status-title').text(title) $modal.find('.modal-status-text').html(text) - openModal($modal) + openModal($modal, unclosable) } export function openWarningModal (title, text) { diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index 1c9d18eab694..b73e36a824b5 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -13,20 +13,21 @@ import { openRemovePoolModal } from './stakes/remove_pool' import { openMakeStakeModal } from './stakes/make_stake' import { openMoveStakeModal } from './stakes/move_stake' import { openWithdrawStakeModal } from './stakes/withdraw_stake' -import { openClaimRewardModal } from './stakes/claim_reward' +import { openClaimRewardModal, connectionLost } from './stakes/claim_reward' import { openClaimWithdrawalModal } from './stakes/claim_withdrawal' import { checkForTokenDefinition } from './stakes/utils' -import { openWarningModal } from '../lib/modals' +import { openWarningModal, openErrorModal } from '../lib/modals' const stakesPageSelector = '[data-page="stakes"]' export const initialState = { account: null, + blockNumber: 0, // current block number blockRewardContract: null, channel: null, - lastBlockNumber: 0, lastEpochNumber: 0, network: null, + refreshBlockNumber: 0, // last refresh block number refreshInterval: null, stakingAllowed: false, stakingTokenDefined: false, @@ -60,6 +61,11 @@ export function reducer (state = initialState, action) { }) }) } + case 'BLOCK_CREATED': { + return Object.assign({}, state, { + blockNumber: action.blockNumber + }) + } case 'NETWORK_UPDATED': { return Object.assign({}, state, { network: action.network, @@ -71,14 +77,18 @@ export function reducer (state = initialState, action) { case 'FILTERS_UPDATED': { return Object.assign({}, state, { additionalParams: Object.assign({}, state.additionalParams, { - filterBanned: action.filterBanned, - filterMy: action.filterMy + filterBanned: 'filterBanned' in action ? action.filterBanned : state.additionalParams.filterBanned, + filterMy: 'filterMy' in action ? action.filterMy : state.additionalParams.filterMy }) }) } + case 'PAGE_REFRESHED': { + return Object.assign({}, state, { + refreshBlockNumber: action.refreshBlockNumber + }) + } case 'RECEIVED_UPDATE': { return Object.assign({}, state, { - lastBlockNumber: action.lastBlockNumber, lastEpochNumber: action.lastEpochNumber, stakingAllowed: action.stakingAllowed, stakingTokenDefined: action.stakingTokenDefined, @@ -102,16 +112,26 @@ export function reducer (state = initialState, action) { } } +function refreshPageWrapper(store) { + refreshPage(store) + store.dispatch({ + type: 'PAGE_REFRESHED', + refreshBlockNumber: store.getState().blockNumber + }) + $refreshInformer.hide() +} + function reloadPoolList(msg, store) { store.dispatch({ type: 'RECEIVED_UPDATE', - lastBlockNumber: msg.block_number, lastEpochNumber: msg.epoch_number, stakingAllowed: msg.staking_allowed, stakingTokenDefined: msg.staking_token_defined, validatorSetApplyBlock: msg.validator_set_apply_block }) - refreshPage(store) + if (!msg.dont_refresh_page) { + refreshPageWrapper(store) + } } const elements = { @@ -130,6 +150,7 @@ const elements = { const $stakesPage = $(stakesPageSelector) const $stakesTop = $('[data-selector="stakes-top"]') +const $refreshInformer = $('.refresh-informer', $stakesPage) if ($stakesPage.length) { const store = createAsyncLoadStore(reducer, initialState, 'dataset.identifierPool') connectElements({ store, elements }) @@ -137,8 +158,6 @@ if ($stakesPage.length) { const channel = subscribeChannel('stakes:staking_update') store.dispatch({ type: 'CHANNEL_CONNECTED', channel }) - const $refreshInformer = $('.refresh-informer', $stakesPage) - channel.on('staking_update', msg => { // hide tooltip on tooltip triggering element reloading // due to issues with bootstrap tooltips https://github.com/twbs/bootstrap/issues/13133 @@ -149,23 +168,27 @@ if ($stakesPage.length) { const state = store.getState() - if (!state.account) { + if (msg.account != state.account) { $stakesPage.find('[pool-filter-my]').prop('checked', false); + store.dispatch({ type: 'FILTERS_UPDATED', filterMy: false }) + store.dispatch({ type: 'ACCOUNT_UPDATED', account: msg.account }) } - let lastBlockNumber = state.lastBlockNumber - if ( msg.staking_allowed !== state.stakingAllowed || msg.epoch_number > state.lastEpochNumber || msg.validator_set_apply_block != state.validatorSetApplyBlock || - (state.refreshInterval && msg.block_number >= state.lastBlockNumber + state.refreshInterval) + (state.refreshInterval && msg.block_number >= state.refreshBlockNumber + state.refreshInterval) ) { + if (state.blockNumber == 0) { + // don't refresh the page for the first load + // as it is already refreshed by `initialize` function + msg.dont_refresh_page = true + } reloadPoolList(msg, store) - lastBlockNumber = msg.block_number } - const refreshGap = msg.block_number - lastBlockNumber + const refreshGap = msg.block_number - store.getState().refreshBlockNumber $refreshInformer.find('span').html(refreshGap) if (refreshGap > 0) { $refreshInformer.show() @@ -179,8 +202,11 @@ if ($stakesPage.length) { event.preventDefault() $refreshInformer.hide() $stakesPage.fadeTo(0, 0.5) + delete msg.dont_refresh_page // refresh anyway reloadPoolList(msg, store) }) + + store.dispatch({ type: 'BLOCK_CREATED', blockNumber: msg.block_number }) }) channel.on('contracts', msg => { @@ -199,6 +225,8 @@ if ($stakesPage.length) { }) }) + channel.onError(connectionLost) + $(document.body) .on('click', '.js-pool-info', event => { if (checkForTokenDefinition(store)) { @@ -231,9 +259,9 @@ if ($stakesPage.length) { openWithdrawStakeModal(event, store) } }) - .on('click', '.js-claim-reward', () => { + .on('click', '.js-claim-reward', event => { if (checkForTokenDefinition(store)) { - openClaimRewardModal(store) + openClaimRewardModal(event, store) } }) .on('click', '.js-claim-withdrawal', event => { @@ -246,13 +274,14 @@ if ($stakesPage.length) { .on('change', '[pool-filter-banned]', () => updateFilters(store, 'banned')) .on('change', '[pool-filter-my]', () => updateFilters(store, 'my')) - initializeWeb3(store) + initialize(store) } -function updateFilters (store, filterType) { +function updateFilters(store, filterType) { const filterBanned = $stakesPage.find('[pool-filter-banned]'); const filterMy = $stakesPage.find('[pool-filter-my]'); - if (filterType == 'my' && !store.getState().account) { + const state = store.getState() + if (filterType == 'my' && !state.account) { filterMy.prop('checked', false); openWarningModal('Unauthorized', 'Please login with MetaMask') return @@ -262,39 +291,66 @@ function updateFilters (store, filterType) { filterBanned: filterBanned.prop('checked'), filterMy: filterMy.prop('checked') }) - refreshPage(store) + refreshPageWrapper(store) } -function initializeWeb3 (store) { +function initialize(store) { if (window.ethereum) { const web3 = new Web3(window.ethereum) store.dispatch({ type: 'WEB3_DETECTED', web3 }) - setInterval(async function () { + let timeoutId + + checkNetworkAndAccount() + + async function checkNetworkAndAccount() { const networkId = await web3.eth.net.getId() - if (!store.getState().network || (networkId !== store.getState().network.id)) { + const state = store.getState() + let refresh = false + + if (!state.network || (networkId !== state.network.id)) { setNetwork(networkId, store) + refresh = true } const accounts = await web3.eth.getAccounts() const account = accounts[0] ? accounts[0].toLowerCase() : null - if (account !== store.getState().account) { + if (account !== state.account) { setAccount(account, store) + } else if (refresh) { + refreshPageWrapper(store) } - }, 100) + + clearTimeout(timeoutId) + timeoutId = setTimeout(checkNetworkAndAccount, 100) + } $stakesTop.on('click', '[data-selector="login-button"]', loginByMetamask) + } else { + refreshPageWrapper(store) } } -function setAccount (account, store) { +function setAccount(account, store) { store.dispatch({ type: 'ACCOUNT_UPDATED', account }) - store.getState().channel.push('set_account', account) - refreshPage(store) + + const errorMsg = 'Cannot properly set account due to connection loss. Please, reload the page.' + const $addressField = $('.stakes-top-stats-item-address .stakes-top-stats-value') + $addressField.html('Loading...') + store.getState().channel.push( + 'set_account', account + ).receive('ok', () => { + $addressField.html(account) + refreshPageWrapper(store) + }).receive('error', () => { + openErrorModal('Change account', errorMsg, true) + }).receive('timeout', () => { + openErrorModal('Change account', errorMsg, true) + }) } -function setNetwork (networkId, store) { +function setNetwork(networkId, store) { let network = { id: networkId, authorized: false @@ -307,13 +363,11 @@ function setNetwork (networkId, store) { } store.dispatch({ type: 'NETWORK_UPDATED', network }) - refreshPage(store) } -async function loginByMetamask (event) { +async function loginByMetamask() { event.stopPropagation() event.preventDefault() - try { await window.ethereum.enable() } catch (e) { diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 38a0fb2a36c0..403f839934e0 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -1,15 +1,20 @@ import $ from 'jquery' -import { isModalLocked, lockModal, openErrorModal, openModal, unlockModal } from '../../lib/modals' +import { currentModal, isModalLocked, lockModal, openErrorModal, openModal, unlockModal } from '../../lib/modals' import { displayInputError, hideInputError } from '../../lib/validation' import { isSupportedNetwork } from './utils' -export function openClaimRewardModal(store) { +let status = 'modalClosed' + +export function openClaimRewardModal(event, store) { if (!isSupportedNetwork(store)) return const state = store.getState() const channel = state.channel + $(event.currentTarget).prop('disabled', true) channel.push('render_claim_reward', { preload: true }).receive('ok', msg => { + $(event.currentTarget).prop('disabled', false) + const $modal = $(msg.html) const $closeButton = $modal.find('.close-modal') const $modalBody = $('.modal-body', $modal) @@ -21,6 +26,7 @@ export function openClaimRewardModal(store) { poolsSearchingFinished() }) $modal.on('shown.bs.modal', () => { + status = 'modalOpened' channel.push('render_claim_reward', { }).receive('error', (error) => { poolsSearchingFinished(error.reason) @@ -29,12 +35,10 @@ export function openClaimRewardModal(store) { }) }) $modal.on('hidden.bs.modal', () => { + status = 'modalClosed' $modal.remove() }) function poolsSearchingStarted() { - $closeButton.hide() - lockModal($modal) - const $waitingMessageContainer = $modalBody.find('p') let dotCounter = 0 @@ -50,7 +54,7 @@ export function openClaimRewardModal(store) { } function poolsSearchingFinished(error) { channel.off('claim_reward_pools', ref) - $closeButton.show() + $closeButton.removeClass('hidden') unlockModal($modal) clearInterval(dotCounterInterval) if (error) { @@ -60,14 +64,27 @@ export function openClaimRewardModal(store) { } } - openModal($modal); + openModal($modal, true); }).receive('error', (error) => { + $(event.currentTarget).prop('disabled', false) openErrorModal('Claim Reward', error.reason) }).receive('timeout', () => { + $(event.currentTarget).prop('disabled', false) openErrorModal('Claim Reward', 'Connection timeout') }) } +export function connectionLost() { + const errorMsg = 'Connection with server is lost. Please, reload the page.' + if (status == 'modalOpened') { + status = 'modalClosed' + openErrorModal('Claim Reward', errorMsg, true) + } else if (status == 'recalculation') { + const $recalculateButton = $('button.recalculate', currentModal()) + displayInputError($recalculateButton, errorMsg) + } +} + function onPoolsFound($modal, $modalBody, channel) { const $poolsDropdown = $('select', $modalBody) const $epochChoiceRadio = $('input[name="epoch_choice"]', $modalBody) @@ -154,11 +171,13 @@ function onPoolsFound($modal, $modalBody, channel) { recalcFinished({error: 'Connection timeout'}) }) function recalcStarted() { + status = 'recalculation' hideInputError($recalculateButton) lockUI(true, $modal, $recalculateButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); } function recalcFinished(result) { channel.off('claim_reward_recalculations', ref) + status = 'modalOpened' if (result.error) { displayInputError($recalculateButton, result.error) } else { 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 77e404ee22c1..0f2df9a774f5 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 @@ -39,6 +39,7 @@ defmodule BlockScoutWeb.StakesChannel do "staking_update", %{ block_number: BlockNumber.get_max(), + dont_refresh_page: true, epoch_number: ContractState.get(:epoch_number, 0), staking_allowed: ContractState.get(:staking_allowed, false), staking_token_defined: ContractState.get(:token, nil) != nil, @@ -46,6 +47,8 @@ defmodule BlockScoutWeb.StakesChannel do }, socket ) + + {:reply, :ok, socket} end def handle_in("render_validator_info", %{"address" => staking_address}, socket) do @@ -332,8 +335,15 @@ defmodule BlockScoutWeb.StakesChannel do end def handle_out("staking_update", data, socket) do + dont_refresh_page = case Map.fetch(data, :dont_refresh_page) do + {:ok, value} -> value + _ -> false + end + push(socket, "staking_update", %{ + account: socket.assigns[:account], block_number: data.block_number, + dont_refresh_page: dont_refresh_page, epoch_number: data.epoch_number, staking_allowed: data.staking_allowed, staking_token_defined: data.staking_token_defined, 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 59131fec9f01..38e887542ebe 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 @@ -49,66 +49,72 @@ defmodule BlockScoutWeb.StakesController do # this is called when account in MetaMask is changed on client side # or when UI periodically reloads the pool list (e.g. once per 10 blocks) defp render_template(filter, conn, %{"type" => "JSON"} = params) do - [paging_options: options] = paging_options(params) - - last_index = - params - |> Map.get("position", "0") - |> String.to_integer() - - pools_plus_one = - Chain.staking_pools( - filter, - options, - unless params["account"] == "" do - params["account"] - end, - params["filterBanned"] == "true", - params["filterMy"] == "true" - ) - - {pools, next_page} = split_list_by_page(pools_plus_one) - - next_page_path = - case next_page_params(next_page, pools, params) do - nil -> - nil - - next_page_params -> - updated_page_params = - next_page_params - |> Map.delete("type") - |> Map.put("position", last_index + 1) - - next_page_path(filter, conn, updated_page_params) - end - - average_block_time = AverageBlockTime.average_block_time() - token = ContractState.get(:token, %Token{}) - epoch_number = ContractState.get(:epoch_number, 0) - staking_allowed = ContractState.get(:staking_allowed, false) - - items = - pools - |> Enum.with_index(last_index + 1) - |> Enum.map(fn {%{pool: pool, delegator: delegator}, index} -> - View.render_to_string( - StakesView, - "_rows.html", - token: token, - pool: pool, - delegator: delegator, - index: index, - average_block_time: average_block_time, - pools_type: filter, - buttons: %{ - stake: staking_allowed and stake_allowed?(pool, delegator), - move: staking_allowed and move_allowed?(delegator), - withdraw: staking_allowed and withdraw_allowed?(delegator), - claim: staking_allowed and claim_allowed?(delegator, epoch_number) - } + {items, next_page_path} = if Map.has_key?(params, "filterMy") do + [paging_options: options] = paging_options(params) + + last_index = + params + |> Map.get("position", "0") + |> String.to_integer() + + pools_plus_one = + Chain.staking_pools( + filter, + options, + unless params["account"] == "" do + params["account"] + end, + params["filterBanned"] == "true", + params["filterMy"] == "true" ) - end) + + {pools, next_page} = split_list_by_page(pools_plus_one) + + next_page_path = + case next_page_params(next_page, pools, params) do + nil -> + nil + + next_page_params -> + updated_page_params = + next_page_params + |> Map.delete("type") + |> Map.put("position", last_index + 1) + + next_page_path(filter, conn, updated_page_params) + end + + average_block_time = AverageBlockTime.average_block_time() + token = ContractState.get(:token, %Token{}) + epoch_number = ContractState.get(:epoch_number, 0) + staking_allowed = ContractState.get(:staking_allowed, false) + + items = + pools + |> Enum.with_index(last_index + 1) + |> Enum.map(fn {%{pool: pool, delegator: delegator}, index} -> + View.render_to_string( + StakesView, + "_rows.html", + token: token, + pool: pool, + delegator: delegator, + index: index, + average_block_time: average_block_time, + pools_type: filter, + buttons: %{ + stake: staking_allowed and stake_allowed?(pool, delegator), + move: staking_allowed and move_allowed?(delegator), + withdraw: staking_allowed and withdraw_allowed?(delegator), + claim: staking_allowed and claim_allowed?(delegator, epoch_number) + } + ) + end) + {items, next_page_path} + else + loading_item = View.render_to_string(StakesView, "_rows_loading.html", %{}) + {[loading_item], nil} + end json( conn, diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows_loading.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows_loading.html.eex new file mode 100644 index 000000000000..281c6866c375 --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_rows_loading.html.eex @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 92542329789a..fa4bf457d451 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2350,24 +2350,24 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:251 +#: lib/block_scout_web/channels/stakes_channel.ex:254 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:253 -#: lib/block_scout_web/channels/stakes_channel.ex:288 +#: lib/block_scout_web/channels/stakes_channel.ex:256 +#: lib/block_scout_web/channels/stakes_channel.ex:291 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:585 +#: lib/block_scout_web/channels/stakes_channel.ex:595 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:255 -#: lib/block_scout_web/channels/stakes_channel.ex:290 +#: lib/block_scout_web/channels/stakes_channel.ex:258 +#: lib/block_scout_web/channels/stakes_channel.ex:293 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" @@ -2437,16 +2437,16 @@ msgid "The staking epochs for which the reward could be claimed:" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:284 +#: lib/block_scout_web/channels/stakes_channel.ex:287 msgid "Staking epochs are not specified or not in the allowed range" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:286 +#: lib/block_scout_web/channels/stakes_channel.ex:289 msgid "Unknown pool staking address. Please, contact support" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:282 +#: lib/block_scout_web/channels/stakes_channel.ex:285 msgid "Reward calculating is already in progress for this address" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index f72b1e2a8193..fa4bf457d451 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2350,24 +2350,24 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:251 +#: lib/block_scout_web/channels/stakes_channel.ex:254 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:253 -#: lib/block_scout_web/channels/stakes_channel.ex:288 +#: lib/block_scout_web/channels/stakes_channel.ex:256 +#: lib/block_scout_web/channels/stakes_channel.ex:291 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:585 +#: lib/block_scout_web/channels/stakes_channel.ex:595 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:255 -#: lib/block_scout_web/channels/stakes_channel.ex:290 +#: lib/block_scout_web/channels/stakes_channel.ex:258 +#: lib/block_scout_web/channels/stakes_channel.ex:293 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" @@ -2437,16 +2437,16 @@ msgid "The staking epochs for which the reward could be claimed:" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:284 +#: lib/block_scout_web/channels/stakes_channel.ex:287 msgid "Staking epochs are not specified or not in the allowed range" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:286 +#: lib/block_scout_web/channels/stakes_channel.ex:289 msgid "Unknown pool staking address. Please, contact support" msgstr "" -#, elixir-format, fuzzy -#: lib/block_scout_web/channels/stakes_channel.ex:282 +#, elixir-format +#: lib/block_scout_web/channels/stakes_channel.ex:285 msgid "Reward calculating is already in progress for this address" msgstr "" From ab82f22814062ecd8eed21310b4534f3a2bfb574 Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 24 Dec 2019 06:09:05 +0300 Subject: [PATCH 56/75] Fix staking page refreshing --- .../block_scout_web/assets/js/pages/stakes.js | 143 ++++++++++-------- .../assets/js/pages/stakes/claim_reward.js | 14 +- .../assets/js/pages/stakes/utils.js | 5 +- .../_stakes_stats_item_account.html.eex | 19 ++- .../templates/stakes/_stakes_top.html.eex | 2 +- apps/block_scout_web/priv/gettext/default.pot | 9 +- .../priv/gettext/en/LC_MESSAGES/default.po | 9 +- 7 files changed, 119 insertions(+), 82 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index b73e36a824b5..0f65a1b938b2 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -22,12 +22,12 @@ const stakesPageSelector = '[data-page="stakes"]' export const initialState = { account: null, - blockNumber: 0, // current block number blockRewardContract: null, channel: null, + currentBlockNumber: 0, // current block number lastEpochNumber: 0, network: null, - refreshBlockNumber: 0, // last refresh block number + refreshBlockNumber: 0, // last page refresh block number refreshInterval: null, stakingAllowed: false, stakingTokenDefined: false, @@ -63,7 +63,7 @@ export function reducer (state = initialState, action) { } case 'BLOCK_CREATED': { return Object.assign({}, state, { - blockNumber: action.blockNumber + currentBlockNumber: action.currentBlockNumber }) } case 'NETWORK_UPDATED': { @@ -112,28 +112,6 @@ export function reducer (state = initialState, action) { } } -function refreshPageWrapper(store) { - refreshPage(store) - store.dispatch({ - type: 'PAGE_REFRESHED', - refreshBlockNumber: store.getState().blockNumber - }) - $refreshInformer.hide() -} - -function reloadPoolList(msg, store) { - store.dispatch({ - type: 'RECEIVED_UPDATE', - lastEpochNumber: msg.epoch_number, - stakingAllowed: msg.staking_allowed, - stakingTokenDefined: msg.staking_token_defined, - validatorSetApplyBlock: msg.validator_set_apply_block - }) - if (!msg.dont_refresh_page) { - refreshPageWrapper(store) - } -} - const elements = { '[data-page="stakes"]': { load ($el) { @@ -159,6 +137,12 @@ if ($stakesPage.length) { store.dispatch({ type: 'CHANNEL_CONNECTED', channel }) channel.on('staking_update', msg => { + const state = store.getState() + const firstMsg = (state.currentBlockNumber == 0) + const accountChanged = (msg.account != state.account) + + store.dispatch({ type: 'BLOCK_CREATED', currentBlockNumber: msg.block_number }) + // hide tooltip on tooltip triggering element reloading // due to issues with bootstrap tooltips https://github.com/twbs/bootstrap/issues/13133 const stakesTopTooltipID = $('[aria-describedby]', $stakesTop).attr('aria-describedby') @@ -166,12 +150,9 @@ if ($stakesPage.length) { $stakesTop.html(msg.top_html) - const state = store.getState() - - if (msg.account != state.account) { - $stakesPage.find('[pool-filter-my]').prop('checked', false); - store.dispatch({ type: 'FILTERS_UPDATED', filterMy: false }) + if (accountChanged) { store.dispatch({ type: 'ACCOUNT_UPDATED', account: msg.account }) + resetFilterMy(store) } if ( @@ -180,17 +161,20 @@ if ($stakesPage.length) { msg.validator_set_apply_block != state.validatorSetApplyBlock || (state.refreshInterval && msg.block_number >= state.refreshBlockNumber + state.refreshInterval) ) { - if (state.blockNumber == 0) { - // don't refresh the page for the first load - // as it is already refreshed by `initialize` function + if (firstMsg || accountChanged) { + // Don't refresh the page for the first load + // as it is already refreshed by `initialize` function. + // Also, don't refresh that after reconnect + // as it is already refreshed by `setAccount` function. msg.dont_refresh_page = true } reloadPoolList(msg, store) } - const refreshGap = msg.block_number - store.getState().refreshBlockNumber + const refreshBlockNumber = store.getState().refreshBlockNumber + const refreshGap = msg.block_number - refreshBlockNumber $refreshInformer.find('span').html(refreshGap) - if (refreshGap > 0) { + if (refreshGap > 0 && refreshBlockNumber > 0) { $refreshInformer.show() } else { $refreshInformer.hide() @@ -205,8 +189,6 @@ if ($stakesPage.length) { delete msg.dont_refresh_page // refresh anyway reloadPoolList(msg, store) }) - - store.dispatch({ type: 'BLOCK_CREATED', blockNumber: msg.block_number }) }) channel.on('contracts', msg => { @@ -277,23 +259,6 @@ if ($stakesPage.length) { initialize(store) } -function updateFilters(store, filterType) { - const filterBanned = $stakesPage.find('[pool-filter-banned]'); - const filterMy = $stakesPage.find('[pool-filter-my]'); - const state = store.getState() - if (filterType == 'my' && !state.account) { - filterMy.prop('checked', false); - openWarningModal('Unauthorized', 'Please login with MetaMask') - return - } - store.dispatch({ - type: 'FILTERS_UPDATED', - filterBanned: filterBanned.prop('checked'), - filterMy: filterMy.prop('checked') - }) - refreshPageWrapper(store) -} - function initialize(store) { if (window.ethereum) { const web3 = new Web3(window.ethereum) @@ -332,8 +297,54 @@ function initialize(store) { } } +async function loginByMetamask() { + event.stopPropagation() + event.preventDefault() + try { + await window.ethereum.enable() + } catch (e) { + console.log(e) + console.error('User denied account access') + } +} + +function refreshPageWrapper(store) { + let currentBlockNumber = store.getState().currentBlockNumber + if (!currentBlockNumber) { + currentBlockNumber = $('[data-block-number]', $stakesTop).data('blockNumber') + } + + refreshPage(store) + store.dispatch({ + type: 'PAGE_REFRESHED', + refreshBlockNumber: currentBlockNumber + }) + $refreshInformer.hide() +} + +function reloadPoolList(msg, store) { + store.dispatch({ + type: 'RECEIVED_UPDATE', + lastEpochNumber: msg.epoch_number, + stakingAllowed: msg.staking_allowed, + stakingTokenDefined: msg.staking_token_defined, + validatorSetApplyBlock: msg.validator_set_apply_block + }) + if (!msg.dont_refresh_page) { + refreshPageWrapper(store) + } +} + +function resetFilterMy(store) { + $stakesPage.find('[pool-filter-my]').prop('checked', false); + store.dispatch({ type: 'FILTERS_UPDATED', filterMy: false }) +} + function setAccount(account, store) { store.dispatch({ type: 'ACCOUNT_UPDATED', account }) + if (!account) { + resetFilterMy(store) + } const errorMsg = 'Cannot properly set account due to connection loss. Please, reload the page.' const $addressField = $('.stakes-top-stats-item-address .stakes-top-stats-value') @@ -359,19 +370,25 @@ function setNetwork(networkId, store) { if (allowedNetworkIds.includes(networkId)) { network.authorized = true } else { - openWarningModal('Unauthorized', 'Connect to the xDai Chain for staking.
Instructions') + openWarningModal('Unauthorized', 'Please, connect to the xDai Chain.
Instructions') } store.dispatch({ type: 'NETWORK_UPDATED', network }) } -async function loginByMetamask() { - event.stopPropagation() - event.preventDefault() - try { - await window.ethereum.enable() - } catch (e) { - console.log(e) - console.error('User denied account access') +function updateFilters(store, filterType) { + const filterBanned = $stakesPage.find('[pool-filter-banned]'); + const filterMy = $stakesPage.find('[pool-filter-my]'); + const state = store.getState() + if (filterType == 'my' && !state.account) { + filterMy.prop('checked', false); + openWarningModal('Unauthorized', 'Please login with MetaMask') + return } + store.dispatch({ + type: 'FILTERS_UPDATED', + filterBanned: filterBanned.prop('checked'), + filterMy: filterMy.prop('checked') + }) + refreshPageWrapper(store) } diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 403f839934e0..520edd6b57b8 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -1,14 +1,22 @@ import $ from 'jquery' -import { currentModal, isModalLocked, lockModal, openErrorModal, openModal, unlockModal } from '../../lib/modals' +import { currentModal, isModalLocked, lockModal, openErrorModal, openModal, openWarningModal, unlockModal } from '../../lib/modals' import { displayInputError, hideInputError } from '../../lib/validation' import { isSupportedNetwork } from './utils' let status = 'modalClosed' export function openClaimRewardModal(event, store) { - if (!isSupportedNetwork(store)) return - const state = store.getState() + + if (!state.account) { + openWarningModal('Unauthorized', 'Please login with MetaMask') + return + } + + if (!isSupportedNetwork(store)) { + return + } + const channel = state.channel $(event.currentTarget).prop('disabled', true) diff --git a/apps/block_scout_web/assets/js/pages/stakes/utils.js b/apps/block_scout_web/assets/js/pages/stakes/utils.js index 2d1a97dbbe5e..32fcd7f459e3 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/utils.js +++ b/apps/block_scout_web/assets/js/pages/stakes/utils.js @@ -92,9 +92,10 @@ export function checkForTokenDefinition(store) { } export function isSupportedNetwork(store) { - if (store.getState().network.authorized) { + const state = store.getState() + if (state.network && state.network.authorized) { return true } - openWarningModal('Unauthorized', 'Connect to the xDai Chain for staking.
Instructions') + openWarningModal('Unauthorized', 'Please, connect to the xDai Chain.
Instructions') return false } diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex index ebc79d76492b..3658717852dc 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex @@ -3,7 +3,7 @@ > <%= if @account do %> -
> +
> <%= @account.address %>
@@ -16,15 +16,20 @@ <% end %> - <%= gettext "Balance" %>: - <%= format_token_amount(@account[:balance], @token) %> + <% + balance = format_token_amount(@account[:balance], @token) + stake_amount = format_token_amount(@account[:stake_amount], @token) + ordered_withdraw = format_token_amount(@account[:ordered_withdraw], @token) + %> + : <%= balance %>"> + <%= gettext "Balance" %>: <%= balance %> - <%= gettext "Staked" %>: - <%= format_token_amount(@account[:stake_amount], @token) %> + : <%= stake_amount %>"> + <%= gettext "Staked" %>: <%= stake_amount %> <%= if @account[:ordered_withdraw] && @account[:ordered_withdraw] > 0 do %> - <%= gettext "Ordered" %>: - <%= format_token_amount(@account[:ordered_withdraw], @token) %> + : <%= ordered_withdraw %>"> + <%= gettext "Ordered" %>: <%= ordered_withdraw %> <% end %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_top.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_top.html.eex index d6b19371696b..16e1271cce7b 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_top.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_top.html.eex @@ -1,6 +1,6 @@
-
+
<%= render BlockScoutWeb.StakesView, "_stakes_stats_item.html", title: gettext("Epoch number"), value: @epoch_number %> <%= render BlockScoutWeb.StakesView, "_stakes_stats_item.html", title: gettext("Block number"), value: @block_number %> <%= render BlockScoutWeb.StakesView, "_stakes_stats_item.html", title: gettext("Next epoch in"), value: ngettext("%{blocks} block", "%{blocks} blocks", @epoch_end_in, blocks: @epoch_end_in) %> diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index fa4bf457d451..3af9ecfb7f38 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -165,7 +165,8 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/_balance_card.html.eex:3 -#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:19 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:24 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:25 msgid "Balance" msgstr "" @@ -2080,7 +2081,8 @@ msgid "Order Withdrawal" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:26 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:31 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:32 msgid "Ordered" msgstr "" @@ -2143,7 +2145,8 @@ msgid "Stake placed on a pool is pending for the current stakin msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:22 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:27 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:28 msgid "Staked" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index fa4bf457d451..3af9ecfb7f38 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -165,7 +165,8 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/_balance_card.html.eex:3 -#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:19 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:24 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:25 msgid "Balance" msgstr "" @@ -2080,7 +2081,8 @@ msgid "Order Withdrawal" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:26 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:31 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:32 msgid "Ordered" msgstr "" @@ -2143,7 +2145,8 @@ msgid "Stake placed on a pool is pending for the current stakin msgstr "" #, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:22 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:27 +#: lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex:28 msgid "Staked" msgstr "" From 42d4390cd9f833515bc06f8a23e8f20dd646dfca Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 24 Dec 2019 10:12:44 +0300 Subject: [PATCH 57/75] Comment for timeout and shutdown for stakes_channel --- .../lib/block_scout_web/channels/stakes_channel.ex | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 0f2df9a774f5..1ade13f6ab11 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 @@ -22,7 +22,11 @@ defmodule BlockScoutWeb.StakesChannel do {:ok, %{}, socket} end - def terminate(_, socket) do + # called when socket is closed on a client side + # or socket timeout is reached - see `timeout` option in + # https://hexdocs.pm/phoenix/Phoenix.Endpoint.html#socket/3-websocket-configuration + # apps/block_scout_web/lib/block_scout_web/endpoint.ex + def terminate(_reason, socket) do s = socket.assigns[@claim_reward_long_op] if s != nil do :ets.delete(ContractState, claim_reward_long_op_key(s.staker)) From e8e88ba6d7d7acaec146ba8ef39dfcfb6e02a330 Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 24 Dec 2019 16:46:39 +0300 Subject: [PATCH 58/75] Add claimReward transaction signing --- apps/block_scout_web/assets/js/lib/modals.js | 8 +- .../block_scout_web/assets/js/pages/stakes.js | 6 +- .../assets/js/pages/stakes/claim_reward.js | 107 ++++++++++++++++-- .../channels/stakes_channel.ex | 8 +- .../_stakes_stats_item_account.html.eex | 6 +- apps/block_scout_web/priv/gettext/default.pot | 18 +-- .../priv/gettext/en/LC_MESSAGES/default.po | 18 +-- .../contracts_abi/posdao/StakingAuRa.json | 18 +++ 8 files changed, 144 insertions(+), 45 deletions(-) diff --git a/apps/block_scout_web/assets/js/lib/modals.js b/apps/block_scout_web/assets/js/lib/modals.js index 683d41e7fbe6..599abc657c6f 100644 --- a/apps/block_scout_web/assets/js/lib/modals.js +++ b/apps/block_scout_web/assets/js/lib/modals.js @@ -25,10 +25,6 @@ export function currentModal() { return $currentModal } -export function isModalLocked() { - return modalLocked -} - export function openModal($modal, unclosable) { // Hide all tooltips before showing a modal, // since they are sticking on top of modal @@ -40,9 +36,7 @@ export function openModal($modal, unclosable) { } if ($currentModal) { - if (!unclosable) { - modalLocked = false - } + modalLocked = false $currentModal .one('hidden.bs.modal', () => { diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index 0f65a1b938b2..ea27ca33f2bd 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -16,7 +16,7 @@ import { openWithdrawStakeModal } from './stakes/withdraw_stake' import { openClaimRewardModal, connectionLost } from './stakes/claim_reward' import { openClaimWithdrawalModal } from './stakes/claim_withdrawal' import { checkForTokenDefinition } from './stakes/utils' -import { openWarningModal, openErrorModal } from '../lib/modals' +import { currentModal, openWarningModal, openErrorModal } from '../lib/modals' const stakesPageSelector = '[data-page="stakes"]' @@ -354,6 +354,10 @@ function setAccount(account, store) { ).receive('ok', () => { $addressField.html(account) refreshPageWrapper(store) + const $modal = currentModal() + if ($modal) { + $modal.modal('hide') + } }).receive('error', () => { openErrorModal('Change account', errorMsg, true) }).receive('timeout', () => { diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 520edd6b57b8..5bc17b2d8a68 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -1,5 +1,13 @@ import $ from 'jquery' -import { currentModal, isModalLocked, lockModal, openErrorModal, openModal, openWarningModal, unlockModal } from '../../lib/modals' +import { + currentModal, + lockModal, + openErrorModal, + openModal, + openSuccessModal, + openWarningModal, + unlockModal +} from '../../lib/modals' import { displayInputError, hideInputError } from '../../lib/validation' import { isSupportedNetwork } from './utils' @@ -68,7 +76,7 @@ export function openClaimRewardModal(event, store) { if (error) { openErrorModal('Claim Reward', error) } else { - onPoolsFound($modal, $modalBody, channel) + onPoolsFound($modal, $modalBody, channel, store) } } @@ -93,22 +101,23 @@ export function connectionLost() { } } -function onPoolsFound($modal, $modalBody, channel) { +function onPoolsFound($modal, $modalBody, channel, store) { const $poolsDropdown = $('select', $modalBody) const $epochChoiceRadio = $('input[name="epoch_choice"]', $modalBody) const $specifiedEpochsText = $('input.specified-epochs', $modalBody) const $recalculateButton = $('button.recalculate', $modalBody) + const $submitButton = $('button.submit', $modalBody) let allowedEpochs = [] $poolsDropdown.on('change', () => { - if (isModalLocked()) return false + if (status == 'recalculation' || status == 'claiming') return false const data = $('option:selected', this).data() const tokenRewardSum = data.tokenRewardSum ? data.tokenRewardSum : '0' const nativeRewardSum = data.nativeRewardSum ? data.nativeRewardSum : '0' const gasLimit = data.gasLimit ? data.gasLimit : '0' const $poolInfo = $('.selected-pool-info', $modalBody) - const epochs = data.epochs ? data.epochs : '' + const epochs = data.epochs ? data.epochs.toString() : '' allowedEpochs = expandEpochsToArray(epochs) @@ -125,7 +134,7 @@ function onPoolsFound($modal, $modalBody, channel) { }) $epochChoiceRadio.on('change', () => { - if (isModalLocked()) return false + if (status == 'recalculation' || status == 'claiming') return false if ($('#epoch-choice-all', $modalBody).is(':checked')) { $specifiedEpochsText.addClass('hidden') showButton('submit', $modalBody) @@ -137,9 +146,9 @@ function onPoolsFound($modal, $modalBody, channel) { }) $specifiedEpochsText.on('input', () => { - if (isModalLocked()) return false + if (status == 'recalculation' || status == 'claiming') return false - const filtered = filterSpecifiedEpochs($specifiedEpochsText.val()) + const filtered = filterSpecifiedEpochs($specifiedEpochsText.val()).toString() $specifiedEpochsText.val(filtered) const pointedEpochs = expandEpochsToArray(filtered) @@ -158,11 +167,11 @@ function onPoolsFound($modal, $modalBody, channel) { }) $recalculateButton.on('click', (e) => { - if (isModalLocked()) return false + if (status == 'recalculation' || status == 'claiming') return false e.preventDefault() recalcStarted() - const specifiedEpochs = $specifiedEpochsText.val().replace(/[-|,]$/g, '').trim() + const specifiedEpochs = $specifiedEpochsText.val().toString().replace(/[-|,]$/g, '').trim() $specifiedEpochsText.val(specifiedEpochs) const epochs = expandEpochsToArray(specifiedEpochs).filter(item => allowedEpochs.indexOf(item) != -1) @@ -194,6 +203,76 @@ function onPoolsFound($modal, $modalBody, channel) { lockUI(false, $modal, $recalculateButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); } }) + + $submitButton.on('click', async (e) => { + if (status == 'recalculation' || status == 'claiming') return false + e.preventDefault() + + const specifiedEpochs = $specifiedEpochsText.val().toString().replace(/[-|,]$/g, '').trim() + const epochs = expandEpochsToArray(specifiedEpochs).filter(item => allowedEpochs.indexOf(item) != -1) + const poolStakingAddress = $poolsDropdown.val() + + claimStarted() + + function claimStarted() { + status = 'claiming' + hideInputError($submitButton) + lockUI(true, $modal, $submitButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); + + const gasLimit = parseInt($('#tx-gas-limit', $modalBody).text().replace(/~/g, '').trim(), 10) + const state = store.getState() + const stakingContract = state.stakingContract + const from = state.account + const web3 = state.web3 + + if (gasLimit === NaN) { + claimFinished('Invalid gas limit. Please, contact support.') + } else if (!stakingContract) { + claimFinished('Staking contract is undefined. Please, contact support.') + } else if (!from) { + claimFinished('Your MetaMask account is undefined. Please, contact support.') + } else if (!web3) { + claimFinished('Web3 is undefined. Please, contact support.') + } else if (!poolStakingAddress) { + claimFinished('Pool staking address is undefined. Please, contact support.') + } else { + stakingContract.methods.claimReward(epochs, poolStakingAddress).send({ + from, + gasPrice: 1000000000, + gas: Math.ceil(gasLimit * 1.2) + }, async function(error, txHash) { + if (error) { + claimFinished(error.message) + } else { + try { + let tx + do { + await sleep(5000) + tx = await web3.eth.getTransactionReceipt(txHash) + } while (tx === null) + if (tx.status === true || tx.status === '0x1') { + claimFinished() + } else { + claimFinished('Transaction reverted') + } + } catch (e) { + claimFinished(e.message) + } + } + }) + } + } + function claimFinished(error) { + lockUI(false, $modal, $submitButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); + if (error) { + status = 'modalOpened' + displayInputError($submitButton, error) + } else { + status = 'modalClosed' + openSuccessModal('Success', 'Transaction is confirmed.') + } + } + }) } function lockUI(lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText) { @@ -207,6 +286,10 @@ function lockUI(lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $speci $specifiedEpochsText.prop('disabled', lock) } +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)) +} + function showButton(type, $modalBody, calculations) { const $recalculateButton = $('button.recalculate', $modalBody) const $submitButton = $('button.submit', $modalBody) @@ -236,7 +319,7 @@ function showButton(type, $modalBody, calculations) { } function expandEpochsToArray(epochs) { - let filtered = epochs.replace(/[-|,]$/g, '').trim() + let filtered = epochs.toString().replace(/[-|,]$/g, '').trim() if (filtered == '') return [] let ranges = filtered.split(',') ranges = ranges.map((v) => { @@ -264,7 +347,7 @@ function expandEpochsToArray(epochs) { } function filterSpecifiedEpochs(epochs) { - let filtered = epochs + let filtered = epochs.toString() filtered = filtered.replace(/[^0-9,-]+/g, '') filtered = filtered.replace(/-{2,}/g, '-') filtered = filtered.replace(/,{2,}/g, ',') 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 1ade13f6ab11..7b2f1aa053e7 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 @@ -37,7 +37,7 @@ defmodule BlockScoutWeb.StakesChannel do socket = socket |> assign(:account, account) - |> push_staking_contract() + |> push_contracts() handle_out( "staking_update", @@ -612,8 +612,8 @@ defmodule BlockScoutWeb.StakesChannel do {first, last, next_index} end - defp push_staking_contract(socket) do - if socket.assigns[:contract_sent] do + defp push_contracts(socket) do + if socket.assigns[:contracts_sent] do socket else token = ContractState.get(:token) @@ -625,7 +625,7 @@ defmodule BlockScoutWeb.StakesChannel do token_symbol: token.symbol }) - assign(socket, :contract_sent, true) + assign(socket, :contracts_sent, true) end end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex index 3658717852dc..4c2a2c5d7fd4 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_stats_item_account.html.eex @@ -17,9 +17,9 @@ <% - balance = format_token_amount(@account[:balance], @token) - stake_amount = format_token_amount(@account[:stake_amount], @token) - ordered_withdraw = format_token_amount(@account[:ordered_withdraw], @token) + balance = format_token_amount(@account[:balance], @token, digits: 5, ellipsize: false, symbol: true) + stake_amount = format_token_amount(@account[:stake_amount], @token, digits: 5, ellipsize: false, symbol: true) + ordered_withdraw = format_token_amount(@account[:ordered_withdraw], @token, digits: 5, ellipsize: false, symbol: true) %> : <%= balance %>"> <%= gettext "Balance" %>: <%= balance %> diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 3af9ecfb7f38..55da9028efe8 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2353,24 +2353,24 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:254 +#: lib/block_scout_web/channels/stakes_channel.ex:258 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:256 -#: lib/block_scout_web/channels/stakes_channel.ex:291 +#: lib/block_scout_web/channels/stakes_channel.ex:260 +#: lib/block_scout_web/channels/stakes_channel.ex:295 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:595 +#: lib/block_scout_web/channels/stakes_channel.ex:599 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:258 -#: lib/block_scout_web/channels/stakes_channel.ex:293 +#: lib/block_scout_web/channels/stakes_channel.ex:262 +#: lib/block_scout_web/channels/stakes_channel.ex:297 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" @@ -2440,16 +2440,16 @@ msgid "The staking epochs for which the reward could be claimed:" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:287 +#: lib/block_scout_web/channels/stakes_channel.ex:291 msgid "Staking epochs are not specified or not in the allowed range" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:289 +#: lib/block_scout_web/channels/stakes_channel.ex:293 msgid "Unknown pool staking address. Please, contact support" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:285 +#: lib/block_scout_web/channels/stakes_channel.ex:289 msgid "Reward calculating is already in progress for this address" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 3af9ecfb7f38..55da9028efe8 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2353,24 +2353,24 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:254 +#: lib/block_scout_web/channels/stakes_channel.ex:258 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:256 -#: lib/block_scout_web/channels/stakes_channel.ex:291 +#: lib/block_scout_web/channels/stakes_channel.ex:260 +#: lib/block_scout_web/channels/stakes_channel.ex:295 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:595 +#: lib/block_scout_web/channels/stakes_channel.ex:599 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:258 -#: lib/block_scout_web/channels/stakes_channel.ex:293 +#: lib/block_scout_web/channels/stakes_channel.ex:262 +#: lib/block_scout_web/channels/stakes_channel.ex:297 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" @@ -2440,16 +2440,16 @@ msgid "The staking epochs for which the reward could be claimed:" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:287 +#: lib/block_scout_web/channels/stakes_channel.ex:291 msgid "Staking epochs are not specified or not in the allowed range" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:289 +#: lib/block_scout_web/channels/stakes_channel.ex:293 msgid "Unknown pool staking address. Please, contact support" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:285 +#: lib/block_scout_web/channels/stakes_channel.ex:289 msgid "Reward calculating is already in progress for this address" msgstr "" diff --git a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json index 98b955b34f57..d8ff094c5106 100644 --- a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json @@ -470,6 +470,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_stakingEpochs", + "type": "uint256[]" + }, + { + "name": "_poolStakingAddress", + "type": "address" + } + ], + "name": "claimReward", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ From 30ac2f2e520b85284d8a7c34b13651e93164721d Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 25 Dec 2019 16:07:43 +0300 Subject: [PATCH 59/75] Claim Reward dialog UI improvements --- .../stakes/_modal_claim_reward.scss | 17 +++--- apps/block_scout_web/assets/js/lib/modals.js | 17 +++--- .../block_scout_web/assets/js/pages/stakes.js | 14 +++-- .../assets/js/pages/stakes/claim_reward.js | 53 ++++++++++++------- .../channels/stakes_channel.ex | 4 +- ...stakes_modal_claim_reward_content.html.eex | 16 +++--- apps/block_scout_web/priv/gettext/default.pot | 20 +++---- .../priv/gettext/en/LC_MESSAGES/default.po | 20 +++---- 8 files changed, 91 insertions(+), 70 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/stakes/_modal_claim_reward.scss b/apps/block_scout_web/assets/css/components/stakes/_modal_claim_reward.scss index dc32cf9ea51d..aabbbc8291e9 100644 --- a/apps/block_scout_web/assets/css/components/stakes/_modal_claim_reward.scss +++ b/apps/block_scout_web/assets/css/components/stakes/_modal_claim_reward.scss @@ -20,20 +20,17 @@ &.m-b-0 { margin-bottom: 0; } - - &.left { - width: 49%; - float: left; - } - - &.right { - width: 49%; - float: right; - } } textarea { background: #fff!important; height: 38px; } + + .amounts { + display: grid; + grid-template-rows: 1fr; + grid-template-columns: 1fr 80px; + grid-gap: 2vw; + } } diff --git a/apps/block_scout_web/assets/js/lib/modals.js b/apps/block_scout_web/assets/js/lib/modals.js index 599abc657c6f..bff2f6bd4330 100644 --- a/apps/block_scout_web/assets/js/lib/modals.js +++ b/apps/block_scout_web/assets/js/lib/modals.js @@ -56,7 +56,7 @@ export function openModal($modal, unclosable) { } } -export function lockModal ($modal, $submitButton = null) { +export function lockModal($modal, $submitButton = null, spinnerText = '') { $modal.find('.close-modal').attr('disabled', true) const $button = $submitButton || $modal.find('.btn-add-full') @@ -66,18 +66,19 @@ export function lockModal ($modal, $submitButton = null) { .attr('disabled', true) const $span = $('span', $button) + const waitHtml = spinner + (spinnerText ? ` ${spinnerText}` : '') if ($span.length) { $('svg', $button).hide() - $span.html(spinner) + $span.html(waitHtml) } else { - $button.html(spinner) + $button.html(waitHtml) } modalLocked = true } -export function unlockModal ($modal, $submitButton = null) { +export function unlockModal($modal, $submitButton = null) { $modal.find('.close-modal').attr('disabled', false) const $button = $submitButton || $modal.find('.btn-add-full') @@ -96,28 +97,28 @@ export function unlockModal ($modal, $submitButton = null) { modalLocked = false } -export function openErrorModal (title, text, unclosable) { +export function openErrorModal(title, text, unclosable) { const $modal = $('#errorStatusModal') $modal.find('.modal-status-title').text(title) $modal.find('.modal-status-text').html(text) openModal($modal, unclosable) } -export function openWarningModal (title, text) { +export function openWarningModal(title, text) { const $modal = $('#warningStatusModal') $modal.find('.modal-status-title').text(title) $modal.find('.modal-status-text').html(text) openModal($modal) } -export function openSuccessModal (title, text) { +export function openSuccessModal(title, text) { const $modal = $('#successStatusModal') $modal.find('.modal-status-title').text(title) $modal.find('.modal-status-text').text(text) openModal($modal) } -export function openQuestionModal (title, text, acceptCallback = null, exceptCallback = null, acceptText = 'Yes', exceptText = 'No') { +export function openQuestionModal(title, text, acceptCallback = null, exceptCallback = null, acceptText = 'Yes', exceptText = 'No') { const $modal = $('#questionStatusModal') $modal.find('.modal-status-title').text(title) diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index ea27ca33f2bd..3b46cbb9c913 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -202,7 +202,7 @@ if ($stakesPage.length) { type: 'RECEIVED_CONTRACTS', stakingContract, blockRewardContract, - tokenDecimals: parseInt(msg.token_decimals), + tokenDecimals: parseInt(msg.token_decimals, 10), tokenSymbol: msg.token_symbol }) }) @@ -259,6 +259,11 @@ if ($stakesPage.length) { initialize(store) } +function hideCurrentModal() { + const $modal = currentModal() + if ($modal) $modal.modal('hide') +} + function initialize(store) { if (window.ethereum) { const web3 = new Web3(window.ethereum) @@ -354,10 +359,7 @@ function setAccount(account, store) { ).receive('ok', () => { $addressField.html(account) refreshPageWrapper(store) - const $modal = currentModal() - if ($modal) { - $modal.modal('hide') - } + hideCurrentModal() }).receive('error', () => { openErrorModal('Change account', errorMsg, true) }).receive('timeout', () => { @@ -366,6 +368,8 @@ function setAccount(account, store) { } function setNetwork(networkId, store) { + hideCurrentModal() + let network = { id: networkId, authorized: false diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 5bc17b2d8a68..8bc8c5c22183 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -123,9 +123,9 @@ function onPoolsFound($modal, $modalBody, channel, store) { $poolsDropdown.blur() $('textarea', $poolInfo).val(epochs) - $('#token-reward-sum', $poolInfo).html(tokenRewardSum).data('default', tokenRewardSum) - $('#native-reward-sum', $poolInfo).html(nativeRewardSum).data('default', nativeRewardSum) - $('#tx-gas-limit', $poolInfo).html('~' + gasLimit).data('default', gasLimit) + $('#token-reward-sum', $poolInfo).text(tokenRewardSum).data('default', tokenRewardSum) + $('#native-reward-sum', $poolInfo).text(nativeRewardSum).data('default', nativeRewardSum) + $('#tx-gas-limit', $poolInfo).text('~' + gasLimit).data('default', gasLimit) $('#epoch-choice-all', $poolInfo).click() $specifiedEpochsText.val('') $poolInfo.removeClass('hidden') @@ -217,7 +217,15 @@ function onPoolsFound($modal, $modalBody, channel, store) { function claimStarted() { status = 'claiming' hideInputError($submitButton) - lockUI(true, $modal, $submitButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); + lockUI( + true, + $modal, + $submitButton, + $poolsDropdown, + $epochChoiceRadio, + $specifiedEpochsText, + 'Please, sign transaction in MetaMask' + ) const gasLimit = parseInt($('#tx-gas-limit', $modalBody).text().replace(/~/g, '').trim(), 10) const state = store.getState() @@ -238,22 +246,31 @@ function onPoolsFound($modal, $modalBody, channel, store) { } else { stakingContract.methods.claimReward(epochs, poolStakingAddress).send({ from, - gasPrice: 1000000000, - gas: Math.ceil(gasLimit * 1.2) + gasPrice: web3.utils.toWei('1', 'gwei'), + gas: Math.ceil(gasLimit * 1.2) // +20% reserve to ensure enough gas }, async function(error, txHash) { if (error) { claimFinished(error.message) } else { try { let tx + let currentBlockNumber + const maxWaitBlocks = 6 + const startBlockNumber = (await web3.eth.getBlockNumber()) - 0 + const finishBlockNumber = startBlockNumber + maxWaitBlocks do { - await sleep(5000) + await sleep(5) // seconds tx = await web3.eth.getTransactionReceipt(txHash) - } while (tx === null) - if (tx.status === true || tx.status === '0x1') { - claimFinished() + currentBlockNumber = await web3.eth.getBlockNumber() + } while (tx === null && currentBlockNumber <= finishBlockNumber) + if (tx) { + if (tx.status === true || tx.status === '0x1') { + claimFinished() + } else { + claimFinished('Transaction reverted') + } } else { - claimFinished('Transaction reverted') + claimFinished(`Your transaction was not mined in ${maxWaitBlocks} blocks. Please, try again with the increased gas price or fixed nonce (use Reset Account feature of MetaMask).`) } } catch (e) { claimFinished(e.message) @@ -275,9 +292,9 @@ function onPoolsFound($modal, $modalBody, channel, store) { }) } -function lockUI(lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText) { +function lockUI(lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText, spinnerText) { if (lock) { - lockModal($modal, $button) + lockModal($modal, $button, spinnerText) } else { unlockModal($modal, $button) } @@ -286,8 +303,8 @@ function lockUI(lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $speci $specifiedEpochsText.prop('disabled', lock) } -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)) +function sleep(seconds) { + return new Promise(resolve => setTimeout(resolve, seconds * 1000)) } function showButton(type, $modalBody, calculations) { @@ -325,8 +342,8 @@ function expandEpochsToArray(epochs) { ranges = ranges.map((v) => { if (v.indexOf('-') > -1) { v = v.split('-') - v[0] = parseInt(v[0]) - v[1] = parseInt(v[1]) + v[0] = parseInt(v[0], 10) + v[1] = parseInt(v[1], 10) v.sort((a, b) => a - b) const min = v[0] const max = v[1] @@ -336,7 +353,7 @@ function expandEpochsToArray(epochs) { } return expanded } else { - return parseInt(v) + return parseInt(v, 10) } }) ranges = ranges.reduce((acc, val) => acc.concat(val), []) // similar to ranges.flat() 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 7b2f1aa053e7..43124c2db394 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 @@ -527,8 +527,8 @@ defmodule BlockScoutWeb.StakesChannel do coin = %Token{symbol: Explorer.coin(), decimals: Decimal.new(18)} push(socket, "claim_reward_recalculations", %{ - token_reward_sum: StakesHelpers.format_token_amount(amounts.token_reward_sum, token, digits: 5, ellipsize: false, symbol: false), - native_reward_sum: StakesHelpers.format_token_amount(amounts.native_reward_sum, coin, digits: 5, ellipsize: false, symbol: false), + token_reward_sum: StakesHelpers.format_token_amount(amounts.token_reward_sum, token, digits: token.decimals, ellipsize: false, symbol: false), + native_reward_sum: StakesHelpers.format_token_amount(amounts.native_reward_sum, coin, digits: coin.decimals, ellipsize: false, symbol: false), gas_limit: gas_limit, error: error }) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex index 4b7c48d0083e..ea8e75e93f0d 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex @@ -6,16 +6,18 @@ <%= for {pool_staking_address, data} <- @pools do %> <% - token_reward_sum = format_token_amount(data.token_reward_sum, @token, digits: 5, ellipsize: false, symbol: false) - native_reward_sum = format_token_amount(data.native_reward_sum, @coin, digits: 5, ellipsize: false, symbol: false) + token_reward_sum = format_token_amount(data.token_reward_sum, @token, digits: @token.decimals, ellipsize: false, symbol: false) + token_reward_sum_short = format_token_amount(data.token_reward_sum, @token, digits: 5, ellipsize: false, symbol: false) + native_reward_sum = format_token_amount(data.native_reward_sum, @coin, digits: @coin.decimals, ellipsize: false, symbol: false) + native_reward_sum_short = format_token_amount(data.native_reward_sum, @coin, digits: 5, ellipsize: false, symbol: false) %> @@ -36,13 +38,13 @@

-
-

+

+

<%= gettext("You will receive:") %>
<%= @token.symbol %>
<%= @coin.symbol %>

-

+

<%= gettext("Tx Gas Limit:") %>

diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 55da9028efe8..ada0fe7d1327 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2342,7 +2342,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:52 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:54 #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 msgid "Claim Reward" msgstr "" @@ -2376,25 +2376,25 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:62 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:64 msgid "Unable to find any pools you could claim a reward from." msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:33 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:35 msgid "Claim for" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:37 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:39 msgid "Epochs range(s) or enum, e.g.: 5-9,23-27,47,50" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:46 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:48 msgid "Tx Gas Limit:" msgstr "" @@ -2406,19 +2406,19 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:41 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:43 msgid "You will receive:" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:34 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:36 msgid "all epochs" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:35 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:37 msgid "specified epochs only" msgstr "" @@ -2429,13 +2429,13 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:51 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:53 msgid "Recalculate" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:29 msgid "The staking epochs for which the reward could be claimed:" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 55da9028efe8..ada0fe7d1327 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2342,7 +2342,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:6 -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:52 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:54 #: lib/block_scout_web/templates/stakes/_stakes_top.html.eex:32 msgid "Claim Reward" msgstr "" @@ -2376,25 +2376,25 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:62 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:64 msgid "Unable to find any pools you could claim a reward from." msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:33 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:35 msgid "Claim for" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:37 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:39 msgid "Epochs range(s) or enum, e.g.: 5-9,23-27,47,50" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:46 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:48 msgid "Tx Gas Limit:" msgstr "" @@ -2406,19 +2406,19 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:41 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:43 msgid "You will receive:" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:34 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:36 msgid "all epochs" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:35 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:37 msgid "specified epochs only" msgstr "" @@ -2429,13 +2429,13 @@ msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:51 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:53 msgid "Recalculate" msgstr "" #, elixir-format #: -#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:27 +#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward_content.html.eex:29 msgid "The staking epochs for which the reward could be claimed:" msgstr "" From 14c1d07dae6ceb5604b598f68435ae4a2880fce5 Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 14 Jan 2020 15:38:49 +0300 Subject: [PATCH 60/75] Add creationMethod to entry_to_elixir --- .../lib/ethereum_jsonrpc/parity/trace/action.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/trace/action.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/trace/action.ex index 4b3442b9fe4b..4785c0d0cf56 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/trace/action.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/trace/action.ex @@ -45,7 +45,7 @@ defmodule EthereumJSONRPC.Parity.Trace.Action do end defp entry_to_elixir({key, value} = entry) - when key in ~w(address callType from init input refundAddress to) and is_binary(value), + when key in ~w(address callType from init input refundAddress to creationMethod) and is_binary(value), do: entry defp entry_to_elixir({key, quantity}) when key in ~w(balance gas value) do From 3198380a462daed0944c9924c8402470c8306232 Mon Sep 17 00:00:00 2001 From: Vadim Date: Mon, 27 Jan 2020 16:50:33 +0300 Subject: [PATCH 61/75] Split eth_getLogs requests --- .../channels/stakes_channel.ex | 52 ++++++++++++------- 1 file changed, 33 insertions(+), 19 deletions(-) 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 43124c2db394..c4d9c1f8f807 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 @@ -549,25 +549,39 @@ defmodule BlockScoutWeb.StakesChannel do end defp find_claim_reward_pools_by_logs(staking_contract_address, topics, json_rpc_named_arguments) 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"], 1)) - end)) - {nil, pools} - {:error, reason} -> - {error_reason_to_string(reason), []} - end + latest_block = BlockNumber.get_max() + split_by = 500 # must be less than 1000 + + iterations = 0..trunc(ceil(latest_block / split_by) - 1) + Enum.reduce(iterations, {nil, []}, fn i, acc -> + {acc_error, acc_pools} = acc + if acc_error do + {acc_error, []} + else + from = i * split_by + 1 + to = (i + 1) * split_by + to = if to > latest_block, do: latest_block, else: to + result = EthereumJSONRPC.request(%{ + id: 0, + method: "eth_getLogs", + params: [%{ + fromBlock: "0x" <> Integer.to_string(from, 16), + toBlock: "0x" <> Integer.to_string(to, 16), + address: staking_contract_address, + topics: topics + }] + }) |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments) + case result do + {:ok, response} -> + pools = Enum.uniq(acc_pools ++ Enum.map(response, fn event -> + truncate_address(Enum.at(event["topics"], 1)) + end)) + {acc_error, pools} + {:error, reason} -> + {error_reason_to_string(reason), []} + end + end + end) end defp address_pad_to_64(address) do From 1cdc2341e0d39bfd99346939de6b67520bcf1ffb Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 30 Jan 2020 17:17:03 +0300 Subject: [PATCH 62/75] Replace eth_getLogs with public getter --- .../channels/stakes_channel.ex | 200 +++++++----------- .../templates/stakes/_stakes_title.html.eex | 2 +- apps/block_scout_web/priv/gettext/default.pot | 12 +- .../priv/gettext/en/LC_MESSAGES/default.po | 12 +- .../lib/explorer/staking/contract_reader.ex | 12 ++ .../contracts_abi/posdao/StakingAuRa.json | 46 ++++ 6 files changed, 145 insertions(+), 139 deletions(-) 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 c4d9c1f8f807..60c943ef7040 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 @@ -361,110 +361,102 @@ defmodule BlockScoutWeb.StakesChannel do def find_claim_reward_pools(socket, staker, staking_contract_address) do :ets.insert(ContractState, {claim_reward_long_op_key(staker), true}) try do - staker_padded = address_pad_to_64(staker) 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) - - # 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, # don't filter by `toPoolStakingAddress` - "0x" <> staker_padded # filter by `staker` - ], json_rpc_named_arguments) + staking_contract = ContractState.get(:staking_contract) + + responses = + ContractReader.get_staker_pools_length_request(staker) + |> ContractReader.perform_requests(%{staking: staking_contract.address}, staking_contract.abi) + staker_pools_length = responses[:length] + + chunk_size = 100 + pools = if staker_pools_length > 0 do + chunks = 0..trunc(ceil(staker_pools_length / chunk_size) - 1) + Enum.reduce(chunks, [], fn i, acc -> + responses = + ContractReader.get_staker_pools_request(staker, i * chunk_size, chunk_size) + |> ContractReader.perform_requests(%{staking: staking_contract.address}, staking_contract.abi) + acc ++ Enum.map(responses[:pools], fn pool_staking_address -> + address_bytes_to_string(pool_staking_address) + end) + end) else - {error, []} + [] end - {error, pools} = if error == nil do - pools = Enum.uniq(pools_staked_into ++ pools_moved_into) + pools_amounts = Enum.map(pools, fn pool_staking_address -> + ContractReader.call_get_reward_amount( + staking_contract_address, + [], + pool_staking_address, + staker, + json_rpc_named_arguments + ) + end) - pools_amounts = Enum.map(pools, fn pool_staking_address -> - ContractReader.call_get_reward_amount( + error = Enum.find_value(pools_amounts, fn result -> + case result do + {:error, reason} -> error_reason_to_string(reason) + _ -> nil + end + end) + + {error, pools} = if error != nil do + {error, %{}} + else + block_reward_contract = ContractState.get(:block_reward_contract) + + pools = + pools_amounts + |> Enum.map(fn {_, amounts} -> amounts end) + |> Enum.zip(pools) + |> Enum.filter(fn {amounts, _} -> amounts.token_reward_sum > 0 || amounts.native_reward_sum > 0 end) + |> Enum.map(fn {amounts, pool_staking_address} -> + responses = + ContractReader.epochs_to_claim_reward_from_request(pool_staking_address, staker) + |> ContractReader.perform_requests(%{block_reward: block_reward_contract.address}, block_reward_contract.abi) + + epochs = + array_to_ranges(responses[:epochs]) + |> Enum.map(fn {first, last} -> + Integer.to_string(first) <> (if first != last, do: "-" <> Integer.to_string(last), else: "") + end) + data = Map.put(amounts, :epochs, Enum.join(epochs, ",")) + + {data, pool_staking_address} + end) + |> Enum.filter(fn {data, _} -> data.epochs != "" end) + + pools_gas_estimates = Enum.map(pools, fn {_data, pool_staking_address} -> + result = ContractReader.claim_reward_estimate_gas( staking_contract_address, [], pool_staking_address, staker, json_rpc_named_arguments ) + {pool_staking_address, result} end) - error = Enum.find_value(pools_amounts, fn result -> + error = Enum.find_value(pools_gas_estimates, fn {_, result} -> case result do {:error, reason} -> error_reason_to_string(reason) _ -> nil end end) - {error, pools} = if error != nil do - {error, %{}} - else - block_reward_contract = ContractState.get(:block_reward_contract) - - pools = - pools_amounts - |> Enum.map(fn {_, amounts} -> amounts end) - |> Enum.zip(pools) - |> Enum.filter(fn {amounts, _} -> amounts.token_reward_sum > 0 || amounts.native_reward_sum > 0 end) - |> Enum.map(fn {amounts, pool_staking_address} -> - responses = - ContractReader.epochs_to_claim_reward_from_request(pool_staking_address, staker) - |> ContractReader.perform_requests(%{block_reward: block_reward_contract.address}, block_reward_contract.abi) - - epochs = - array_to_ranges(responses[:epochs]) - |> Enum.map(fn {first, last} -> - Integer.to_string(first) <> (if first != last, do: "-" <> Integer.to_string(last), else: "") - end) - data = Map.put(amounts, :epochs, Enum.join(epochs, ",")) - - {data, pool_staking_address} - end) - |> Enum.filter(fn {data, _} -> data.epochs != "" end) - - pools_gas_estimates = Enum.map(pools, fn {_data, pool_staking_address} -> - result = ContractReader.claim_reward_estimate_gas( - staking_contract_address, - [], - pool_staking_address, - staker, - json_rpc_named_arguments - ) - {pool_staking_address, result} + pools = if error == nil do + pools_gas_estimates = Map.new(pools_gas_estimates) + Map.new(pools, fn {data, pool_staking_address} -> + {:ok, estimate} = pools_gas_estimates[pool_staking_address] + data = Map.put(data, :gas_estimate, estimate) + {pool_staking_address, data} end) - - error = Enum.find_value(pools_gas_estimates, fn {_, result} -> - case result do - {:error, reason} -> error_reason_to_string(reason) - _ -> nil - end - end) - - pools = if error == nil do - pools_gas_estimates = Map.new(pools_gas_estimates) - Map.new(pools, fn {data, pool_staking_address} -> - {:ok, estimate} = pools_gas_estimates[pool_staking_address] - data = Map.put(data, :gas_estimate, estimate) - {pool_staking_address, data} - end) - else - %{} - end - - {error, pools} + else + %{} end {error, pools} - else - {error, %{}} end html = View.render_to_string( @@ -548,47 +540,7 @@ defmodule BlockScoutWeb.StakesChannel do end end - defp find_claim_reward_pools_by_logs(staking_contract_address, topics, json_rpc_named_arguments) do - latest_block = BlockNumber.get_max() - split_by = 500 # must be less than 1000 - - iterations = 0..trunc(ceil(latest_block / split_by) - 1) - Enum.reduce(iterations, {nil, []}, fn i, acc -> - {acc_error, acc_pools} = acc - if acc_error do - {acc_error, []} - else - from = i * split_by + 1 - to = (i + 1) * split_by - to = if to > latest_block, do: latest_block, else: to - result = EthereumJSONRPC.request(%{ - id: 0, - method: "eth_getLogs", - params: [%{ - fromBlock: "0x" <> Integer.to_string(from, 16), - toBlock: "0x" <> Integer.to_string(to, 16), - address: staking_contract_address, - topics: topics - }] - }) |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments) - case result do - {:ok, response} -> - pools = Enum.uniq(acc_pools ++ Enum.map(response, fn event -> - truncate_address(Enum.at(event["topics"], 1)) - end)) - {acc_error, pools} - {:error, reason} -> - {error_reason_to_string(reason), []} - end - end - end) - end - - defp address_pad_to_64(address) do - address - |> String.replace_leading("0x", "") - |> String.pad_leading(64, ["0"]) - end + defp address_bytes_to_string(hash), do: "0x" <> Base.encode16(hash, case: :lower) defp array_to_ranges(numbers, prev_ranges \\ []) do length = Enum.count(numbers) @@ -647,8 +599,4 @@ defmodule BlockScoutWeb.StakesChannel do staker = if staker == nil, do: "", else: staker Atom.to_string(@claim_reward_long_op) <> "_" <> staker end - - defp truncate_address("0x000000000000000000000000" <> truncated_address) do - "0x#{truncated_address}" - end end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_title.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_title.html.eex index 6b1d71401fd2..40342d6967be 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_title.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_title.html.eex @@ -11,7 +11,7 @@
-
<%= gettext("Show only those I staked into") %>
+
<%= gettext("Show only those I have stake in") %>
\ No newline at end of file diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index ada0fe7d1327..b83cb656b6cf 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2119,11 +2119,6 @@ msgstr "" msgid "Show banned only" msgstr "" -#, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_title.html.eex:14 -msgid "Show only those I staked into" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_stake.html.eex:7 msgid "Stake" @@ -2364,7 +2359,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:599 +#: lib/block_scout_web/channels/stakes_channel.ex:565 msgid "JSON RPC error" msgstr "" @@ -2453,3 +2448,8 @@ msgstr "" #: lib/block_scout_web/channels/stakes_channel.ex:289 msgid "Reward calculating is already in progress for this address" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_title.html.eex:14 +msgid "Show only those I have stake in" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index ada0fe7d1327..b83cb656b6cf 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2119,11 +2119,6 @@ msgstr "" msgid "Show banned only" msgstr "" -#, elixir-format -#: lib/block_scout_web/templates/stakes/_stakes_title.html.eex:14 -msgid "Show only those I staked into" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_stake.html.eex:7 msgid "Stake" @@ -2364,7 +2359,7 @@ msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:599 +#: lib/block_scout_web/channels/stakes_channel.ex:565 msgid "JSON RPC error" msgstr "" @@ -2453,3 +2448,8 @@ msgstr "" #: lib/block_scout_web/channels/stakes_channel.ex:289 msgid "Reward calculating is already in progress for this address" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/stakes/_stakes_title.html.eex:14 +msgid "Show only those I have stake in" +msgstr "" diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index f108b51a0e0a..0041d3385076 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -162,6 +162,18 @@ defmodule Explorer.Staking.ContractReader do ] end + def get_staker_pools_request(staker, offset, length) do + [ + pools: {:staking, "getStakerPools", [staker, offset, length]} + ] + end + + def get_staker_pools_length_request(staker) do + [ + length: {:staking, "getStakerPoolsLength", [staker]} + ] + end + def pool_staking_requests(staking_address, block_number) do [ active_delegators: active_delegators_request(staking_address, block_number)[:active_delegators], diff --git a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json index d8ff094c5106..bf9cebbb5820 100644 --- a/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/StakingAuRa.json @@ -36,6 +36,52 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "name": "_staker", + "type": "address" + }, + { + "name": "_offset", + "type": "uint256" + }, + { + "name": "_length", + "type": "uint256" + } + ], + "name": "getStakerPools", + "outputs": [ + { + "name": "result", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_staker", + "type": "address" + } + ], + "name": "getStakerPoolsLength", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ From 1ce8b3a0457998dbba959d35032769431bdeaaa6 Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 20 Feb 2020 12:17:42 +0300 Subject: [PATCH 63/75] Rename bridge fee to bridge reward --- .../priv/contracts_abi/posdao/BlockRewardAuRa.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json index 8e74b4ddc9ab..87b535f05ffb 100644 --- a/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json +++ b/apps/explorer/priv/contracts_abi/posdao/BlockRewardAuRa.json @@ -25,7 +25,7 @@ { "constant": true, "inputs": [], - "name": "bridgeTokenFee", + "name": "bridgeTokenReward", "outputs": [ { "name": "", @@ -240,7 +240,7 @@ { "constant": true, "inputs": [], - "name": "bridgeNativeFee", + "name": "bridgeNativeReward", "outputs": [ { "name": "", @@ -321,7 +321,7 @@ "type": "uint256" } ], - "name": "addBridgeNativeFeeReceivers", + "name": "addBridgeNativeRewardReceivers", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -335,7 +335,7 @@ "type": "uint256" } ], - "name": "addBridgeTokenFeeReceivers", + "name": "addBridgeTokenRewardReceivers", "outputs": [], "payable": false, "stateMutability": "nonpayable", From dc6708b256ce7f8194b8c23ae603f5ec03c91dc2 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 1 Apr 2020 22:38:32 +0300 Subject: [PATCH 64/75] Fix tests: mix format and mix credo --- apps/block_scout_web/config/config.exs | 3 +- .../channels/stakes_channel.ex | 455 +++++++---- .../controllers/stakes_controller.ex | 132 ++-- apps/explorer/lib/explorer/chain.ex | 39 +- apps/explorer/lib/explorer/chain/import.ex | 6 +- .../chain/import/runner/staking_pools.ex | 68 +- .../import/runner/staking_pools_delegators.ex | 34 +- .../lib/explorer/staking/contract_reader.ex | 116 ++- .../lib/explorer/staking/contract_state.ex | 741 +++++++++++------- .../explorer/staking/stake_snapshotting.ex | 43 +- ...0190807111216_remove_duplicate_indexes.exs | 4 +- ...add_index_for_snapshotted_stake_amount.exs | 2 +- 12 files changed, 1015 insertions(+), 628 deletions(-) diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs index 6598c4e25774..1e86f9b96cd0 100644 --- a/apps/block_scout_web/config/config.exs +++ b/apps/block_scout_web/config/config.exs @@ -21,7 +21,8 @@ config :block_scout_web, BlockScoutWeb.Chain, logo_footer: System.get_env("LOGO_FOOTER"), has_emission_funds: false, staking_enabled: not is_nil(System.get_env("POS_STAKING_CONTRACT")), - staking_pool_list_refresh_interval: 5 # how often (in blocks) the list of pools should autorefresh in UI (zero turns off autorefreshing) + # how often (in blocks) the list of pools should autorefresh in UI (zero turns off autorefreshing) + staking_pool_list_refresh_interval: 5 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 60c943ef7040..62ef1a1daad9 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 @@ -28,6 +28,7 @@ defmodule BlockScoutWeb.StakesChannel do # apps/block_scout_web/lib/block_scout_web/endpoint.ex def terminate(_reason, socket) do s = socket.assigns[@claim_reward_long_op] + if s != nil do :ets.delete(ContractState, claim_reward_long_op_key(s.staker)) end @@ -251,55 +252,60 @@ defmodule BlockScoutWeb.StakesChannel do def handle_in("render_claim_reward", data, socket) do staker = socket.assigns[:account] - staking_contract_address = try do ContractState.get(:staking_contract).address after end - - cond do - claim_reward_long_op_active(socket) == true -> - {:reply, {:error, %{reason: gettext("Pools searching is already in progress for this address")}}, socket} - staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" -> - {: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 -> - result = if data["preload"] do - %{ - html: View.render_to_string(StakesView, "_stakes_modal_claim_reward.html", %{}), - socket: socket - } - else - task = Task.async(__MODULE__, :find_claim_reward_pools, [socket, staker, staking_contract_address]) - %{ - html: "OK", - socket: assign(socket, @claim_reward_long_op, %{task: task, staker: staker}) - } - end - {:reply, {:ok, %{html: result.html}}, result.socket} - end + staking_contract_address = + try do + ContractState.get(:staking_contract).address + after + end + + empty_staker = staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" + + empty_staking_contract_address = + staking_contract_address == nil || staking_contract_address == "" || + staking_contract_address == "0x0000000000000000000000000000000000000000" + + handle_in_render_claim_reward_result( + socket, + data, + staker, + staking_contract_address, + empty_staker, + empty_staking_contract_address + ) end def handle_in("recalc_claim_reward", data, socket) do epochs = data["epochs"] pool_staking_address = data["pool_staking_address"] staker = socket.assigns[:account] - staking_contract_address = try do ContractState.get(:staking_contract).address after end - - cond do - claim_reward_long_op_active(socket) == true -> - {:reply, {:error, %{reason: gettext("Reward calculating is already in progress for this address")}}, socket} - Enum.count(epochs) == 0 -> - {:reply, {:error, %{reason: gettext("Staking epochs are not specified or not in the allowed range")}}, socket} - pool_staking_address == nil || pool_staking_address == "" || pool_staking_address == "0x0000000000000000000000000000000000000000" -> - {:reply, {:error, %{reason: gettext("Unknown pool staking address. Please, contact support")}}, socket} - staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" -> - {: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 -> - task = Task.async(__MODULE__, :recalc_claim_reward, [socket, staking_contract_address, epochs, pool_staking_address, staker]) - socket = assign(socket, @claim_reward_long_op, %{task: task, staker: staker}) - {:reply, {:ok, %{html: "OK"}}, socket} - end + + staking_contract_address = + try do + ContractState.get(:staking_contract).address + after + end + + empty_pool_staking_address = + pool_staking_address == nil || pool_staking_address == "" || + pool_staking_address == "0x0000000000000000000000000000000000000000" + + empty_staker = staker == nil || staker == "" || staker == "0x0000000000000000000000000000000000000000" + + empty_staking_contract_address = + staking_contract_address == nil || staking_contract_address == "" || + staking_contract_address == "0x0000000000000000000000000000000000000000" + + handle_in_recalc_claim_reward_result( + socket, + epochs, + staking_contract_address, + pool_staking_address, + staker, + empty_pool_staking_address, + empty_staking_contract_address, + empty_staker + ) end def handle_in("render_claim_withdrawal", %{"address" => staking_address}, socket) do @@ -325,12 +331,15 @@ defmodule BlockScoutWeb.StakesChannel do def handle_info({:DOWN, ref, :process, pid, _reason}, socket) do s = socket.assigns[@claim_reward_long_op] - socket = if s && s.task.ref == ref && s.task.pid == pid do - :ets.delete(ContractState, claim_reward_long_op_key(s.staker)) - assign(socket, @claim_reward_long_op, nil) - else - socket - end + + socket = + if s && s.task.ref == ref && s.task.pid == pid do + :ets.delete(ContractState, claim_reward_long_op_key(s.staker)) + assign(socket, @claim_reward_long_op, nil) + else + socket + end + {:noreply, socket} end @@ -339,10 +348,11 @@ defmodule BlockScoutWeb.StakesChannel do end def handle_out("staking_update", data, socket) do - dont_refresh_page = case Map.fetch(data, :dont_refresh_page) do - {:ok, value} -> value - _ -> false - end + dont_refresh_page = + case Map.fetch(data, :dont_refresh_page) do + {:ok, value} -> value + _ -> false + end push(socket, "staking_update", %{ account: socket.assigns[:account], @@ -360,93 +370,138 @@ defmodule BlockScoutWeb.StakesChannel do def find_claim_reward_pools(socket, staker, staking_contract_address) do :ets.insert(ContractState, {claim_reward_long_op_key(staker), true}) + try do json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments) staking_contract = ContractState.get(:staking_contract) responses = - ContractReader.get_staker_pools_length_request(staker) + staker + |> ContractReader.get_staker_pools_length_request() |> ContractReader.perform_requests(%{staking: staking_contract.address}, staking_contract.abi) + staker_pools_length = responses[:length] chunk_size = 100 - pools = if staker_pools_length > 0 do - chunks = 0..trunc(ceil(staker_pools_length / chunk_size) - 1) - Enum.reduce(chunks, [], fn i, acc -> - responses = - ContractReader.get_staker_pools_request(staker, i * chunk_size, chunk_size) - |> ContractReader.perform_requests(%{staking: staking_contract.address}, staking_contract.abi) - acc ++ Enum.map(responses[:pools], fn pool_staking_address -> - address_bytes_to_string(pool_staking_address) - end) - end) - else - [] - end - pools_amounts = Enum.map(pools, fn pool_staking_address -> - ContractReader.call_get_reward_amount( - staking_contract_address, - [], - pool_staking_address, - staker, - json_rpc_named_arguments - ) - end) + pools = + if staker_pools_length > 0 do + chunks = 0..trunc(ceil(staker_pools_length / chunk_size) - 1) - error = Enum.find_value(pools_amounts, fn result -> - case result do - {:error, reason} -> error_reason_to_string(reason) - _ -> nil - end - end) - - {error, pools} = if error != nil do - {error, %{}} - else - block_reward_contract = ContractState.get(:block_reward_contract) - - pools = - pools_amounts - |> Enum.map(fn {_, amounts} -> amounts end) - |> Enum.zip(pools) - |> Enum.filter(fn {amounts, _} -> amounts.token_reward_sum > 0 || amounts.native_reward_sum > 0 end) - |> Enum.map(fn {amounts, pool_staking_address} -> + Enum.reduce(chunks, [], fn i, acc -> responses = - ContractReader.epochs_to_claim_reward_from_request(pool_staking_address, staker) - |> ContractReader.perform_requests(%{block_reward: block_reward_contract.address}, block_reward_contract.abi) + staker + |> ContractReader.get_staker_pools_request(i * chunk_size, chunk_size) + |> ContractReader.perform_requests(%{staking: staking_contract.address}, staking_contract.abi) - epochs = - array_to_ranges(responses[:epochs]) - |> Enum.map(fn {first, last} -> - Integer.to_string(first) <> (if first != last, do: "-" <> Integer.to_string(last), else: "") + acc ++ + Enum.map(responses[:pools], fn pool_staking_address -> + address_bytes_to_string(pool_staking_address) end) - data = Map.put(amounts, :epochs, Enum.join(epochs, ",")) - - {data, pool_staking_address} end) - |> Enum.filter(fn {data, _} -> data.epochs != "" end) + else + [] + end - pools_gas_estimates = Enum.map(pools, fn {_data, pool_staking_address} -> - result = ContractReader.claim_reward_estimate_gas( + pools_amounts = + Enum.map(pools, fn pool_staking_address -> + ContractReader.call_get_reward_amount( staking_contract_address, [], pool_staking_address, staker, json_rpc_named_arguments ) + end) + + error = + Enum.find_value(pools_amounts, fn result -> + case result do + {:error, reason} -> error_reason_to_string(reason) + _ -> nil + end + end) + + {error, pools} = + get_pools(pools_amounts, pools, staking_contract_address, staker, json_rpc_named_arguments, error) + + html = + View.render_to_string( + StakesView, + "_stakes_modal_claim_reward_content.html", + coin: %Token{symbol: Explorer.coin(), decimals: Decimal.new(18)}, + error: error, + pools: pools, + token: ContractState.get(:token) + ) + + push(socket, "claim_reward_pools", %{ + html: html + }) + after + :ets.delete(ContractState, claim_reward_long_op_key(staker)) + end + end + + def get_pools(pools_amounts, pools, staking_contract_address, staker, json_rpc_named_arguments, error) do + if error != nil do + {error, %{}} + else + block_reward_contract = ContractState.get(:block_reward_contract) + + pools = + pools_amounts + |> Enum.map(fn {_, amounts} -> amounts end) + |> Enum.zip(pools) + |> Enum.filter(fn {amounts, _} -> amounts.token_reward_sum > 0 || amounts.native_reward_sum > 0 end) + |> Enum.map(fn {amounts, pool_staking_address} -> + responses = + pool_staking_address + |> ContractReader.epochs_to_claim_reward_from_request(staker) + |> ContractReader.perform_requests( + %{block_reward: block_reward_contract.address}, + block_reward_contract.abi + ) + + epochs = + responses[:epochs] + |> array_to_ranges() + |> Enum.map(fn {first, last} -> + Integer.to_string(first) <> if first != last, do: "-" <> Integer.to_string(last), else: "" + end) + + data = Map.put(amounts, :epochs, Enum.join(epochs, ",")) + + {data, pool_staking_address} + end) + |> Enum.filter(fn {data, _} -> data.epochs != "" end) + + pools_gas_estimates = + Enum.map(pools, fn {_data, pool_staking_address} -> + result = + ContractReader.claim_reward_estimate_gas( + staking_contract_address, + [], + pool_staking_address, + staker, + json_rpc_named_arguments + ) + {pool_staking_address, result} end) - error = Enum.find_value(pools_gas_estimates, fn {_, result} -> + error = + Enum.find_value(pools_gas_estimates, fn {_, result} -> case result do {:error, reason} -> error_reason_to_string(reason) _ -> nil end end) - pools = if error == nil do + pools = + if error == nil do pools_gas_estimates = Map.new(pools_gas_estimates) + Map.new(pools, fn {data, pool_staking_address} -> {:ok, estimate} = pools_gas_estimates[pool_staking_address] data = Map.put(data, :gas_estimate, estimate) @@ -456,48 +511,18 @@ defmodule BlockScoutWeb.StakesChannel do %{} end - {error, pools} - end - - html = View.render_to_string( - StakesView, - "_stakes_modal_claim_reward_content.html", - coin: %Token{symbol: Explorer.coin(), decimals: Decimal.new(18)}, - error: error, - pools: pools, - token: ContractState.get(:token) - ) - - push(socket, "claim_reward_pools", %{ - html: html - }) - after - :ets.delete(ContractState, claim_reward_long_op_key(staker)) + {error, pools} end end def recalc_claim_reward(socket, staking_contract_address, epochs, pool_staking_address, staker) do :ets.insert(ContractState, {claim_reward_long_op_key(staker), true}) + try do json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments) - amounts_result = ContractReader.call_get_reward_amount( - staking_contract_address, - epochs, - pool_staking_address, - staker, - json_rpc_named_arguments - ) - - {error, amounts} = case amounts_result do - {:ok, amounts} -> - {nil, amounts} - {:error, reason} -> - {error_reason_to_string(reason), %{token_reward_sum: 0, native_reward_sum: 0}} - end - - {error, gas_limit} = if error == nil do - estimate_gas_result = ContractReader.claim_reward_estimate_gas( + amounts_result = + ContractReader.call_get_reward_amount( staking_contract_address, epochs, pool_staking_address, @@ -505,22 +530,53 @@ defmodule BlockScoutWeb.StakesChannel do json_rpc_named_arguments ) - case estimate_gas_result do - {:ok, gas_limit} -> - {nil, gas_limit} + {error, amounts} = + case amounts_result do + {:ok, amounts} -> + {nil, amounts} + {:error, reason} -> - {error_reason_to_string(reason), 0} + {error_reason_to_string(reason), %{token_reward_sum: 0, native_reward_sum: 0}} + end + + {error, gas_limit} = + if error == nil do + estimate_gas_result = + ContractReader.claim_reward_estimate_gas( + staking_contract_address, + epochs, + pool_staking_address, + staker, + json_rpc_named_arguments + ) + + case estimate_gas_result do + {:ok, gas_limit} -> + {nil, gas_limit} + + {:error, reason} -> + {error_reason_to_string(reason), 0} + end + else + {error, 0} end - else - {error, 0} - end token = ContractState.get(:token) coin = %Token{symbol: Explorer.coin(), decimals: Decimal.new(18)} push(socket, "claim_reward_recalculations", %{ - token_reward_sum: StakesHelpers.format_token_amount(amounts.token_reward_sum, token, digits: token.decimals, ellipsize: false, symbol: false), - native_reward_sum: StakesHelpers.format_token_amount(amounts.native_reward_sum, coin, digits: coin.decimals, ellipsize: false, symbol: false), + token_reward_sum: + StakesHelpers.format_token_amount(amounts.token_reward_sum, token, + digits: token.decimals, + ellipsize: false, + symbol: false + ), + native_reward_sum: + StakesHelpers.format_token_amount(amounts.native_reward_sum, coin, + digits: coin.decimals, + ellipsize: false, + symbol: false + ), gas_limit: gas_limit, error: error }) @@ -534,6 +590,7 @@ defmodule BlockScoutWeb.StakesChannel do true else staker = socket.assigns[:account] + with [{_, true}] <- :ets.lookup(ContractState, claim_reward_long_op_key(staker)) do true end @@ -544,13 +601,20 @@ defmodule BlockScoutWeb.StakesChannel do defp array_to_ranges(numbers, prev_ranges \\ []) do length = Enum.count(numbers) + if length > 0 do {first, last, next_index} = get_range(numbers) - ranges = prev_ranges ++ [{first, last}] + prev_ranges_reversed = Enum.reverse(prev_ranges) + + ranges = + [{first, last} | prev_ranges_reversed] + |> Enum.reverse() + if next_index == 0 || next_index >= length do ranges else - Enum.slice(numbers, next_index, length - next_index) + numbers + |> Enum.slice(next_index, length - next_index) |> array_to_ranges(ranges) end else @@ -567,11 +631,13 @@ defmodule BlockScoutWeb.StakesChannel do end defp get_range(numbers) do - last_index = - Enum.with_index(numbers) + last_index = + numbers + |> Enum.with_index() |> Enum.find_index(fn {n, i} -> if i > 0, do: n != Enum.at(numbers, i - 1) + 1, else: false end) + next_index = if last_index == nil, do: Enum.count(numbers), else: last_index first = Enum.at(numbers, 0) last = Enum.at(numbers, next_index - 1) @@ -599,4 +665,85 @@ defmodule BlockScoutWeb.StakesChannel do staker = if staker == nil, do: "", else: staker Atom.to_string(@claim_reward_long_op) <> "_" <> staker end + + defp handle_in_render_claim_reward_result( + socket, + data, + staker, + staking_contract_address, + empty_staker, + empty_staking_contract_address + ) do + cond do + claim_reward_long_op_active(socket) == true -> + {:reply, {:error, %{reason: gettext("Pools searching is already in progress for this address")}}, socket} + + empty_staker -> + {:reply, {:error, %{reason: gettext("Unknown staker address. Please, choose your account in MetaMask")}}, + socket} + + empty_staking_contract_address -> + {:reply, {:error, %{reason: gettext("Unknown address of Staking contract. Please, contact support")}}, socket} + + true -> + result = + if data["preload"] do + %{ + html: View.render_to_string(StakesView, "_stakes_modal_claim_reward.html", %{}), + socket: socket + } + else + task = Task.async(__MODULE__, :find_claim_reward_pools, [socket, staker, staking_contract_address]) + + %{ + html: "OK", + socket: assign(socket, @claim_reward_long_op, %{task: task, staker: staker}) + } + end + + {:reply, {:ok, %{html: result.html}}, result.socket} + end + end + + defp handle_in_recalc_claim_reward_result( + socket, + epochs, + staking_contract_address, + pool_staking_address, + staker, + empty_pool_staking_address, + empty_staking_contract_address, + empty_staker + ) do + cond do + claim_reward_long_op_active(socket) == true -> + {:reply, {:error, %{reason: gettext("Reward calculating is already in progress for this address")}}, socket} + + Enum.empty?(epochs) -> + {:reply, {:error, %{reason: gettext("Staking epochs are not specified or not in the allowed range")}}, socket} + + empty_pool_staking_address -> + {:reply, {:error, %{reason: gettext("Unknown pool staking address. Please, contact support")}}, socket} + + empty_staker -> + {:reply, {:error, %{reason: gettext("Unknown staker address. Please, choose your account in MetaMask")}}, + socket} + + empty_staking_contract_address -> + {:reply, {:error, %{reason: gettext("Unknown address of Staking contract. Please, contact support")}}, socket} + + true -> + task = + Task.async(__MODULE__, :recalc_claim_reward, [ + socket, + staking_contract_address, + epochs, + pool_staking_address, + staker + ]) + + socket = assign(socket, @claim_reward_long_op, %{task: task, staker: staker}) + {:reply, {:ok, %{html: "OK"}}, socket} + end + end end 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 38e887542ebe..506f271b042c 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 @@ -49,72 +49,74 @@ defmodule BlockScoutWeb.StakesController do # this is called when account in MetaMask is changed on client side # or when UI periodically reloads the pool list (e.g. once per 10 blocks) defp render_template(filter, conn, %{"type" => "JSON"} = params) do - {items, next_page_path} = if Map.has_key?(params, "filterMy") do - [paging_options: options] = paging_options(params) - - last_index = - params - |> Map.get("position", "0") - |> String.to_integer() - - pools_plus_one = - Chain.staking_pools( - filter, - options, - unless params["account"] == "" do - params["account"] - end, - params["filterBanned"] == "true", - params["filterMy"] == "true" - ) - - {pools, next_page} = split_list_by_page(pools_plus_one) - - next_page_path = - case next_page_params(next_page, pools, params) do - nil -> - nil - - next_page_params -> - updated_page_params = - next_page_params - |> Map.delete("type") - |> Map.put("position", last_index + 1) - - next_page_path(filter, conn, updated_page_params) - end - - average_block_time = AverageBlockTime.average_block_time() - token = ContractState.get(:token, %Token{}) - epoch_number = ContractState.get(:epoch_number, 0) - staking_allowed = ContractState.get(:staking_allowed, false) - - items = - pools - |> Enum.with_index(last_index + 1) - |> Enum.map(fn {%{pool: pool, delegator: delegator}, index} -> - View.render_to_string( - StakesView, - "_rows.html", - token: token, - pool: pool, - delegator: delegator, - index: index, - average_block_time: average_block_time, - pools_type: filter, - buttons: %{ - stake: staking_allowed and stake_allowed?(pool, delegator), - move: staking_allowed and move_allowed?(delegator), - withdraw: staking_allowed and withdraw_allowed?(delegator), - claim: staking_allowed and claim_allowed?(delegator, epoch_number) - } + {items, next_page_path} = + if Map.has_key?(params, "filterMy") do + [paging_options: options] = paging_options(params) + + last_index = + params + |> Map.get("position", "0") + |> String.to_integer() + + pools_plus_one = + Chain.staking_pools( + filter, + options, + unless params["account"] == "" do + params["account"] + end, + params["filterBanned"] == "true", + params["filterMy"] == "true" ) - end) - {items, next_page_path} - else - loading_item = View.render_to_string(StakesView, "_rows_loading.html", %{}) - {[loading_item], nil} - end + + {pools, next_page} = split_list_by_page(pools_plus_one) + + next_page_path = + case next_page_params(next_page, pools, params) do + nil -> + nil + + next_page_params -> + updated_page_params = + next_page_params + |> Map.delete("type") + |> Map.put("position", last_index + 1) + + next_page_path(filter, conn, updated_page_params) + end + + average_block_time = AverageBlockTime.average_block_time() + token = ContractState.get(:token, %Token{}) + epoch_number = ContractState.get(:epoch_number, 0) + staking_allowed = ContractState.get(:staking_allowed, false) + + items = + pools + |> Enum.with_index(last_index + 1) + |> Enum.map(fn {%{pool: pool, delegator: delegator}, index} -> + View.render_to_string( + StakesView, + "_rows.html", + token: token, + pool: pool, + delegator: delegator, + index: index, + average_block_time: average_block_time, + pools_type: filter, + buttons: %{ + stake: staking_allowed and stake_allowed?(pool, delegator), + move: staking_allowed and move_allowed?(delegator), + withdraw: staking_allowed and withdraw_allowed?(delegator), + claim: staking_allowed and claim_allowed?(delegator, epoch_number) + } + ) + end) + + {items, next_page_path} + else + loading_item = View.render_to_string(StakesView, "_rows_loading.html", %{}) + {[loading_item], nil} + end json( conn, diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index dd166eff638b..678ea3e4f83d 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -3642,25 +3642,32 @@ defmodule Explorer.Chain do end def staking_pool_delegators(staking_address_hash, show_snapshotted_data) do - from( - d in StakingPoolsDelegator, - where: - d.staking_address_hash == ^staking_address_hash and - (d.is_active == true or ^show_snapshotted_data and d.snapshotted_stake_amount > 0 and d.is_active != true), - order_by: - [desc: d.stake_amount] - ) |> Repo.all() + query = + from( + d in StakingPoolsDelegator, + where: + d.staking_address_hash == ^staking_address_hash and + (d.is_active == true or (^show_snapshotted_data and d.snapshotted_stake_amount > 0 and d.is_active != true)), + order_by: [desc: d.stake_amount] + ) + + query + |> Repo.all() end def staking_pool_snapshotted_inactive_delegators_count(staking_address_hash) do - from( - d in StakingPoolsDelegator, - where: - d.staking_address_hash == ^staking_address_hash and - d.snapshotted_stake_amount > 0 and - d.is_active != true, - select: fragment("count(*)") - ) |> Repo.one() + query = + from( + d in StakingPoolsDelegator, + where: + d.staking_address_hash == ^staking_address_hash and + d.snapshotted_stake_amount > 0 and + d.is_active != true, + select: fragment("count(*)") + ) + + query + |> Repo.one() end def staking_pool_delegator(staking_address_hash, address_hash) do diff --git a/apps/explorer/lib/explorer/chain/import.ex b/apps/explorer/lib/explorer/chain/import.ex index b80ec3b3d7c7..8b5696a003fb 100644 --- a/apps/explorer/lib/explorer/chain/import.ex +++ b/apps/explorer/lib/explorer/chain/import.ex @@ -225,7 +225,7 @@ defmodule Explorer.Chain.Import do defp validate_runner_options(runner, options) when is_map(options) do option_key = runner.option_key() - runner_specific_options = + runner_specific_options = if Map.has_key?(Enum.into(runner.__info__(:functions), %{}), :runner_specific_options) do apply(runner, :runner_specific_options, []) else @@ -256,8 +256,8 @@ defmodule Explorer.Chain.Import do @local_options ~w(on_conflict params with timeout)a defp validate_runner_options_known(runner_option_key, options, runner_specific_options) do - unknown_option_keys = Map.keys(options) -- @local_options - unknown_option_keys = unknown_option_keys -- runner_specific_options + base_unknown_option_keys = Map.keys(options) -- @local_options + unknown_option_keys = base_unknown_option_keys -- runner_specific_options if Enum.empty?(unknown_option_keys) do :ok diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index 55b3bc9d0f8a..8d2871137c30 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -43,19 +43,21 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do |> Map.put_new(:timeout, @timeout) |> Map.put(:timestamps, timestamps) - clear_snapshotted_values = case Map.fetch(insert_options, :clear_snapshotted_values) do - {:ok, v} -> v - :error -> false - end - - multi = if not clear_snapshotted_values do - # Enforce ShareLocks tables order (see docs: sharelocks.md) - Multi.run(multi, :acquire_all_staking_pools, fn repo, _ -> - acquire_all_staking_pools(repo) - end) - else - multi - end + clear_snapshotted_values = + case Map.fetch(insert_options, :clear_snapshotted_values) do + {:ok, v} -> v + :error -> false + end + + multi = + if clear_snapshotted_values do + multi + else + # Enforce ShareLocks tables order (see docs: sharelocks.md) + Multi.run(multi, :acquire_all_staking_pools, fn repo, _ -> + acquire_all_staking_pools(repo) + end) + end multi |> Multi.run(:mark_as_deleted, fn repo, _ -> @@ -84,26 +86,28 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do end defp mark_as_deleted(repo, changes_list, %{timeout: timeout}, clear_snapshotted_values) when is_list(changes_list) do - query = if clear_snapshotted_values do - from( - pool in StakingPool, - update: [ - set: [ - snapshotted_self_staked_amount: nil, - snapshotted_total_staked_amount: nil, - snapshotted_validator_reward_ratio: nil + query = + if clear_snapshotted_values do + from( + pool in StakingPool, + update: [ + set: [ + snapshotted_self_staked_amount: nil, + snapshotted_total_staked_amount: nil, + snapshotted_validator_reward_ratio: nil + ] ] - ] - ) - else - addresses = Enum.map(changes_list, & &1.staking_address_hash) - from( - pool in StakingPool, - where: pool.staking_address_hash not in ^addresses, - # ShareLocks order already enforced by `acquire_all_staking_pools` (see docs: sharelocks.md) - update: [set: [is_deleted: true, is_active: false]] - ) - end + ) + else + addresses = Enum.map(changes_list, & &1.staking_address_hash) + + from( + pool in StakingPool, + where: pool.staking_address_hash not in ^addresses, + # ShareLocks order already enforced by `acquire_all_staking_pools` (see docs: sharelocks.md) + update: [set: [is_deleted: true, is_active: false]] + ) + end try do {_, result} = repo.update_all(query, [], timeout: timeout) diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex index 992cd8cf83da..b0e28f2ce6e8 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools_delegators.ex @@ -57,22 +57,24 @@ defmodule Explorer.Chain.Import.Runner.StakingPoolsDelegators do def timeout, do: @timeout defp mark_as_deleted(repo, %{timeout: timeout} = options) do - clear_snapshotted_values = case Map.fetch(options, :clear_snapshotted_values) do - {:ok, v} -> v - :error -> false - end - - query = if clear_snapshotted_values do - from( - d in StakingPoolsDelegator, - update: [set: [snapshotted_reward_ratio: nil, snapshotted_stake_amount: nil]] - ) - else - from( - d in StakingPoolsDelegator, - update: [set: [is_active: false, is_deleted: true]] - ) - end + clear_snapshotted_values = + case Map.fetch(options, :clear_snapshotted_values) do + {:ok, v} -> v + :error -> false + end + + query = + if clear_snapshotted_values do + from( + d in StakingPoolsDelegator, + update: [set: [snapshotted_reward_ratio: nil, snapshotted_stake_amount: nil]] + ) + else + from( + d in StakingPoolsDelegator, + update: [set: [is_active: false, is_deleted: true]] + ) + end try do {_, result} = repo.update_all(query, [], timeout: timeout) diff --git a/apps/explorer/lib/explorer/staking/contract_reader.ex b/apps/explorer/lib/explorer/staking/contract_reader.ex index 0041d3385076..1249127f51ca 100644 --- a/apps/explorer/lib/explorer/staking/contract_reader.ex +++ b/apps/explorer/lib/explorer/staking/contract_reader.ex @@ -37,12 +37,12 @@ defmodule Explorer.Staking.ContractReader do # address _staker # ) public view returns(uint256 tokenRewardSum, uint256 nativeRewardSum); def call_get_reward_amount( - staking_contract_address, - staking_epochs, - pool_staking_address, - staker, - json_rpc_named_arguments - ) do + staking_contract_address, + staking_epochs, + pool_staking_address, + staker, + json_rpc_named_arguments + ) do staking_epochs_joint = staking_epochs |> Enum.map(fn epoch -> @@ -56,29 +56,44 @@ defmodule Explorer.Staking.ContractReader do staker = address_pad_to_64(staker) staking_epochs_length = - Enum.count(staking_epochs) + staking_epochs + |> Enum.count() |> Integer.to_string(16) |> String.pad_leading(64, ["0"]) - data = "0xfb367a9b" # `getRewardAmount` function signature - data = data <> String.pad_leading("60", 64, ["0"]) # offset to the `_stakingEpochs` array - data = data <> pool_staking_address # `_poolStakingAddress` parameter - data = data <> staker # `_staker` parameter - data = data <> staking_epochs_length # the length of `_stakingEpochs` array - data = data <> staking_epochs_joint # encoded `_stakingEpochs` array - - result = EthereumJSONRPC.request(%{ + # `getRewardAmount` function signature + function_signature = "0xfb367a9b" + # offset to the `_stakingEpochs` array + function_signature_with_offset = function_signature <> String.pad_leading("60", 64, ["0"]) + # `_poolStakingAddress` parameter + function_with_param_1 = function_signature_with_offset <> pool_staking_address + # `_staker` parameter + function_with_param1_param2 = function_with_param_1 <> staker + # the length of `_stakingEpochs` array + function_with_param_1_length_param2 = function_with_param1_param2 <> staking_epochs_length + # encoded `_stakingEpochs` array + data = function_with_param_1_length_param2 <> staking_epochs_joint + + request = %{ id: 0, method: "eth_call", - params: [%{ - to: staking_contract_address, - data: data - }] - }) |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments) + params: [ + %{ + to: staking_contract_address, + data: data + } + ] + } + + result = + request + |> EthereumJSONRPC.request() + |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments) case result do {:ok, response} -> response = String.replace_leading(response, "0x", "") + if String.length(response) != 64 * 2 do {:error, "Invalid getRewardAmount response."} else @@ -87,6 +102,7 @@ defmodule Explorer.Staking.ContractReader do native_reward_sum = String.to_integer(native_reward_sum, 16) {:ok, %{token_reward_sum: token_reward_sum, native_reward_sum: native_reward_sum}} end + {:error, reason} -> {:error, reason} end @@ -98,12 +114,12 @@ defmodule Explorer.Staking.ContractReader do # address _poolStakingAddress # ) public; def claim_reward_estimate_gas( - staking_contract_address, - staking_epochs, - pool_staking_address, - staker, - json_rpc_named_arguments - ) do + staking_contract_address, + staking_epochs, + pool_staking_address, + staker, + json_rpc_named_arguments + ) do staking_epochs_joint = staking_epochs |> Enum.map(fn epoch -> @@ -116,34 +132,50 @@ defmodule Explorer.Staking.ContractReader do pool_staking_address = address_pad_to_64(pool_staking_address) staking_epochs_length = - Enum.count(staking_epochs) + staking_epochs + |> Enum.count() |> Integer.to_string(16) |> String.pad_leading(64, ["0"]) - data = "0x3ea15d62" # `claimReward` function signature - data = data <> String.pad_leading("40", 64, ["0"]) # offset to the `_stakingEpochs` array - data = data <> pool_staking_address # `_poolStakingAddress` parameter - data = data <> staking_epochs_length # the length of `_stakingEpochs` array - data = data <> staking_epochs_joint # encoded `_stakingEpochs` array - - result = EthereumJSONRPC.request(%{ + # `claimReward` function signature + function_signature = "0x3ea15d62" + # offset to the `_stakingEpochs` array + function_signature_with_offset = function_signature <> String.pad_leading("40", 64, ["0"]) + # `_poolStakingAddress` parameter + function_with_param_1 = function_signature_with_offset <> pool_staking_address + # the length of `_stakingEpochs` array + function_with_param_1_length_param2 = function_with_param_1 <> staking_epochs_length + # encoded `_stakingEpochs` array + data = function_with_param_1_length_param2 <> staking_epochs_joint + + request = %{ id: 0, method: "eth_estimateGas", - params: [%{ - from: staker, - to: staking_contract_address, - gasPrice: "0x3B9ACA00", # 1 gwei - data: data - }] - }) |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments) + params: [ + %{ + from: staker, + to: staking_contract_address, + # 1 gwei + gasPrice: "0x3B9ACA00", + data: data + } + ] + } + + result = + request + |> EthereumJSONRPC.request() + |> EthereumJSONRPC.json_rpc(json_rpc_named_arguments) case result do {:ok, response} -> - estimate = + estimate = response |> String.replace_leading("0x", "") |> String.to_integer(16) + {:ok, estimate} + {:error, reason} -> {:error, reason} end diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 12675fc9fb00..fc4dd2a1204e 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -34,7 +34,8 @@ defmodule Explorer.Staking.ContractState do :validator_set_contract ] - @token_renew_frequency 10 # frequency in blocks + # frequency in blocks + @token_renew_frequency 10 defstruct [ :seen_block, @@ -128,81 +129,151 @@ defmodule Explorer.Staking.ContractState do # read general info from the contracts (including pool list and validator list) global_responses = ContractReader.perform_requests(ContractReader.global_requests(), contracts, abi) - validator_min_reward_percent = ContractReader.perform_requests( - ContractReader.validator_min_reward_percent_request(global_responses.epoch_number), contracts, abi - ).value + validator_min_reward_percent = get_validator_min_reward_percent(global_responses, contracts, abi) - epoch_very_beginning = (global_responses.epoch_start_block == block_number + 1) + epoch_very_beginning = global_responses.epoch_start_block == block_number + 1 is_validator = Enum.into(global_responses.validators, %{}, &{address_bytes_to_string(&1), true}) - start_snapshotting = (global_responses.epoch_number > get(:snapshotted_epoch_number) && global_responses.epoch_number > 0 && not get(:is_snapshotting)) - # save the general info to ETS (excluding pool list and validator list) - settings = - global_responses - |> Map.take([ - :token_contract_address, - :min_candidate_stake, - :min_delegator_stake, - :epoch_number, - :epoch_start_block, - :epoch_end_block, - :staking_allowed, - :validator_set_apply_block - ]) - |> Map.to_list() - |> Enum.concat(validator_min_reward_percent: validator_min_reward_percent) + start_snapshotting = + global_responses.epoch_number > get(:snapshotted_epoch_number) && global_responses.epoch_number > 0 && + not get(:is_snapshotting) - 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 + # save the general info to ETS (excluding pool list and validator list) + settings = get_settings(global_responses, validator_min_reward_percent, block_number) :ets.insert(@table_name, settings) # form the list of validator pools - validators = if start_snapshotting do - if global_responses.validator_set_apply_block == 0 do - %{ - "getPendingValidators" => {:ok, [validators_pending]}, - "validatorsToBeFinalized" => {:ok, [validators_to_be_finalized]} - } = Reader.query_contract(contracts.validator_set, abi, %{ - "getPendingValidators" => [], - "validatorsToBeFinalized" => [] - }) - validators_pending = Enum.uniq(validators_pending ++ validators_to_be_finalized) - %{ - all: Enum.uniq(global_responses.validators ++ validators_pending), - for_snapshot: validators_pending - } - else - %{ - all: global_responses.validators, - for_snapshot: global_responses.validators - } - end - else - %{all: global_responses.validators} - end + validators = + get_validators( + start_snapshotting, + global_responses, + contracts, + abi + ) # miningToStakingAddress mapping - mining_to_staking_address = - validators.all - |> Enum.map(&ContractReader.staking_by_mining_request/1) - |> ContractReader.perform_grouped_requests(validators.all, contracts, abi) - |> Map.new(fn {mining_address, resp} -> {mining_address, address_string_to_bytes(resp.staking_address).bytes} end) + mining_to_staking_address = get_mining_to_staking_address(validators, contracts, abi) # the list of all pools (validators + active pools + inactive pools) - pools = Enum.uniq( - Map.values(mining_to_staking_address) ++ - global_responses.active_pools ++ - global_responses.inactive_pools - ) + pools = + Enum.uniq( + Map.values(mining_to_staking_address) ++ + global_responses.active_pools ++ + global_responses.inactive_pools + ) + %{ + pool_staking_responses: pool_staking_responses, + pool_mining_responses: pool_mining_responses, + staker_responses: staker_responses + } = get_responses(pools, block_number, contracts, abi) + + # to keep sort order when using `perform_grouped_requests` (see below) + 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 = + get_candidate_reward_responses(pool_staking_responses, global_responses, pool_staking_keys, contracts, abi) + + # to keep sort order when using `perform_grouped_requests` (see below) + 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 = + get_delegator_reward_responses( + staker_responses, + pool_staking_responses, + global_responses, + delegator_keys, + contracts, + abi + ) + + # calculate total amount staked into all active pools + staked_total = Enum.sum(for {_, pool} <- pool_staking_responses, pool.is_active, do: pool.total_staked_amount) + + # calculate likelihood of becoming a validator on the next epoch + [likelihood_values, total_likelihood] = global_responses.pools_likelihood + # array of pool addresses (staking addresses) + likelihood = + global_responses.pools_to_be_elected + |> Enum.zip(likelihood_values) + |> Enum.into(%{}) + + snapshotted_epoch_number = get(:snapshotted_epoch_number) + + # form entries for writing to the `staking_pools` table in DB + pool_entries = + get_pool_entries(%{ + pools: pools, + pool_mining_responses: pool_mining_responses, + pool_staking_responses: pool_staking_responses, + is_validator: is_validator, + candidate_reward_responses: candidate_reward_responses, + global_responses: global_responses, + snapshotted_epoch_number: snapshotted_epoch_number, + likelihood: likelihood, + total_likelihood: total_likelihood, + staked_total: staked_total + }) + + # form entries for writing to the `staking_pools_delegators` table in DB + delegator_entries = get_delegator_entries(staker_responses, delegator_reward_responses) + + # perform SQL queries + {:ok, _} = + Chain.import(%{ + staking_pools: %{params: pool_entries}, + staking_pools_delegators: %{params: delegator_entries}, + timeout: :infinity + }) + + if epoch_very_beginning or start_snapshotting do + at_start_snapshotting(block_number) + end + + if start_snapshotting do + do_start_snapshotting( + epoch_very_beginning, + pool_staking_responses, + global_responses, + contracts, + abi, + validators, + mining_to_staking_address + ) + end + + # notify the UI about new block + Publisher.broadcast(:staking_update) + end + + defp get_settings(global_responses, validator_min_reward_percent, block_number) do + base_settings = get_base_settings(global_responses, 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 + + if update_token do + Enum.concat(base_settings, token: get_token(global_responses.token_contract_address)) + else + base_settings + end + end + + defp get_mining_to_staking_address(validators, contracts, abi) do + validators.all + |> Enum.map(&ContractReader.staking_by_mining_request/1) + |> ContractReader.perform_grouped_requests(validators.all, contracts, abi) + |> Map.new(fn {mining_address, resp} -> {mining_address, address_string_to_bytes(resp.staking_address).bytes} end) + end + + defp get_responses(pools, block_number, contracts, abi) do # read pool info from the contracts by its staking address pool_staking_responses = pools @@ -233,258 +304,366 @@ defmodule Explorer.Staking.ContractState do end) |> ContractReader.perform_grouped_requests(stakers, contracts, abi) - # to keep sort order when using `perform_grouped_requests` (see below) - pool_staking_keys = Enum.map(pool_staking_responses, fn {pool_staking_address, _} -> pool_staking_address end) + %{ + pool_staking_responses: pool_staking_responses, + pool_mining_responses: pool_mining_responses, + staker_responses: staker_responses + } + 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 = - pool_staking_responses - |> Enum.map(fn {_pool_staking_address, resp} -> - ContractReader.validator_reward_request([ - global_responses.epoch_number, - resp.self_staked_amount, - resp.total_staked_amount, - 1000_000 - ]) - end) - |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) + defp get_candidate_reward_responses(pool_staking_responses, global_responses, pool_staking_keys, contracts, abi) do + pool_staking_responses + |> Enum.map(fn {_pool_staking_address, resp} -> + ContractReader.validator_reward_request([ + global_responses.epoch_number, + resp.self_staked_amount, + resp.total_staked_amount, + 1000_000 + ]) + end) + |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) + end - # to keep sort order when using `perform_grouped_requests` (see below) - delegator_keys = Enum.map(staker_responses, fn {key, _} -> key end) + defp get_delegator_reward_responses( + staker_responses, + pool_staking_responses, + global_responses, + delegator_keys, + contracts, + abi + ) do + staker_responses + |> Enum.map(fn {{pool_staking_address, _staker_address, _is_active}, resp} -> + staking_resp = pool_staking_responses[pool_staking_address] + + ContractReader.delegator_reward_request([ + global_responses.epoch_number, + resp.stake_amount, + staking_resp.self_staked_amount, + staking_resp.total_staked_amount, + 1000_000 + ]) + end) + |> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi) + 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 = - staker_responses - |> Enum.map(fn {{pool_staking_address, _staker_address, _is_active}, resp} -> - staking_resp = pool_staking_responses[pool_staking_address] - - ContractReader.delegator_reward_request([ - global_responses.epoch_number, - resp.stake_amount, - staking_resp.self_staked_amount, - staking_resp.total_staked_amount, - 1000_000 - ]) - end) - |> ContractReader.perform_grouped_requests(delegator_keys, contracts, abi) + defp get_delegator_entries(staker_responses, delegator_reward_responses) do + Enum.map(staker_responses, fn {{pool_address, delegator_address, is_active}, response} -> + delegator_reward_response = delegator_reward_responses[{pool_address, delegator_address, is_active}] - # calculate total amount staked into all active pools - staked_total = Enum.sum(for {_, pool} <- pool_staking_responses, pool.is_active, do: pool.total_staked_amount) + Map.merge(response, %{ + address_hash: delegator_address, + staking_address_hash: pool_address, + is_active: is_active, + reward_ratio: Float.floor(delegator_reward_response.delegator_share / 10_000, 2) + }) + end) + end - # calculate likelihood of becoming a validator on the next epoch - [likelihood_values, total_likelihood] = global_responses.pools_likelihood - likelihood = - global_responses.pools_to_be_elected # array of pool addresses (staking addresses) - |> Enum.zip(likelihood_values) - |> Enum.into(%{}) + defp get_validator_min_reward_percent(global_responses, contracts, abi) do + ContractReader.perform_requests( + ContractReader.validator_min_reward_percent_request(global_responses.epoch_number), + contracts, + abi + ).value + end - snapshotted_epoch_number = get(:snapshotted_epoch_number) + defp get_base_settings(global_responses, validator_min_reward_percent) do + global_responses + |> Map.take([ + :token_contract_address, + :min_candidate_stake, + :min_delegator_stake, + :epoch_number, + :epoch_start_block, + :epoch_end_block, + :staking_allowed, + :validator_set_apply_block + ]) + |> Map.to_list() + |> Enum.concat(validator_min_reward_percent: validator_min_reward_percent) + end - # form entries for writing to the `staking_pools` table in DB - pool_entries = - Enum.map(pools, fn pool_staking_address -> - staking_resp = pool_staking_responses[pool_staking_address] - mining_resp = pool_mining_responses[pool_staking_address] - candidate_reward_resp = candidate_reward_responses[pool_staking_address] - is_validator = is_validator[staking_resp.mining_address_hash] || false - - delegators_count = - length(staking_resp.active_delegators) + - if show_snapshotted_data(is_validator, global_responses.validator_set_apply_block, snapshotted_epoch_number, global_responses.epoch_number) do + defp get_validators( + start_snapshotting, + global_responses, + contracts, + abi + ) do + if start_snapshotting do + if global_responses.validator_set_apply_block == 0 do + %{ + "getPendingValidators" => {:ok, [validators_pending]}, + "validatorsToBeFinalized" => {:ok, [validators_to_be_finalized]} + } = + Reader.query_contract(contracts.validator_set, abi, %{ + "getPendingValidators" => [], + "validatorsToBeFinalized" => [] + }) + + validators_pending = Enum.uniq(validators_pending ++ validators_to_be_finalized) + + %{ + all: Enum.uniq(global_responses.validators ++ validators_pending), + for_snapshot: validators_pending + } + else + %{ + all: global_responses.validators, + for_snapshot: global_responses.validators + } + end + else + %{all: global_responses.validators} + end + end + + def show_snapshotted_data( + is_validator, + validator_set_apply_block \\ nil, + snapshotted_epoch_number \\ nil, + epoch_number \\ nil + ) do + validator_set_apply_block = + if validator_set_apply_block !== nil do + validator_set_apply_block + else + get(:validator_set_apply_block) + end + + snapshotted_epoch_number = + if snapshotted_epoch_number !== nil do + snapshotted_epoch_number + else + get(:snapshotted_epoch_number) + end + + epoch_number = + if epoch_number !== nil do + epoch_number + else + get(:epoch_number) + end + + is_validator && validator_set_apply_block > 0 && snapshotted_epoch_number === epoch_number + end + + defp get_pool_entries(%{ + pools: pools, + pool_mining_responses: pool_mining_responses, + pool_staking_responses: pool_staking_responses, + is_validator: is_validator, + candidate_reward_responses: candidate_reward_responses, + global_responses: global_responses, + snapshotted_epoch_number: snapshotted_epoch_number, + likelihood: likelihood, + total_likelihood: total_likelihood, + staked_total: staked_total + }) do + Enum.map(pools, fn pool_staking_address -> + staking_resp = pool_staking_responses[pool_staking_address] + mining_resp = pool_mining_responses[pool_staking_address] + candidate_reward_resp = candidate_reward_responses[pool_staking_address] + is_validator = is_validator[staking_resp.mining_address_hash] || false + + delegators_count = + length(staking_resp.active_delegators) + + if show_snapshotted_data( + is_validator, + global_responses.validator_set_apply_block, + snapshotted_epoch_number, + global_responses.epoch_number + ) do Chain.staking_pool_snapshotted_inactive_delegators_count(pool_staking_address) else 0 end - %{ - staking_address_hash: pool_staking_address, - delegators_count: delegators_count, - stakes_ratio: - if staking_resp.is_active do - ratio(staking_resp.total_staked_amount, staked_total) - else - 0 - end, - validator_reward_ratio: Float.floor(candidate_reward_resp.validator_share / 10_000, 2), - likelihood: ratio(likelihood[pool_staking_address] || 0, total_likelihood), - validator_reward_percent: staking_resp.validator_reward_percent / 10_000, - is_deleted: false, - is_validator: is_validator, - is_unremovable: address_bytes_to_string(pool_staking_address) == global_responses.unremovable_validator, - ban_reason: binary_to_string(mining_resp.ban_reason) - } - |> Map.merge( - Map.take(staking_resp, [ - :is_active, - :mining_address_hash, - :self_staked_amount, - :total_staked_amount - ]) - ) - |> Map.merge( - Map.take(mining_resp, [ - :are_delegators_banned, - :banned_delegators_until, - :banned_until, - :is_banned, - :was_banned_count, - :was_validator_count - ]) - ) - end) + %{ + staking_address_hash: pool_staking_address, + delegators_count: delegators_count, + stakes_ratio: + if staking_resp.is_active do + ratio(staking_resp.total_staked_amount, staked_total) + else + 0 + end, + validator_reward_ratio: Float.floor(candidate_reward_resp.validator_share / 10_000, 2), + likelihood: ratio(likelihood[pool_staking_address] || 0, total_likelihood), + validator_reward_percent: staking_resp.validator_reward_percent / 10_000, + is_deleted: false, + is_validator: is_validator, + is_unremovable: address_bytes_to_string(pool_staking_address) == global_responses.unremovable_validator, + ban_reason: binary_to_string(mining_resp.ban_reason) + } + |> Map.merge( + Map.take(staking_resp, [ + :is_active, + :mining_address_hash, + :self_staked_amount, + :total_staked_amount + ]) + ) + |> Map.merge( + Map.take(mining_resp, [ + :are_delegators_banned, + :banned_delegators_until, + :banned_until, + :is_banned, + :was_banned_count, + :was_validator_count + ]) + ) + end) + end - # form entries for writing to the `staking_pools_delegators` table in DB - delegator_entries = - Enum.map(staker_responses, fn {{pool_address, delegator_address, is_active}, response} -> - delegator_reward_response = delegator_reward_responses[{pool_address, delegator_address, is_active}] - - Map.merge(response, %{ - address_hash: delegator_address, - staking_address_hash: pool_address, - is_active: is_active, - reward_ratio: Float.floor(delegator_reward_response.delegator_share / 10_000, 2) - }) - end) + defp at_start_snapshotting(block_number) do + # update ERC balance of the BlockReward contract + token = get(:token) - # perform SQL queries - {:ok, _} = - Chain.import(%{ - staking_pools: %{params: pool_entries}, - staking_pools_delegators: %{params: delegator_entries}, - timeout: :infinity - }) + if token != nil do + block_reward_address = address_string_to_bytes(get(:block_reward_contract).address) + token_contract_address_hash = token.contract_address_hash - if epoch_very_beginning or start_snapshotting 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.bytes, - 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" - }) + block_reward_balance = + BalanceReader.get_balances_of([ + %{ + token_contract_address_hash: token_contract_address_hash, + address_hash: block_reward_address.bytes, + 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" + }) - import_result = Chain.import(%{ + import_result = + Chain.import(%{ addresses: %{params: [%{hash: block_reward_address.bytes}], on_conflict: :nothing}, - address_current_token_balances: %{params: [%{ - address_hash: block_reward_address.bytes, - token_contract_address_hash: token_contract_address_hash, - block_number: block_number, - value: block_reward_balance, - value_fetched_at: DateTime.utc_now() - }]}, + address_current_token_balances: %{ + params: [ + %{ + address_hash: block_reward_address.bytes, + 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]} }) - with {:ok, _} <- import_result, do: - Publisher.broadcast([{ - :address_token_balances, [ - %{address_hash: block_reward_address.struct, block_number: block_number} - ] - }], - :on_demand - ) - end + with {:ok, _} <- import_result, + do: + Publisher.broadcast( + [ + { + :address_token_balances, + [ + %{address_hash: block_reward_address.struct, block_number: block_number} + ] + } + ], + :on_demand + ) end + end - if start_snapshotting do - # start snapshotting at the beginning of the staking epoch - cached_pool_staking_responses = if epoch_very_beginning do + defp do_start_snapshotting( + epoch_very_beginning, + pool_staking_responses, + global_responses, + contracts, + abi, + validators, + mining_to_staking_address + ) do + # start snapshotting at the beginning of the staking epoch + cached_pool_staking_responses = + if epoch_very_beginning do pool_staking_responses else %{} end - spawn(StakeSnapshotting, :do_snapshotting, [ - %{contracts: contracts, abi: abi, ets_table_name: @table_name}, - global_responses.epoch_number, - cached_pool_staking_responses, - validators.for_snapshot, # mining addresses of pending/current validators - mining_to_staking_address, - global_responses.epoch_start_block - 1 # the last block of the previous staking epoch - ]) - end - - # notify the UI about new block - Publisher.broadcast(:staking_update) + spawn(StakeSnapshotting, :do_snapshotting, [ + %{contracts: contracts, abi: abi, ets_table_name: @table_name}, + global_responses.epoch_number, + cached_pool_staking_responses, + # mining addresses of pending/current validators + validators.for_snapshot, + mining_to_staking_address, + # the last block of the previous staking epoch + global_responses.epoch_start_block - 1 + ]) end - def show_snapshotted_data(is_validator, validator_set_apply_block \\ nil, snapshotted_epoch_number \\ nil, epoch_number \\ nil) do - validator_set_apply_block = if validator_set_apply_block !== nil do - validator_set_apply_block - else - get(:validator_set_apply_block) - end - snapshotted_epoch_number = if snapshotted_epoch_number !== nil do - snapshotted_epoch_number - else - get(:snapshotted_epoch_number) - end - epoch_number = if epoch_number !== nil do - epoch_number + defp get_token(address) do + if address == "0x0000000000000000000000000000000000000000" do + # the token address is empty, so return nil + nil else - get(:epoch_number) + case Chain.string_to_address_hash(address) do + {:ok, address_hash} -> + # the token address has correct format, so try to read the token + # from DB or from its contract + case Chain.token_from_address_hash(address_hash) do + {:ok, token} -> + # the token is read from DB + token + + _ -> + fetch_token(address, address_hash) + end + + _ -> + # the token address has incorrect format + nil + end end - is_validator && validator_set_apply_block > 0 && snapshotted_epoch_number === epoch_number end - defp get_token(address) do - if address == "0x0000000000000000000000000000000000000000" do - nil # the token address is empty, so return nil - else - with {:ok, address_hash} <- Chain.string_to_address_hash(address) do - # the token address has correct format, so try to read the token - # from DB or from its contract - case Chain.token_from_address_hash(address_hash) do - {:ok, token} -> - token # the token is read from DB - _ -> - # the token doesn't exist in DB, so try - # to read it from a contract and then write to DB - token_functions = MetadataRetriever.get_functions_of(address) - - if map_size(token_functions) > 0 do - # the token is successfully read from its contract - token_params = Map.merge(token_functions, %{ - contract_address_hash: address, - type: "ERC-20" - }) - - # try to write the token info to DB - import_result = Chain.import(%{ - addresses: %{params: [%{hash: address}], on_conflict: :nothing}, - tokens: %{params: [token_params]} - }) - - with {:ok, _} <- import_result do - # the token is successfully added to DB, so return it as a result - case Chain.token_from_address_hash(address_hash) do - {:ok, token} -> token - _ -> nil - end - else - _ -> nil # cannot write the token info to DB - end - else - nil # cannot read the token info from its contract - end - end - else - _ -> nil # the token address has incorrect format + defp fetch_token(address, address_hash) do + # the token doesn't exist in DB, so try + # to read it from a contract and then write to DB + token_functions = MetadataRetriever.get_functions_of(address) + + if map_size(token_functions) > 0 do + # the token is successfully read from its contract + token_params = + Map.merge(token_functions, %{ + contract_address_hash: address, + type: "ERC-20" + }) + + # try to write the token info to DB + import_result = + Chain.import(%{ + addresses: %{params: [%{hash: address}], on_conflict: :nothing}, + tokens: %{params: [token_params]} + }) + + case import_result do + {:ok, _} -> + # the token is successfully added to DB, so return it as a result + case Chain.token_from_address_hash(address_hash) do + {:ok, token} -> token + _ -> nil + end + + _ -> + # cannot write the token info to DB + nil end + else + # cannot read the token info from its contract + nil end end diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 43b8f026f446..28a6f7400f3c 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -12,13 +12,13 @@ defmodule Explorer.Staking.StakeSnapshotting do alias Explorer.Staking.ContractReader def do_snapshotting( - %{contracts: contracts, abi: abi, ets_table_name: ets_table_name}, - epoch_number, - cached_pool_staking_responses, - pools_mining_addresses, - mining_to_staking_address, - block_number - ) do + %{contracts: contracts, abi: abi, ets_table_name: ets_table_name}, + epoch_number, + cached_pool_staking_responses, + pools_mining_addresses, + mining_to_staking_address, + block_number + ) do :ets.insert(ets_table_name, is_snapshotting: true) # get staking addresses for the pending validators @@ -36,10 +36,18 @@ defmodule Explorer.Staking.StakeSnapshotting do # use `cached_pool_staking_responses` when possible pool_staking_responses = pool_staking_addresses - |> Enum.map(fn staking_address_hash -> + |> Enum.map(fn staking_address_hash -> case Map.fetch(cached_pool_staking_responses, staking_address_hash) do {:ok, resp} -> - Map.merge(resp, ContractReader.perform_requests(snapshotted_pool_amounts_requests(staking_address_hash, block_number), contracts, abi)) + Map.merge( + resp, + ContractReader.perform_requests( + snapshotted_pool_amounts_requests(staking_address_hash, block_number), + contracts, + abi + ) + ) + :error -> ContractReader.perform_requests( ContractReader.active_delegators_request(staking_address_hash, block_number) ++ @@ -156,10 +164,14 @@ defmodule Explorer.Staking.StakeSnapshotting do # perform SQL queries case Chain.import(%{ - 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}, - timeout: :infinity - }) do + 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 + }, + timeout: :infinity + }) do {:ok, _} -> :ets.insert(ets_table_name, snapshotted_epoch_number: epoch_number) _ -> Logger.error("Cannot successfully finish snapshotting for the epoch #{epoch_number - 1}") end @@ -172,7 +184,10 @@ defmodule Explorer.Staking.StakeSnapshotting do defp snapshotted_pool_amounts_requests(pool_staking_address, block_number) do [ snapshotted_total_staked_amount: {:staking, "stakeAmountTotal", [pool_staking_address], block_number}, - snapshotted_self_staked_amount: snapshotted_staker_amount_request(pool_staking_address, pool_staking_address, block_number)[:snapshotted_stake_amount] + snapshotted_self_staked_amount: + snapshotted_staker_amount_request(pool_staking_address, pool_staking_address, block_number)[ + :snapshotted_stake_amount + ] ] end diff --git a/apps/explorer/priv/repo/migrations/20190807111216_remove_duplicate_indexes.exs b/apps/explorer/priv/repo/migrations/20190807111216_remove_duplicate_indexes.exs index 5c2ce8069173..45d873e1dea0 100644 --- a/apps/explorer/priv/repo/migrations/20190807111216_remove_duplicate_indexes.exs +++ b/apps/explorer/priv/repo/migrations/20190807111216_remove_duplicate_indexes.exs @@ -7,9 +7,7 @@ defmodule Explorer.Repo.Migrations.RemoveDuplicateIndexes do ) drop_if_exists( - index(:staking_pools_delegators, [:address_hash], - name: "staking_pools_delegators_address_hash_index" - ) + index(:staking_pools_delegators, [:address_hash], name: "staking_pools_delegators_address_hash_index") ) drop_if_exists(index(:transactions, [:to_address_hash], name: "transactions_to_address_hash_index")) diff --git a/apps/explorer/priv/repo/migrations/20191128144250_add_index_for_snapshotted_stake_amount.exs b/apps/explorer/priv/repo/migrations/20191128144250_add_index_for_snapshotted_stake_amount.exs index e7a0836235d9..e3b5432f9fd4 100644 --- a/apps/explorer/priv/repo/migrations/20191128144250_add_index_for_snapshotted_stake_amount.exs +++ b/apps/explorer/priv/repo/migrations/20191128144250_add_index_for_snapshotted_stake_amount.exs @@ -2,7 +2,7 @@ defmodule Explorer.Repo.Migrations.AddIndexForSnapshottedStakeAmount do use Ecto.Migration def change do - create( + create( index(:staking_pools_delegators, [:staking_address_hash, :snapshotted_stake_amount, :is_active], unique: false, name: :snapshotted_stake_amount_index From 10aae546bcfe5b2080268ef988abc1544657371d Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 1 Apr 2020 23:01:14 +0300 Subject: [PATCH 65/75] Fix tests: gettext, eslint --- apps/block_scout_web/assets/js/lib/modals.js | 18 ++--- .../assets/js/pages/address.js | 6 +- .../block_scout_web/assets/js/pages/stakes.js | 81 +++++++++---------- .../assets/js/pages/stakes/claim_reward.js | 78 +++++++++--------- .../assets/js/pages/stakes/utils.js | 8 +- apps/block_scout_web/priv/gettext/default.pot | 18 ++--- .../priv/gettext/en/LC_MESSAGES/default.po | 18 ++--- 7 files changed, 113 insertions(+), 114 deletions(-) diff --git a/apps/block_scout_web/assets/js/lib/modals.js b/apps/block_scout_web/assets/js/lib/modals.js index bff2f6bd4330..2240907ab6cd 100644 --- a/apps/block_scout_web/assets/js/lib/modals.js +++ b/apps/block_scout_web/assets/js/lib/modals.js @@ -21,11 +21,11 @@ $(document.body).on('hide.bs.modal', e => { $currentModal = null }) -export function currentModal() { +export function currentModal () { return $currentModal } -export function openModal($modal, unclosable) { +export function openModal ($modal, unclosable) { // Hide all tooltips before showing a modal, // since they are sticking on top of modal $('.tooltip').tooltip('hide') @@ -56,7 +56,7 @@ export function openModal($modal, unclosable) { } } -export function lockModal($modal, $submitButton = null, spinnerText = '') { +export function lockModal ($modal, $submitButton = null, spinnerText = '') { $modal.find('.close-modal').attr('disabled', true) const $button = $submitButton || $modal.find('.btn-add-full') @@ -78,11 +78,11 @@ export function lockModal($modal, $submitButton = null, spinnerText = '') { modalLocked = true } -export function unlockModal($modal, $submitButton = null) { +export function unlockModal ($modal, $submitButton = null) { $modal.find('.close-modal').attr('disabled', false) const $button = $submitButton || $modal.find('.btn-add-full') - const buttonText = $button.attr('data-text'); + const buttonText = $button.attr('data-text') $button.attr('disabled', false) @@ -97,28 +97,28 @@ export function unlockModal($modal, $submitButton = null) { modalLocked = false } -export function openErrorModal(title, text, unclosable) { +export function openErrorModal (title, text, unclosable) { const $modal = $('#errorStatusModal') $modal.find('.modal-status-title').text(title) $modal.find('.modal-status-text').html(text) openModal($modal, unclosable) } -export function openWarningModal(title, text) { +export function openWarningModal (title, text) { const $modal = $('#warningStatusModal') $modal.find('.modal-status-title').text(title) $modal.find('.modal-status-text').html(text) openModal($modal) } -export function openSuccessModal(title, text) { +export function openSuccessModal (title, text) { const $modal = $('#successStatusModal') $modal.find('.modal-status-title').text(title) $modal.find('.modal-status-text').text(text) openModal($modal) } -export function openQuestionModal(title, text, acceptCallback = null, exceptCallback = null, acceptText = 'Yes', exceptText = 'No') { +export function openQuestionModal (title, text, acceptCallback = null, exceptCallback = null, acceptText = 'Yes', exceptText = 'No') { const $modal = $('#questionStatusModal') $modal.find('.modal-status-title').text(title) diff --git a/apps/block_scout_web/assets/js/pages/address.js b/apps/block_scout_web/assets/js/pages/address.js index 7886312aac5a..2143c8650522 100644 --- a/apps/block_scout_web/assets/js/pages/address.js +++ b/apps/block_scout_web/assets/js/pages/address.js @@ -59,8 +59,8 @@ export function reducer (state = initialState, action) { } } -let fetchedTokenBalanceBlockNumber = 0; -function loadTokenBalance(blockNumber) { +let fetchedTokenBalanceBlockNumber = 0 +function loadTokenBalance (blockNumber) { if (blockNumber > fetchedTokenBalanceBlockNumber) { fetchedTokenBalanceBlockNumber = blockNumber setTimeout(loadTokenBalanceDropdown, 1000) @@ -136,7 +136,7 @@ if ($addressDetailsPage.length) { msg: humps.camelizeKeys(msg) })) addressChannel.on('token_balance', (msg) => loadTokenBalance( - msg.block_number + msg.block_number )) addressChannel.on('transaction', (msg) => { store.dispatch({ diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index 3b46cbb9c913..357b57de3a07 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -138,8 +138,8 @@ if ($stakesPage.length) { channel.on('staking_update', msg => { const state = store.getState() - const firstMsg = (state.currentBlockNumber == 0) - const accountChanged = (msg.account != state.account) + const firstMsg = (state.currentBlockNumber === 0) + const accountChanged = (msg.account !== state.account) store.dispatch({ type: 'BLOCK_CREATED', currentBlockNumber: msg.block_number }) @@ -158,7 +158,7 @@ if ($stakesPage.length) { if ( msg.staking_allowed !== state.stakingAllowed || msg.epoch_number > state.lastEpochNumber || - msg.validator_set_apply_block != state.validatorSetApplyBlock || + msg.validator_set_apply_block !== state.validatorSetApplyBlock || (state.refreshInterval && msg.block_number >= state.refreshBlockNumber + state.refreshInterval) ) { if (firstMsg || accountChanged) { @@ -259,50 +259,49 @@ if ($stakesPage.length) { initialize(store) } -function hideCurrentModal() { +function hideCurrentModal () { const $modal = currentModal() if ($modal) $modal.modal('hide') } -function initialize(store) { +function initialize (store) { if (window.ethereum) { const web3 = new Web3(window.ethereum) store.dispatch({ type: 'WEB3_DETECTED', web3 }) - let timeoutId + checkNetworkAndAccount(store, web3) - checkNetworkAndAccount() - - async function checkNetworkAndAccount() { - const networkId = await web3.eth.net.getId() - const state = store.getState() - let refresh = false - - if (!state.network || (networkId !== state.network.id)) { - setNetwork(networkId, store) - refresh = true - } + $stakesTop.on('click', '[data-selector="login-button"]', loginByMetamask) + } else { + refreshPageWrapper(store) + } +} - const accounts = await web3.eth.getAccounts() - const account = accounts[0] ? accounts[0].toLowerCase() : null +async function checkNetworkAndAccount (store, web3) { + let timeoutId + const networkId = await web3.eth.net.getId() + const state = store.getState() + let refresh = false - if (account !== state.account) { - setAccount(account, store) - } else if (refresh) { - refreshPageWrapper(store) - } + if (!state.network || (networkId !== state.network.id)) { + setNetwork(networkId, store) + refresh = true + } - clearTimeout(timeoutId) - timeoutId = setTimeout(checkNetworkAndAccount, 100) - } + const accounts = await web3.eth.getAccounts() + const account = accounts[0] ? accounts[0].toLowerCase() : null - $stakesTop.on('click', '[data-selector="login-button"]', loginByMetamask) - } else { + if (account !== state.account) { + setAccount(account, store) + } else if (refresh) { refreshPageWrapper(store) } + + clearTimeout(timeoutId) + timeoutId = setTimeout(checkNetworkAndAccount, 100) } -async function loginByMetamask() { +async function loginByMetamask () { event.stopPropagation() event.preventDefault() try { @@ -313,7 +312,7 @@ async function loginByMetamask() { } } -function refreshPageWrapper(store) { +function refreshPageWrapper (store) { let currentBlockNumber = store.getState().currentBlockNumber if (!currentBlockNumber) { currentBlockNumber = $('[data-block-number]', $stakesTop).data('blockNumber') @@ -327,7 +326,7 @@ function refreshPageWrapper(store) { $refreshInformer.hide() } -function reloadPoolList(msg, store) { +function reloadPoolList (msg, store) { store.dispatch({ type: 'RECEIVED_UPDATE', lastEpochNumber: msg.epoch_number, @@ -340,12 +339,12 @@ function reloadPoolList(msg, store) { } } -function resetFilterMy(store) { - $stakesPage.find('[pool-filter-my]').prop('checked', false); +function resetFilterMy (store) { + $stakesPage.find('[pool-filter-my]').prop('checked', false) store.dispatch({ type: 'FILTERS_UPDATED', filterMy: false }) } -function setAccount(account, store) { +function setAccount (account, store) { store.dispatch({ type: 'ACCOUNT_UPDATED', account }) if (!account) { resetFilterMy(store) @@ -367,7 +366,7 @@ function setAccount(account, store) { }) } -function setNetwork(networkId, store) { +function setNetwork (networkId, store) { hideCurrentModal() let network = { @@ -384,12 +383,12 @@ function setNetwork(networkId, store) { store.dispatch({ type: 'NETWORK_UPDATED', network }) } -function updateFilters(store, filterType) { - const filterBanned = $stakesPage.find('[pool-filter-banned]'); - const filterMy = $stakesPage.find('[pool-filter-my]'); +function updateFilters (store, filterType) { + const filterBanned = $stakesPage.find('[pool-filter-banned]') + const filterMy = $stakesPage.find('[pool-filter-my]') const state = store.getState() - if (filterType == 'my' && !state.account) { - filterMy.prop('checked', false); + if (filterType === 'my' && !state.account) { + filterMy.prop('checked', false) openWarningModal('Unauthorized', 'Please login with MetaMask') return } diff --git a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js index 8bc8c5c22183..788286c0cc3f 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js +++ b/apps/block_scout_web/assets/js/pages/stakes/claim_reward.js @@ -13,7 +13,7 @@ import { isSupportedNetwork } from './utils' let status = 'modalClosed' -export function openClaimRewardModal(event, store) { +export function openClaimRewardModal (event, store) { const state = store.getState() if (!state.account) { @@ -37,8 +37,8 @@ export function openClaimRewardModal(event, store) { const dotCounterInterval = poolsSearchingStarted() - const ref = channel.on('claim_reward_pools', msg_pools => { - $modalBody.html(msg_pools.html) + const ref = channel.on('claim_reward_pools', msgPools => { + $modalBody.html(msgPools.html) poolsSearchingFinished() }) $modal.on('shown.bs.modal', () => { @@ -54,7 +54,7 @@ export function openClaimRewardModal(event, store) { status = 'modalClosed' $modal.remove() }) - function poolsSearchingStarted() { + function poolsSearchingStarted () { const $waitingMessageContainer = $modalBody.find('p') let dotCounter = 0 @@ -63,12 +63,12 @@ export function openClaimRewardModal(event, store) { if (!waitingMessage.endsWith('.')) { waitingMessage = waitingMessage + '.' } - waitingMessage = waitingMessage.replace(/\.+$/g, " " + ".".repeat(dotCounter)) + waitingMessage = waitingMessage.replace(/\.+$/g, ' ' + '.'.repeat(dotCounter)) $waitingMessageContainer.text(waitingMessage) dotCounter = (dotCounter + 1) % 4 }, 500) } - function poolsSearchingFinished(error) { + function poolsSearchingFinished (error) { channel.off('claim_reward_pools', ref) $closeButton.removeClass('hidden') unlockModal($modal) @@ -80,7 +80,7 @@ export function openClaimRewardModal(event, store) { } } - openModal($modal, true); + openModal($modal, true) }).receive('error', (error) => { $(event.currentTarget).prop('disabled', false) openErrorModal('Claim Reward', error.reason) @@ -90,18 +90,18 @@ export function openClaimRewardModal(event, store) { }) } -export function connectionLost() { +export function connectionLost () { const errorMsg = 'Connection with server is lost. Please, reload the page.' - if (status == 'modalOpened') { + if (status === 'modalOpened') { status = 'modalClosed' openErrorModal('Claim Reward', errorMsg, true) - } else if (status == 'recalculation') { + } else if (status === 'recalculation') { const $recalculateButton = $('button.recalculate', currentModal()) displayInputError($recalculateButton, errorMsg) } } -function onPoolsFound($modal, $modalBody, channel, store) { +function onPoolsFound ($modal, $modalBody, channel, store) { const $poolsDropdown = $('select', $modalBody) const $epochChoiceRadio = $('input[name="epoch_choice"]', $modalBody) const $specifiedEpochsText = $('input.specified-epochs', $modalBody) @@ -110,7 +110,7 @@ function onPoolsFound($modal, $modalBody, channel, store) { let allowedEpochs = [] $poolsDropdown.on('change', () => { - if (status == 'recalculation' || status == 'claiming') return false + if (status === 'recalculation' || status === 'claiming') return false const data = $('option:selected', this).data() const tokenRewardSum = data.tokenRewardSum ? data.tokenRewardSum : '0' @@ -134,7 +134,7 @@ function onPoolsFound($modal, $modalBody, channel, store) { }) $epochChoiceRadio.on('change', () => { - if (status == 'recalculation' || status == 'claiming') return false + if (status === 'recalculation' || status === 'claiming') return false if ($('#epoch-choice-all', $modalBody).is(':checked')) { $specifiedEpochsText.addClass('hidden') showButton('submit', $modalBody) @@ -146,18 +146,18 @@ function onPoolsFound($modal, $modalBody, channel, store) { }) $specifiedEpochsText.on('input', () => { - if (status == 'recalculation' || status == 'claiming') return false + if (status === 'recalculation' || status === 'claiming') return false const filtered = filterSpecifiedEpochs($specifiedEpochsText.val()).toString() $specifiedEpochsText.val(filtered) const pointedEpochs = expandEpochsToArray(filtered) - const pointedEpochsAllowed = pointedEpochs.filter(item => allowedEpochs.indexOf(item) != -1) - - const needsRecalc = pointedEpochs.length > 0 && pointedEpochsAllowed.length != allowedEpochs.length + const pointedEpochsAllowed = pointedEpochs.filter(item => allowedEpochs.indexOf(item) !== -1) + + const needsRecalc = pointedEpochs.length > 0 && pointedEpochsAllowed.length !== allowedEpochs.length showButton(needsRecalc ? 'recalculate' : 'submit', $modalBody) - if (needsRecalc && pointedEpochsAllowed.length == 0) { + if (needsRecalc && pointedEpochsAllowed.length === 0) { $recalculateButton.prop('disabled', true) displayInputError($recalculateButton, 'The specified staking epochs are not in the allowed range') } else { @@ -167,14 +167,14 @@ function onPoolsFound($modal, $modalBody, channel, store) { }) $recalculateButton.on('click', (e) => { - if (status == 'recalculation' || status == 'claiming') return false + if (status === 'recalculation' || status === 'claiming') return false e.preventDefault() recalcStarted() const specifiedEpochs = $specifiedEpochsText.val().toString().replace(/[-|,]$/g, '').trim() $specifiedEpochsText.val(specifiedEpochs) - const epochs = expandEpochsToArray(specifiedEpochs).filter(item => allowedEpochs.indexOf(item) != -1) + const epochs = expandEpochsToArray(specifiedEpochs).filter(item => allowedEpochs.indexOf(item) !== -1) const poolStakingAddress = $poolsDropdown.val() const ref = channel.on('claim_reward_recalculations', result => { recalcFinished(result) @@ -187,12 +187,12 @@ function onPoolsFound($modal, $modalBody, channel, store) { }).receive('timeout', () => { recalcFinished({error: 'Connection timeout'}) }) - function recalcStarted() { + function recalcStarted () { status = 'recalculation' hideInputError($recalculateButton) - lockUI(true, $modal, $recalculateButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); + lockUI(true, $modal, $recalculateButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText) } - function recalcFinished(result) { + function recalcFinished (result) { channel.off('claim_reward_recalculations', ref) status = 'modalOpened' if (result.error) { @@ -200,21 +200,21 @@ function onPoolsFound($modal, $modalBody, channel, store) { } else { showButton('submit', $modalBody, result) } - lockUI(false, $modal, $recalculateButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); + lockUI(false, $modal, $recalculateButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText) } }) $submitButton.on('click', async (e) => { - if (status == 'recalculation' || status == 'claiming') return false + if (status === 'recalculation' || status === 'claiming') return false e.preventDefault() const specifiedEpochs = $specifiedEpochsText.val().toString().replace(/[-|,]$/g, '').trim() - const epochs = expandEpochsToArray(specifiedEpochs).filter(item => allowedEpochs.indexOf(item) != -1) + const epochs = expandEpochsToArray(specifiedEpochs).filter(item => allowedEpochs.indexOf(item) !== -1) const poolStakingAddress = $poolsDropdown.val() claimStarted() - function claimStarted() { + function claimStarted () { status = 'claiming' hideInputError($submitButton) lockUI( @@ -233,7 +233,7 @@ function onPoolsFound($modal, $modalBody, channel, store) { const from = state.account const web3 = state.web3 - if (gasLimit === NaN) { + if (isNaN(gasLimit)) { claimFinished('Invalid gas limit. Please, contact support.') } else if (!stakingContract) { claimFinished('Staking contract is undefined. Please, contact support.') @@ -248,7 +248,7 @@ function onPoolsFound($modal, $modalBody, channel, store) { from, gasPrice: web3.utils.toWei('1', 'gwei'), gas: Math.ceil(gasLimit * 1.2) // +20% reserve to ensure enough gas - }, async function(error, txHash) { + }, async function (error, txHash) { if (error) { claimFinished(error.message) } else { @@ -279,8 +279,8 @@ function onPoolsFound($modal, $modalBody, channel, store) { }) } } - function claimFinished(error) { - lockUI(false, $modal, $submitButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText); + function claimFinished (error) { + lockUI(false, $modal, $submitButton, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText) if (error) { status = 'modalOpened' displayInputError($submitButton, error) @@ -292,7 +292,7 @@ function onPoolsFound($modal, $modalBody, channel, store) { }) } -function lockUI(lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText, spinnerText) { +function lockUI (lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $specifiedEpochsText, spinnerText) { if (lock) { lockModal($modal, $button, spinnerText) } else { @@ -303,11 +303,11 @@ function lockUI(lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $speci $specifiedEpochsText.prop('disabled', lock) } -function sleep(seconds) { +function sleep (seconds) { return new Promise(resolve => setTimeout(resolve, seconds * 1000)) } -function showButton(type, $modalBody, calculations) { +function showButton (type, $modalBody, calculations) { const $recalculateButton = $('button.recalculate', $modalBody) const $submitButton = $('button.submit', $modalBody) @@ -315,7 +315,7 @@ function showButton(type, $modalBody, calculations) { const $nativeRewardSum = $('#native-reward-sum', $modalBody) const $gasLimit = $('#tx-gas-limit', $modalBody) - if (type == 'submit') { + if (type === 'submit') { $recalculateButton.addClass('hidden') $submitButton.removeClass('hidden') @@ -335,9 +335,9 @@ function showButton(type, $modalBody, calculations) { } } -function expandEpochsToArray(epochs) { +function expandEpochsToArray (epochs) { let filtered = epochs.toString().replace(/[-|,]$/g, '').trim() - if (filtered == '') return [] + if (filtered === '') return [] let ranges = filtered.split(',') ranges = ranges.map((v) => { if (v.indexOf('-') > -1) { @@ -359,11 +359,11 @@ function expandEpochsToArray(epochs) { ranges = ranges.reduce((acc, val) => acc.concat(val), []) // similar to ranges.flat() ranges.sort((a, b) => a - b) ranges = [...new Set(ranges)] // make unique - ranges = ranges.filter(epoch => epoch != 0) + ranges = ranges.filter(epoch => epoch !== 0) return ranges } -function filterSpecifiedEpochs(epochs) { +function filterSpecifiedEpochs (epochs) { let filtered = epochs.toString() filtered = filtered.replace(/[^0-9,-]+/g, '') filtered = filtered.replace(/-{2,}/g, '-') diff --git a/apps/block_scout_web/assets/js/pages/stakes/utils.js b/apps/block_scout_web/assets/js/pages/stakes/utils.js index 32fcd7f459e3..58b8e2620cb6 100644 --- a/apps/block_scout_web/assets/js/pages/stakes/utils.js +++ b/apps/block_scout_web/assets/js/pages/stakes/utils.js @@ -3,7 +3,7 @@ import Chart from 'chart.js' import { refreshPage } from '../../lib/async_listing_load' import { openErrorModal, openSuccessModal, openWarningModal } from '../../lib/modals' -export async function makeContractCall(call, store) { +export async function makeContractCall (call, store) { let gas, timeout let resultShown = false const account = store.getState().account @@ -52,7 +52,7 @@ export async function makeContractCall(call, store) { } } -export function setupChart($canvas, self, total) { +export function setupChart ($canvas, self, total) { const primaryColor = $('.stakes-progress-graph-thing-for-getting-color').css('color') const backgroundColors = [ primaryColor, @@ -83,7 +83,7 @@ export function setupChart($canvas, self, total) { }) } -export function checkForTokenDefinition(store) { +export function checkForTokenDefinition (store) { if (store.getState().stakingTokenDefined) { return true } @@ -91,7 +91,7 @@ export function checkForTokenDefinition(store) { return false } -export function isSupportedNetwork(store) { +export function isSupportedNetwork (store) { const state = store.getState() if (state.network && state.network.authorized) { return true diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index b83cb656b6cf..c8b4a7a0149d 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -2348,24 +2348,24 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:258 +#: lib/block_scout_web/channels/stakes_channel.ex:679 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:260 -#: lib/block_scout_web/channels/stakes_channel.ex:295 +#: lib/block_scout_web/channels/stakes_channel.ex:682 +#: lib/block_scout_web/channels/stakes_channel.ex:729 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:565 +#: lib/block_scout_web/channels/stakes_channel.ex:629 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:262 -#: lib/block_scout_web/channels/stakes_channel.ex:297 +#: lib/block_scout_web/channels/stakes_channel.ex:686 +#: lib/block_scout_web/channels/stakes_channel.ex:733 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" @@ -2435,17 +2435,17 @@ msgid "The staking epochs for which the reward could be claimed:" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:291 +#: lib/block_scout_web/channels/stakes_channel.ex:723 msgid "Staking epochs are not specified or not in the allowed range" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:293 +#: lib/block_scout_web/channels/stakes_channel.ex:726 msgid "Unknown pool staking address. Please, contact support" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:289 +#: lib/block_scout_web/channels/stakes_channel.ex:720 msgid "Reward calculating is already in progress for this address" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index b83cb656b6cf..c8b4a7a0149d 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -2348,24 +2348,24 @@ msgid "Searching for pools you have ever staked into. Please, wait..." msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:258 +#: lib/block_scout_web/channels/stakes_channel.ex:679 msgid "Pools searching is already in progress for this address" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:260 -#: lib/block_scout_web/channels/stakes_channel.ex:295 +#: lib/block_scout_web/channels/stakes_channel.ex:682 +#: lib/block_scout_web/channels/stakes_channel.ex:729 msgid "Unknown staker address. Please, choose your account in MetaMask" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:565 +#: lib/block_scout_web/channels/stakes_channel.ex:629 msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:262 -#: lib/block_scout_web/channels/stakes_channel.ex:297 +#: lib/block_scout_web/channels/stakes_channel.ex:686 +#: lib/block_scout_web/channels/stakes_channel.ex:733 msgid "Unknown address of Staking contract. Please, contact support" msgstr "" @@ -2435,17 +2435,17 @@ msgid "The staking epochs for which the reward could be claimed:" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:291 +#: lib/block_scout_web/channels/stakes_channel.ex:723 msgid "Staking epochs are not specified or not in the allowed range" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:293 +#: lib/block_scout_web/channels/stakes_channel.ex:726 msgid "Unknown pool staking address. Please, contact support" msgstr "" #, elixir-format -#: lib/block_scout_web/channels/stakes_channel.ex:289 +#: lib/block_scout_web/channels/stakes_channel.ex:720 msgid "Reward calculating is already in progress for this address" msgstr "" From 38667bc2641c4be2de3da8a01ed73f9706d28e85 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 1 Apr 2020 23:14:09 +0300 Subject: [PATCH 66/75] Fix tests: dialyzer (add entries to .dialyzer-iggnore) --- .dialyzer-ignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.dialyzer-ignore b/.dialyzer-ignore index 86584c2cb5a6..9af33f21ff44 100644 --- a/.dialyzer-ignore +++ b/.dialyzer-ignore @@ -12,4 +12,6 @@ apps/block_scout_web/lib/block_scout_web/views/layout_view.ex:175: The call 'Eli apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The pattern 'false' can never match the type 'true' apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The test 5 == 'infinity' can never evaluate to 'true' lib/block_scout_web/router.ex:1 -lib/phoenix/router.ex:324 \ No newline at end of file +lib/phoenix/router.ex:324 +lib/explorer/staking/stake_snapshotting.ex:14: Function do_snapshotting/6 has no local return +lib/explorer/staking/stake_snapshotting.ex:166 \ No newline at end of file From 77b493e37adc4f65763a9047e4251fdd96705011 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Thu, 2 Apr 2020 19:43:40 +0300 Subject: [PATCH 67/75] Fix 3 failed tests in stakes_controller_test.exs --- .../block_scout_web/controllers/stakes_controller_test.exs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/block_scout_web/test/block_scout_web/controllers/stakes_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/stakes_controller_test.exs index bce571ce2e1c..a98d1bd15532 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/stakes_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/stakes_controller_test.exs @@ -21,7 +21,7 @@ defmodule BlockScoutWeb.StakesControllerTest do test "returns rendered table", %{conn: conn} do address_hashes = Enum.map(1..4, fn _ -> insert(:staking_pool) end) - conn = get(conn, validators_path(conn, :index, %{type: "JSON"})) + conn = get(conn, validators_path(conn, :index, %{type: "JSON", filterMy: true})) assert {:ok, %{"items" => items, "next_page_path" => _}} = Poison.decode(conn.resp_body) assert Enum.count(items) == Enum.count(address_hashes) end @@ -31,7 +31,7 @@ defmodule BlockScoutWeb.StakesControllerTest do test "returns rendered table", %{conn: conn} do address_hashes = Enum.map(1..4, fn _ -> insert(:staking_pool) end) - conn = get(conn, active_pools_path(conn, :index, %{type: "JSON"})) + conn = get(conn, active_pools_path(conn, :index, %{type: "JSON", filterMy: true})) assert {:ok, %{"items" => items, "next_page_path" => _}} = Poison.decode(conn.resp_body) assert Enum.count(items) == Enum.count(address_hashes) end @@ -41,7 +41,7 @@ defmodule BlockScoutWeb.StakesControllerTest do test "returns rendered table", %{conn: conn} do address_hashes = Enum.map(1..4, fn _ -> insert(:staking_pool, is_active: false) end) - conn = get(conn, inactive_pools_path(conn, :index, %{type: "JSON"})) + conn = get(conn, inactive_pools_path(conn, :index, %{type: "JSON", filterMy: true})) assert {:ok, %{"items" => items, "next_page_path" => _}} = Poison.decode(conn.resp_body) assert Enum.count(items) == Enum.count(address_hashes) end From 7521d64215e3ec50bf7fa612d4730bd24a6cf467 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Thu, 2 Apr 2020 23:13:48 +0300 Subject: [PATCH 68/75] Fix bug in dropdown with tokens appearance in address view page --- apps/block_scout_web/assets/js/pages/address.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/block_scout_web/assets/js/pages/address.js b/apps/block_scout_web/assets/js/pages/address.js index 2143c8650522..488d5dd395be 100644 --- a/apps/block_scout_web/assets/js/pages/address.js +++ b/apps/block_scout_web/assets/js/pages/address.js @@ -64,6 +64,8 @@ function loadTokenBalance (blockNumber) { if (blockNumber > fetchedTokenBalanceBlockNumber) { fetchedTokenBalanceBlockNumber = blockNumber setTimeout(loadTokenBalanceDropdown, 1000) + } else { + loadTokenBalanceDropdown() } } From 3df924d1fd907f301c94a9a2b43c8d9bd6d61b4d Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Fri, 3 Apr 2020 13:57:49 +0300 Subject: [PATCH 69/75] Fix the order of mock calls in contract_state_test.exs --- .../explorer/staking/contract_state_test.exs | 581 ++++++++++++++++-- 1 file changed, 543 insertions(+), 38 deletions(-) diff --git a/apps/explorer/test/explorer/staking/contract_state_test.exs b/apps/explorer/test/explorer/staking/contract_state_test.exs index 578cf7795f13..b87a1fc0d4aa 100644 --- a/apps/explorer/test/explorer/staking/contract_state_test.exs +++ b/apps/explorer/test/explorer/staking/contract_state_test.exs @@ -9,7 +9,6 @@ defmodule Explorer.Staking.ContractStateTest do alias Explorer.Repo alias Explorer.Staking.ContractState - setup :verify_on_exit! setup :set_mox_global test "when disabled, returns default values" do @@ -36,9 +35,6 @@ defmodule Explorer.Staking.ContractStateTest do Publisher.broadcast([{:blocks, [%Explorer.Chain.Block{number: 5999}]}], :realtime) Publisher.broadcast([{:blocks, [%Explorer.Chain.Block{number: 6000}]}], :realtime) - set_mox() - Publisher.broadcast([{:blocks, [%Explorer.Chain.Block{number: 6001}]}], :realtime) - Process.sleep(500) assert ContractState.get(:epoch_number) == 74 @@ -47,8 +43,8 @@ defmodule Explorer.Staking.ContractStateTest do assert ContractState.get(:min_candidate_stake) == 1_000_000_000_000_000_000 assert ContractState.get(:token_contract_address) == "0x6f7a73c96bd56f8b0debc795511eda135e105ea3" - assert Repo.aggregate(StakingPool, :count, :id) == 4 - assert Repo.aggregate(StakingPoolsDelegator, :count, :id) == 7 + assert Repo.aggregate(StakingPool, :count, :id) == 7 + assert Repo.aggregate(StakingPoolsDelegator, :count, :id) == 10 end defp set_init_mox() do @@ -60,8 +56,8 @@ defmodule Explorer.Staking.ContractStateTest do {:ok, format_responses([ - "0x0000000000000000000000001000000000000000000000000000000000000001", - "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3" + "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", + "0x0000000000000000000000001000000000000000000000000000000000000001" ])} end ) @@ -81,23 +77,58 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 13 + assert length(requests) == 4 {:ok, format_responses([ - "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + # 1 decimals + "0x0000000000000000000000000000000000000000000000000000000000000012", + # 2 name + "0x7465737400000000000000000000000000000000000000000000000000000000", + # 3 symbol + "0x5453540000000000000000000000000000000000000000000000000000000000", + # 4 totalSupply + "0x00000000000000000000000000000000000000000000000000000000000f4240" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 14 + + {:ok, + format_responses([ + # 1 getPools + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577", + # 2 stakingEpochEndBlock + "0x0000000000000000000000000000000000000000000000000000000000001770", + # 3 stakingEpoch "0x000000000000000000000000000000000000000000000000000000000000004a", + # 4 stakingEpochStartBlock "0x0000000000000000000000000000000000000000000000000000000000001760", - "0x0000000000000000000000000000000000000000000000000000000000001770", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577", + # 5 getPoolsInactive "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e", - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577", + # 6 candidateMinStake + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + # 7 delegatorMinStake + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + # 8 getPoolsLikelihood "0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000514000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000044c", + # 9 getPoolsToBeElected + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577", + # 10 areStakeAndWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 11 erc677TokenContract + "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", + # 12 unremovableValidator + "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", + # 13 getValidators "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3", - "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6" + # 14 validatorSetApplyBlock + "0x0000000000000000000000000000000000000000000000000000000000000001" ])} end ) @@ -106,46 +137,146 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 36 + assert length(requests) == 1 {:ok, format_responses([ - "0x000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78", - "0x0000000000000000000000000000000000000000000000000000000000000001", + # 1 validatorMinRewardPercent + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 3 + + {:ok, + format_responses([ + # 1 stakingByMiningAddress + "0x000000000000000000000000a5063b12c4d6ca73e189ef071f6712d048175055", + # 2 stakingByMiningAddress + "0x0000000000000000000000003efbc7ae3e8f608f1336076a4004aa191d2ca7c7", + # 3 stakingByMiningAddress + "0x0000000000000000000000006f2859f4e38423b85ff2152bdc7c43720171a12f" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 49 + + {:ok, + format_responses([ + # 1 poolDelegators "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2 poolDelegatorsInactive "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3 isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4 miningByStakingAddress + "0x000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 stakeAmountTotal "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7 validatorRewardPercent "0x000000000000000000000000000000000000000000000000000000000003d090", - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", - "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240", - "0x000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb", - "0x0000000000000000000000000000000000000000000000000000000000000001", + + # 1 poolDelegators "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2 poolDelegatorsInactive "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3 isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4 miningByStakingAddress + "0x000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 6 stakeAmountTotal "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 7 validatorRewardPercent "0x0000000000000000000000000000000000000000000000000000000000051615", - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9", - "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240", - "0x000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3", - "0x0000000000000000000000000000000000000000000000000000000000000001", + + # 1 poolDelegators "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000009d99f80d3b59cca783f11918311fb31212fb7500000000000000000000000008d6867958e1cab5c39160a1d30fbc68ac55b45ef", + # 2 poolDelegatorsInactive "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", + # 3 isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4 miningByStakingAddress + "0x000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 6 stakeAmountTotal + "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", + # 7 validatorRewardPercent "0x0000000000000000000000000000000000000000000000000000000000051615", - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000db9cb2478d917719c53862008672166808258577", - "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240", - "0x000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", - "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 1 poolDelegators "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e4978fac7adfc925352dbc7e1962e6545142eeee", + # 2 poolDelegatorsInactive "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000029a2241af62c0000", + # 3 isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 miningByStakingAddress + "0x000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 6 stakeAmountTotal + "0x00000000000000000000000000000000000000000000000029a2241af62c0000", + # 7 validatorRewardPercent "0x0000000000000000000000000000000000000000000000000000000000051615", - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e", - "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240" + + # 1 poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2 poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3 isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4 miningByStakingAddress + "0x00000000000000000000000015b18132380cbc7e200e2c0b46de3cad06f53f36", + # 5 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7 validatorRewardPercent + "0x000000000000000000000000000000000000000000000000000000000003d090", + + # 1 poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2 poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3 isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4 miningByStakingAddress + "0x0000000000000000000000006defba7208e8fc11d8c7c32e10be08c19b155089", + # 5 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7 validatorRewardPercent + "0x000000000000000000000000000000000000000000000000000000000003d090", + + # 1 poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2 poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3 isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4 miningByStakingAddress + "0x0000000000000000000000006a8a0060ed0d1c083b34d9122ab61cbe626a59f6", + # 5 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7 validatorRewardPercent + "0x000000000000000000000000000000000000000000000000000000000003d090" ])} end ) @@ -154,37 +285,113 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 28 + assert length(requests) == 49 {:ok, format_responses([ + # 1 areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 validatorCounter "0x000000000000000000000000000000000000000000000000000000000000004b", + # 7 banCounter "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 1 areDelegatorsBanned "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 banReason "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 bannedUntil "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 bannedDelegatorsUntil "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 isValidatorBanned "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 validatorCounter "0x0000000000000000000000000000000000000000000000000000000000000002", + # 7 banCounter "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 1 areDelegatorsBanned "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 banReason "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 bannedUntil "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 bannedDelegatorsUntil "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 isValidatorBanned "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 validatorCounter "0x000000000000000000000000000000000000000000000000000000000000004a", + # 7 banCounter "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 1 areDelegatorsBanned "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 banReason "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 bannedUntil "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 bannedDelegatorsUntil "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 isValidatorBanned "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 validatorCounter "0x000000000000000000000000000000000000000000000000000000000000004a", + # 7 banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 1 areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 isValidatorBanned "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 validatorCounter + "0x000000000000000000000000000000000000000000000000000000000000004b", + # 7 banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 1 areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 bannedUntil "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 validatorCounter + "0x000000000000000000000000000000000000000000000000000000000000004b", + # 7 banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 1 areDelegatorsBanned "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 banReason "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 bannedUntil "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 validatorCounter + "0x000000000000000000000000000000000000000000000000000000000000004b", + # 7 banCounter "0x0000000000000000000000000000000000000000000000000000000000000000" ])} end @@ -194,44 +401,342 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 35 + assert length(requests) == 50 {:ok, format_responses([ + # 1 maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 1 maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 7 + + {:ok, + format_responses([ + # 1 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 10 + + {:ok, + format_responses([ + # 1 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10 delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # 1 balanceOf + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 4 + + {:ok, + format_responses([ + # 1 decimals + "0x0000000000000000000000000000000000000000000000000000000000000012", + # 2 name + "0x7465737400000000000000000000000000000000000000000000000000000000", + # 3 symbol + "0x5453540000000000000000000000000000000000000000000000000000000000", + # 4 totalSupply + "0x00000000000000000000000000000000000000000000000000000000000f4240" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 3 + + {:ok, + format_responses([ + # 1 poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2 stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 3 + + {:ok, + format_responses([ + # 1 poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2 stakeAmountTotal "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 3 + + {:ok, + format_responses([ + # 1 poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2 stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # 1 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # 1 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # 1 stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 3 + + {:ok, + format_responses([ + # 1 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 3 + + {:ok, + format_responses([ + # 1 delegatorShare "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 delegatorShare "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 delegatorShare "0x0000000000000000000000000000000000000000000000000000000000000000" ])} end From 45f810196402cd1d3dc869a364a85855ea0b8f63 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 8 May 2020 14:51:51 +0300 Subject: [PATCH 70/75] checkNetworkAndAccount function fix and small improvements --- .../block_scout_web/assets/js/pages/stakes.js | 6 ++--- .../_stakes_modal_become_candidate.html.eex | 4 ++-- .../_stakes_modal_delegators_list.html.eex | 2 +- apps/block_scout_web/priv/gettext/default.pot | 24 +++++++++---------- .../priv/gettext/en/LC_MESSAGES/default.po | 24 +++++++++---------- .../controllers/stakes_controller_test.exs | 18 +++++++------- apps/explorer/test/support/factory.ex | 2 +- 7 files changed, 40 insertions(+), 40 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index 357b57de3a07..8141895e70e2 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -278,7 +278,6 @@ function initialize (store) { } async function checkNetworkAndAccount (store, web3) { - let timeoutId const networkId = await web3.eth.net.getId() const state = store.getState() let refresh = false @@ -297,8 +296,9 @@ async function checkNetworkAndAccount (store, web3) { refreshPageWrapper(store) } - clearTimeout(timeoutId) - timeoutId = setTimeout(checkNetworkAndAccount, 100) + setTimeout(() => { + checkNetworkAndAccount(store, web3) + }, 100) } async function loginByMetamask () { diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex index fbab143aa32d..d919e20a4462 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex @@ -23,8 +23,8 @@
<%= render BlockScoutWeb.CommonComponentsView, "_btn_add_full.html", text: gettext("Become a Candidate"), extra_class: "full-width" %>
- <%= render BlockScoutWeb.CommonComponentsView, "_modal_bottom_disclaimer.html", text: gettext("

To become a candidate, your staking address must be funded with STAKE tokens and xDai coins, and your Parity node must be active and configured with the mining address you specify here.

-

To become a delegator, close this window and select an address from the list of pools you would like to place stake on. Click the Stake button next to the address to begin the process.

") |> raw() %> + <%= render BlockScoutWeb.CommonComponentsView, "_modal_bottom_disclaimer.html", text: gettext("

To become a candidate, your staking address must be funded with %{symbol} tokens and xDai coins, and your OpenEthereum node must be active and configured with the mining address you specify here.

+

To become a delegator, close this window and select an address from the list of pools you would like to place stake on. Click the Stake button next to the address to begin the process.

", symbol: @token.symbol) |> raw() %>
\ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex index da30ad3f0449..b7e414186fb1 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex @@ -35,7 +35,7 @@ gettext("Current Stake Amount") end - render BlockScoutWeb.StakesView, "_stakes_th.html", title: amount_col_title, tooltip: gettext("Amount of STAKE placed by an address") + render BlockScoutWeb.StakesView, "_stakes_th.html", title: amount_col_title, tooltip: gettext("Amount of %{symbol} placed by an address.", symbol: @token.symbol) %>
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index c8b4a7a0149d..daa8719b02bc 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -1892,12 +1892,6 @@ msgstr[1] "" msgid "

Pending stake (stake placed on a candidate pool or placed during the current staking epoch) may be withdrawn now.

\n

Active stake (stake available after the current epoch) can be ordered for withdrawal from the pool, and will be available to claim after the current staking epoch is complete.

\n

If you have already ordered (and the staking window is still open), you may increase your current order by entering a positive value, or decrease your current order by entering a negative value in the box and clicking 'Order Withdrawal'. You must either keep the minimum stake amount in the pool, or order your entire stake for withdrawal.

\n" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:26 -msgid "

To become a candidate, your staking address must be funded with STAKE tokens and xDai coins, and your Parity node must be active and configured with the mining address you specify here.

\n

To become a delegator, close this window and select an address from the list of pools you would like to place stake on. Click the Stake button next to the address to begin the process.

" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/layout/_topnav.html.eex:131 #: lib/block_scout_web/templates/stakes/_stakes_tabs.html.eex:11 @@ -1918,12 +1912,6 @@ msgstr "" msgid "Amount" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:38 -msgid "Amount of STAKE placed by an address" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_withdraw.html.eex:25 msgid "Available Now:" @@ -2453,3 +2441,15 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_title.html.eex:14 msgid "Show only those I have stake in" msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:38 +msgid "Amount of %{symbol} placed by an address." +msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:26 +msgid "

To become a candidate, your staking address must be funded with %{symbol} tokens and xDai coins, and your OpenEthereum node must be active and configured with the mining address you specify here.

\n

To become a delegator, close this window and select an address from the list of pools you would like to place stake on. Click the Stake button next to the address to begin the process.

" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index c8b4a7a0149d..77c352ea1dee 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -1892,12 +1892,6 @@ msgstr[1] "" msgid "

Pending stake (stake placed on a candidate pool or placed during the current staking epoch) may be withdrawn now.

\n

Active stake (stake available after the current epoch) can be ordered for withdrawal from the pool, and will be available to claim after the current staking epoch is complete.

\n

If you have already ordered (and the staking window is still open), you may increase your current order by entering a positive value, or decrease your current order by entering a negative value in the box and clicking 'Order Withdrawal'. You must either keep the minimum stake amount in the pool, or order your entire stake for withdrawal.

\n" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:26 -msgid "

To become a candidate, your staking address must be funded with STAKE tokens and xDai coins, and your Parity node must be active and configured with the mining address you specify here.

\n

To become a delegator, close this window and select an address from the list of pools you would like to place stake on. Click the Stake button next to the address to begin the process.

" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/layout/_topnav.html.eex:131 #: lib/block_scout_web/templates/stakes/_stakes_tabs.html.eex:11 @@ -1918,12 +1912,6 @@ msgstr "" msgid "Amount" msgstr "" -#, elixir-format -#: -#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:38 -msgid "Amount of STAKE placed by an address" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/stakes/_stakes_modal_withdraw.html.eex:25 msgid "Available Now:" @@ -2453,3 +2441,15 @@ msgstr "" #: lib/block_scout_web/templates/stakes/_stakes_title.html.eex:14 msgid "Show only those I have stake in" msgstr "" + +#, elixir-format +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:38 +msgid "Amount of %{symbol} placed by an address." +msgstr "" + +#, elixir-format, fuzzy +#: +#: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:26 +msgid "

To become a candidate, your staking address must be funded with %{symbol} tokens and xDai coins, and your OpenEthereum node must be active and configured with the mining address you specify here.

\n

To become a delegator, close this window and select an address from the list of pools you would like to place stake on. Click the Stake button next to the address to begin the process.

" +msgstr "" diff --git a/apps/block_scout_web/test/block_scout_web/controllers/stakes_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/stakes_controller_test.exs index a98d1bd15532..add0e7d4b73f 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/stakes_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/stakes_controller_test.exs @@ -19,31 +19,31 @@ defmodule BlockScoutWeb.StakesControllerTest do end test "returns rendered table", %{conn: conn} do - address_hashes = Enum.map(1..4, fn _ -> insert(:staking_pool) end) + pools = Enum.map(1..4, fn _ -> insert(:staking_pool) end) - conn = get(conn, validators_path(conn, :index, %{type: "JSON", filterMy: true})) + conn = get(conn, validators_path(conn, :index, %{type: "JSON", filterMy: false})) assert {:ok, %{"items" => items, "next_page_path" => _}} = Poison.decode(conn.resp_body) - assert Enum.count(items) == Enum.count(address_hashes) + assert Enum.count(items) == Enum.count(pools) end end describe "GET active_pools/2" do test "returns rendered table", %{conn: conn} do - address_hashes = Enum.map(1..4, fn _ -> insert(:staking_pool) end) + pools = Enum.map(1..4, fn _ -> insert(:staking_pool) end) - conn = get(conn, active_pools_path(conn, :index, %{type: "JSON", filterMy: true})) + conn = get(conn, active_pools_path(conn, :index, %{type: "JSON", filterMy: false})) assert {:ok, %{"items" => items, "next_page_path" => _}} = Poison.decode(conn.resp_body) - assert Enum.count(items) == Enum.count(address_hashes) + assert Enum.count(items) == Enum.count(pools) end end describe "GET inactive_pools/2" do test "returns rendered table", %{conn: conn} do - address_hashes = Enum.map(1..4, fn _ -> insert(:staking_pool, is_active: false) end) + pools = Enum.map(1..4, fn _ -> insert(:staking_pool, is_active: false) end) - conn = get(conn, inactive_pools_path(conn, :index, %{type: "JSON", filterMy: true})) + conn = get(conn, inactive_pools_path(conn, :index, %{type: "JSON", filterMy: false})) assert {:ok, %{"items" => items, "next_page_path" => _}} = Poison.decode(conn.resp_body) - assert Enum.count(items) == Enum.count(address_hashes) + assert Enum.count(items) == Enum.count(pools) end end end diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index a05ef91a204d..2ed0ef43897e 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -636,7 +636,7 @@ defmodule Explorer.Factory do is_banned: false, is_validator: true, total_staked_amount: wei_per_ether * 500, - self_staked_amount: wei_per_ether * 300, + self_staked_amount: wei_per_ether * 500, was_banned_count: 0, was_validator_count: 1 } From d5ff9d34813baaba19c39e2e7fe0bfa94b2f7bc2 Mon Sep 17 00:00:00 2001 From: Vadim Date: Mon, 11 May 2020 15:07:36 +0300 Subject: [PATCH 71/75] Fix viewing_addresses_test.exs --- apps/block_scout_web/assets/js/pages/address.js | 2 -- .../test/block_scout_web/features/viewing_addresses_test.exs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/block_scout_web/assets/js/pages/address.js b/apps/block_scout_web/assets/js/pages/address.js index 488d5dd395be..2143c8650522 100644 --- a/apps/block_scout_web/assets/js/pages/address.js +++ b/apps/block_scout_web/assets/js/pages/address.js @@ -64,8 +64,6 @@ function loadTokenBalance (blockNumber) { if (blockNumber > fetchedTokenBalanceBlockNumber) { fetchedTokenBalanceBlockNumber = blockNumber setTimeout(loadTokenBalanceDropdown, 1000) - } else { - loadTokenBalanceDropdown() } } diff --git a/apps/block_scout_web/test/block_scout_web/features/viewing_addresses_test.exs b/apps/block_scout_web/test/block_scout_web/features/viewing_addresses_test.exs index bb223077a2ee..1f7f2781de02 100644 --- a/apps/block_scout_web/test/block_scout_web/features/viewing_addresses_test.exs +++ b/apps/block_scout_web/test/block_scout_web/features/viewing_addresses_test.exs @@ -440,7 +440,7 @@ defmodule BlockScoutWeb.ViewingAddressesTest do describe "viewing token balances" do setup do block = insert(:block) - lincoln = insert(:address, fetched_coin_balance: 5) + lincoln = insert(:address, fetched_coin_balance: 5, fetched_coin_balance_block_number: block.number) taft = insert(:address, fetched_coin_balance: 5) contract_address = insert(:contract_address) From f7c61f4ee8c8ddb2e5c22c546228ea5cec2263e1 Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 13 May 2020 16:16:47 +0300 Subject: [PATCH 72/75] Update contract_state_test.exs --- .../lib/explorer/staking/contract_state.ex | 8 +- .../explorer/staking/contract_state_test.exs | 1408 ++++++++++------- 2 files changed, 854 insertions(+), 562 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index fc4dd2a1204e..591b4aea4ad8 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -75,12 +75,12 @@ defmodule Explorer.Staking.ContractState do staking_contract_address = Application.get_env(:explorer, __MODULE__)[:staking_contract_address] %{ - "validatorSetContract" => {:ok, [validator_set_contract_address]}, - "erc677TokenContract" => {:ok, [token_contract_address]} + "erc677TokenContract" => {:ok, [token_contract_address]}, + "validatorSetContract" => {:ok, [validator_set_contract_address]} } = Reader.query_contract(staking_contract_address, staking_abi, %{ - "validatorSetContract" => [], - "erc677TokenContract" => [] + "erc677TokenContract" => [], + "validatorSetContract" => [] }) %{"blockRewardContract" => {:ok, [block_reward_contract_address]}} = diff --git a/apps/explorer/test/explorer/staking/contract_state_test.exs b/apps/explorer/test/explorer/staking/contract_state_test.exs index b87a1fc0d4aa..330959e97c7b 100644 --- a/apps/explorer/test/explorer/staking/contract_state_test.exs +++ b/apps/explorer/test/explorer/staking/contract_state_test.exs @@ -30,21 +30,18 @@ defmodule Explorer.Staking.ContractStateTest do start_supervised!(ContractState) - set_mox() - Publisher.broadcast([{:blocks, [%Explorer.Chain.Block{number: 6000}]}], :realtime) - Publisher.broadcast([{:blocks, [%Explorer.Chain.Block{number: 5999}]}], :realtime) - Publisher.broadcast([{:blocks, [%Explorer.Chain.Block{number: 6000}]}], :realtime) + Publisher.broadcast([{:blocks, [%Explorer.Chain.Block{number: 76}]}], :realtime) Process.sleep(500) - assert ContractState.get(:epoch_number) == 74 - assert ContractState.get(:epoch_end_block) == 6000 + assert ContractState.get(:epoch_number) == 1 + assert ContractState.get(:epoch_end_block) == 152 assert ContractState.get(:min_delegator_stake) == 1_000_000_000_000_000_000 assert ContractState.get(:min_candidate_stake) == 1_000_000_000_000_000_000 assert ContractState.get(:token_contract_address) == "0x6f7a73c96bd56f8b0debc795511eda135e105ea3" - assert Repo.aggregate(StakingPool, :count, :id) == 7 - assert Repo.aggregate(StakingPoolsDelegator, :count, :id) == 10 + assert Repo.aggregate(StakingPool, :count, :id) == 6 + assert Repo.aggregate(StakingPoolsDelegator, :count, :id) == 16 end defp set_init_mox() do @@ -55,10 +52,12 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 2 {:ok, - format_responses([ - "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", - "0x0000000000000000000000001000000000000000000000000000000000000001" - ])} + format_responses([ + # StakingAuRa.erc677TokenContract + "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", + # StakingAuRa.validatorSetContract + "0x0000000000000000000000001000000000000000000000000000000000000001" + ])} end ) @@ -67,12 +66,12 @@ defmodule Explorer.Staking.ContractStateTest do :json_rpc, fn requests, _opts -> assert length(requests) == 1 + # ValidatorSetAuRa.blockRewardContract {:ok, format_responses(["0x0000000000000000000000002000000000000000000000000000000000000001"])} end ) - end - defp set_mox() do + # get_token, fetch_token, MetadataRetriever.get_functions_of expect( EthereumJSONRPC.Mox, :json_rpc, @@ -80,19 +79,22 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 4 {:ok, - format_responses([ - # 1 decimals - "0x0000000000000000000000000000000000000000000000000000000000000012", - # 2 name - "0x7465737400000000000000000000000000000000000000000000000000000000", - # 3 symbol - "0x5453540000000000000000000000000000000000000000000000000000000000", - # 4 totalSupply - "0x00000000000000000000000000000000000000000000000000000000000f4240" - ])} + format_responses([ + # ERC677BridgeTokenRewardable.decimals + "0x0000000000000000000000000000000000000000000000000000000000000012", + # ERC677BridgeTokenRewardable.name + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", + # ERC677BridgeTokenRewardable.symbol + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", + # ERC677BridgeTokenRewardable.totalSupply + "0x000000000000000000000000000000000000000000000001f399b1438a100000" + ])} end ) + end + defp set_mox() do + # ContractReader.global_requests expect( EthereumJSONRPC.Mox, :json_rpc, @@ -100,39 +102,40 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 14 {:ok, - format_responses([ - # 1 getPools - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577", - # 2 stakingEpochEndBlock - "0x0000000000000000000000000000000000000000000000000000000000001770", - # 3 stakingEpoch - "0x000000000000000000000000000000000000000000000000000000000000004a", - # 4 stakingEpochStartBlock - "0x0000000000000000000000000000000000000000000000000000000000001760", - # 5 getPoolsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e", - # 6 candidateMinStake - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - # 7 delegatorMinStake - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - # 8 getPoolsLikelihood - "0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000514000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000044c", - # 9 getPoolsToBeElected - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577", - # 10 areStakeAndWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 11 erc677TokenContract - "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", - # 12 unremovableValidator - "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", - # 13 getValidators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3", - # 14 validatorSetApplyBlock - "0x0000000000000000000000000000000000000000000000000000000000000001" - ])} + format_responses([ + # 1 StakingAuRa.getPools + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e000000000000000000000000db9cb2478d917719c53862008672166808258577000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9", + # 2 StakingAuRa.stakingEpochEndBlock + "0x0000000000000000000000000000000000000000000000000000000000000098", + # 3 StakingAuRa.stakingEpoch + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4 StakingAuRa.stakingEpochStartBlock + "0x000000000000000000000000000000000000000000000000000000000000004d", + # 5 StakingAuRa.getPoolsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 6 StakingAuRa.candidateMinStake + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + # 7 StakingAuRa.delegatorMinStake + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + # 8 StakingAuRa.getPoolsLikelihood + "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000098a7d9b8314c000000000000000000000000000000000000000000000000000029a2241af62c0000", + # 9 StakingAuRa.getPoolsToBeElected + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e", + # 10 StakingAuRa.areStakeAndWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11 StakingAuRa.erc677TokenContract + "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", + # 12 ValidatorSetAuRa.unremovableValidator + "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", + # 13 ValidatorSetAuRa.getValidators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c7800000000000000000000000075df42383afe6bf5194aa8fa0e9b3d5f9e869441000000000000000000000000522df396ae70a058bd69778408630fdb023389b2", + # 14 ValidatorSetAuRa.validatorSetApplyBlock + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} end ) + # get_validator_min_reward_percent expect( EthereumJSONRPC.Mox, :json_rpc, @@ -140,442 +143,520 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # 1 validatorMinRewardPercent - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} - end - ) - - expect( - EthereumJSONRPC.Mox, - :json_rpc, - fn requests, _opts -> - assert length(requests) == 3 - - {:ok, - format_responses([ - # 1 stakingByMiningAddress - "0x000000000000000000000000a5063b12c4d6ca73e189ef071f6712d048175055", - # 2 stakingByMiningAddress - "0x0000000000000000000000003efbc7ae3e8f608f1336076a4004aa191d2ca7c7", - # 3 stakingByMiningAddress - "0x0000000000000000000000006f2859f4e38423b85ff2152bdc7c43720171a12f" - ])} - end - ) - - expect( - EthereumJSONRPC.Mox, - :json_rpc, - fn requests, _opts -> - assert length(requests) == 49 - - {:ok, - format_responses([ - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2 poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3 isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4 miningByStakingAddress - "0x000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7 validatorRewardPercent - "0x000000000000000000000000000000000000000000000000000000000003d090", - - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2 poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3 isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4 miningByStakingAddress - "0x000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # 6 stakeAmountTotal - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # 7 validatorRewardPercent - "0x0000000000000000000000000000000000000000000000000000000000051615", - - # 1 poolDelegators - "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000009d99f80d3b59cca783f11918311fb31212fb7500000000000000000000000008d6867958e1cab5c39160a1d30fbc68ac55b45ef", - # 2 poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3 isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4 miningByStakingAddress - "0x000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # 6 stakeAmountTotal - "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", - # 7 validatorRewardPercent - "0x0000000000000000000000000000000000000000000000000000000000051615", - - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e4978fac7adfc925352dbc7e1962e6545142eeee", - # 2 poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3 isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 miningByStakingAddress - "0x000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # 6 stakeAmountTotal - "0x00000000000000000000000000000000000000000000000029a2241af62c0000", - # 7 validatorRewardPercent - "0x0000000000000000000000000000000000000000000000000000000000051615", - - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2 poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3 isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4 miningByStakingAddress - "0x00000000000000000000000015b18132380cbc7e200e2c0b46de3cad06f53f36", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7 validatorRewardPercent - "0x000000000000000000000000000000000000000000000000000000000003d090", - - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2 poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3 isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4 miningByStakingAddress - "0x0000000000000000000000006defba7208e8fc11d8c7c32e10be08c19b155089", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7 validatorRewardPercent - "0x000000000000000000000000000000000000000000000000000000000003d090", - - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2 poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3 isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4 miningByStakingAddress - "0x0000000000000000000000006a8a0060ed0d1c083b34d9122ab61cbe626a59f6", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7 validatorRewardPercent - "0x000000000000000000000000000000000000000000000000000000000003d090" - ])} - end - ) - - expect( - EthereumJSONRPC.Mox, - :json_rpc, - fn requests, _opts -> - assert length(requests) == 49 - - {:ok, - format_responses([ - # 1 areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 validatorCounter - "0x000000000000000000000000000000000000000000000000000000000000004b", - # 7 banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 1 areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 validatorCounter - "0x0000000000000000000000000000000000000000000000000000000000000002", - # 7 banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 1 areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 validatorCounter - "0x000000000000000000000000000000000000000000000000000000000000004a", - # 7 banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 1 areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 validatorCounter - "0x000000000000000000000000000000000000000000000000000000000000004a", - # 7 banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 1 areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 validatorCounter - "0x000000000000000000000000000000000000000000000000000000000000004b", - # 7 banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 1 areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 validatorCounter - "0x000000000000000000000000000000000000000000000000000000000000004b", - # 7 banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 1 areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 validatorCounter - "0x000000000000000000000000000000000000000000000000000000000000004b", - # 7 banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} - end - ) - - expect( - EthereumJSONRPC.Mox, - :json_rpc, - fn requests, _opts -> - assert length(requests) == 50 - - {:ok, - format_responses([ - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 1 maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} - end - ) - - expect( - EthereumJSONRPC.Mox, - :json_rpc, - fn requests, _opts -> - assert length(requests) == 7 - - {:ok, - format_responses([ - # 1 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} - end - ) - - expect( - EthereumJSONRPC.Mox, - :json_rpc, - fn requests, _opts -> - assert length(requests) == 10 - - {:ok, - format_responses([ - # 1 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 8 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 9 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 10 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # BlockRewardAuRa.validatorMinRewardPercent + "0x000000000000000000000000000000000000000000000000000000000000001e" + ])} + end + ) + + # get_validators + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 2 + + {:ok, + format_responses([ + # ValidatorSetAuRa.getPendingValidators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", + # ValidatorSetAuRa.validatorsToBeFinalized + "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + # get_mining_to_staking_address + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 6 + + {:ok, + format_responses([ + # 1 ValidatorSetAuRa.stakingByMiningAddress + "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", + # 2 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000aa94b687d3f9552a453b81b2834ca53778980dc0", + # 3 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000312c230e7d6db05224f60208a656e3541c5c42ba", + # 4 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9", + # 5 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000db9cb2478d917719c53862008672166808258577", + # 6 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e" + ])} + end + ) + + # get_responses, ContractReader.pool_staking_requests + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 6*7 + + {:ok, + format_responses([ + # 1.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 1.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 1.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000522df396ae70a058bd69778408630fdb023389b2", + # 1.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.6 StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.7 BlockRewardAuRa.validatorRewardPercent + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 2.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d788829c11f61972c6c43ff6a7aaef4b154006ba", + # 2.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 2.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", + # 2.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 2.6 StakingAuRa.stakeAmountTotal + "0x00000000000000000000000000000000000000000000000029a2241af62c0000", + # 2.7 BlockRewardAuRa.validatorRewardPercent + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + + # 3.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.4 ValidatorSetAuRa.miningByStakingAddress + "0x00000000000000000000000075df42383afe6bf5194aa8fa0e9b3d5f9e869441", + # 3.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.6 StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.7 BlockRewardAuRa.validatorRewardPercent + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 4.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 4.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 4.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78", + # 4.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.6 StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.7 BlockRewardAuRa.validatorRewardPercent + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 5.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000009000000000000000000000000d5bd381ffd0aba13265a7489f4a141d0ece91054000000000000000000000000682271d71c0412adb8ad7cd027a46da18f220315000000000000000000000000aa6a2866891a5c9046b06abb638bb8030e332724000000000000000000000000e90b1459d82917f1727b656756181b39f807044200000000000000000000000000898d801f6a565503f4df66ecb38292a9744828000000000000000000000000c69fe675984232f239cdfd3a35ad234b2b24988a000000000000000000000000fe9739a22165d48acae6b2385bfe0e43f3ea983000000000000000000000000044c331d263b5e319f34903adfd1621787fda381e000000000000000000000000629c7e8be1b2e0d40850689401ca59ea1769a08e", + # 5.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 5.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 5.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3", + # 5.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 5.6 StakingAuRa.stakeAmountTotal + "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", + # 5.7 BlockRewardAuRa.validatorRewardPercent + "0x00000000000000000000000000000000000000000000000000000000000493e0", + + # 6.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 6.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 6.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 6.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb", + # 6.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 6.6 StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 6.7 BlockRewardAuRa.validatorRewardPercent + "0x00000000000000000000000000000000000000000000000000000000000f4240" + ])} + end + ) + + # get_responses, ContractReader.pool_mining_requests + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 6*7 + + {:ok, + format_responses([ + # 1.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 1.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 2.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 3.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 3.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 4.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 5.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 6.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + # get_responses, ContractReader.staker_requests + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 16*5 + + {:ok, + format_responses([ + # 1.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 2.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 3.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 4.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + + # 5.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 6.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + + # 7.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + + # 8.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 9.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 10.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 11.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 12.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 12.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 12.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 12.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 12.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 13.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 13.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 13.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 13.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 13.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 14.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 14.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 14.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 14.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 14.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 15.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 15.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 15.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 15.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 15.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 16.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 16.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 16.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 16.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 16.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) + # get_candidate_reward_responses + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 6 + + {:ok, + format_responses([ + # 1 BlockRewardAuRa.validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 BlockRewardAuRa.validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 BlockRewardAuRa.validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + # 5 BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000f4240", + # 6 BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000493e0" + ])} + end + ) + + # get_delegator_reward_responses + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 16 + + {:ok, + format_responses([ + # 1 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 BlockRewardAuRa.delegatorShare + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + # 5 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000051615", + # 6 BlockRewardAuRa.delegatorShare + "0x00000000000000000000000000000000000000000000000000000000000f4240", + # 7 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 8 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 9 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 10 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 11 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 12 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 13 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 14 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000025fa3", + # 15 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 16 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1" + ])} + end + ) + + # invoke at_start_snapshotting() + + ## BalanceReader.get_balances_of expect( EthereumJSONRPC.Mox, :json_rpc, @@ -583,13 +664,14 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # 1 balanceOf - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # ERC677BridgeTokenRewardable.balanceOf(BlockRewardAuRa) + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} end ) + ## MetadataRetriever.get_functions_of expect( EthereumJSONRPC.Mox, :json_rpc, @@ -597,73 +679,195 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 4 {:ok, - format_responses([ - # 1 decimals - "0x0000000000000000000000000000000000000000000000000000000000000012", - # 2 name - "0x7465737400000000000000000000000000000000000000000000000000000000", - # 3 symbol - "0x5453540000000000000000000000000000000000000000000000000000000000", - # 4 totalSupply - "0x00000000000000000000000000000000000000000000000000000000000f4240" - ])} + format_responses([ + # ERC677BridgeTokenRewardable.decimals + "0x0000000000000000000000000000000000000000000000000000000000000012", + # ERC677BridgeTokenRewardable.name + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", + # ERC677BridgeTokenRewardable.symbol + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", + # ERC677BridgeTokenRewardable.totalSupply + "0x000000000000000000000000000000000000000000000001f399b1438a100000" + ])} + end + ) + + # invoke do_snapshotting() + + ## 1 snapshotted_pool_amounts_requests + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 2 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + ## 2 snapshotted_pool_amounts_requests + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 2 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} + end + ) + + ## 3 snapshotted_pool_amounts_requests + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 2 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmountTotal + "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} + end + ) + + ## 4 snapshotted_pool_amounts_requests + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 2 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmountTotal + "0x00000000000000000000000000000000000000000000000029a2241af62c0000", + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} + end + ) + + ## 1 snapshotted_staker_amount_request + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} + end + ) + + ## 2 snapshotted_staker_amount_request + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} + end + ) + + ## 3 snapshotted_staker_amount_request + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} + end + ) + + ## 4 snapshotted_staker_amount_request + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} end ) + ## 5 snapshotted_staker_amount_request expect( EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 3 + assert length(requests) == 1 {:ok, - format_responses([ - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2 stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} end ) + ## 6 snapshotted_staker_amount_request expect( EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 3 + assert length(requests) == 1 {:ok, - format_responses([ - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2 stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) + ## 7 snapshotted_staker_amount_request expect( EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 3 + assert length(requests) == 1 {:ok, - format_responses([ - # 1 poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2 stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) + ## 8 snapshotted_staker_amount_request expect( EthereumJSONRPC.Mox, :json_rpc, @@ -671,13 +875,14 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # 1 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) + ## 9 snapshotted_staker_amount_request expect( EthereumJSONRPC.Mox, :json_rpc, @@ -685,13 +890,14 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # 1 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) + ## 10 snapshotted_staker_amount_request expect( EthereumJSONRPC.Mox, :json_rpc, @@ -699,46 +905,132 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # 1 stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) + ## 11 snapshotted_staker_amount_request expect( EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 3 + assert length(requests) == 1 {:ok, - format_responses([ - # 1 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) + ## 12 snapshotted_staker_amount_request expect( EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 3 + assert length(requests) == 1 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} + end + ) + + ## 13 snapshotted_staker_amount_request + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} + end + ) + + ## 14 snapshotted_staker_amount_request + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 1 + + {:ok, + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} + end + ) + + ## ContractReader.validator_reward_request + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 4 + + {:ok, + format_responses([ + # BlockRewardAuRa.validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + # BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000f4240", + # BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000493e0" + ])} + end + ) + + ## ContractReader.delegator_reward_request + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn requests, _opts -> + assert length(requests) == 14 {:ok, - format_responses([ - # 1 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # BlockRewardAuRa.delegatorShare + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000051615", + # BlockRewardAuRa.delegatorShare + "0x00000000000000000000000000000000000000000000000000000000000f4240", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000025fa3", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1" + ])} end ) end From 10868c505707c13b178f14983a9eecddbe6a96be Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 13 May 2020 16:30:15 +0300 Subject: [PATCH 73/75] mix format contract_state_test.exs --- .../explorer/staking/contract_state_test.exs | 1228 ++++++++--------- 1 file changed, 614 insertions(+), 614 deletions(-) diff --git a/apps/explorer/test/explorer/staking/contract_state_test.exs b/apps/explorer/test/explorer/staking/contract_state_test.exs index 330959e97c7b..7a76a7a61395 100644 --- a/apps/explorer/test/explorer/staking/contract_state_test.exs +++ b/apps/explorer/test/explorer/staking/contract_state_test.exs @@ -52,12 +52,12 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 2 {:ok, - format_responses([ - # StakingAuRa.erc677TokenContract - "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", - # StakingAuRa.validatorSetContract - "0x0000000000000000000000001000000000000000000000000000000000000001" - ])} + format_responses([ + # StakingAuRa.erc677TokenContract + "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", + # StakingAuRa.validatorSetContract + "0x0000000000000000000000001000000000000000000000000000000000000001" + ])} end ) @@ -79,16 +79,16 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 4 {:ok, - format_responses([ - # ERC677BridgeTokenRewardable.decimals - "0x0000000000000000000000000000000000000000000000000000000000000012", - # ERC677BridgeTokenRewardable.name - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", - # ERC677BridgeTokenRewardable.symbol - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", - # ERC677BridgeTokenRewardable.totalSupply - "0x000000000000000000000000000000000000000000000001f399b1438a100000" - ])} + format_responses([ + # ERC677BridgeTokenRewardable.decimals + "0x0000000000000000000000000000000000000000000000000000000000000012", + # ERC677BridgeTokenRewardable.name + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", + # ERC677BridgeTokenRewardable.symbol + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", + # ERC677BridgeTokenRewardable.totalSupply + "0x000000000000000000000000000000000000000000000001f399b1438a100000" + ])} end ) end @@ -102,36 +102,36 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 14 {:ok, - format_responses([ - # 1 StakingAuRa.getPools - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e000000000000000000000000db9cb2478d917719c53862008672166808258577000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9", - # 2 StakingAuRa.stakingEpochEndBlock - "0x0000000000000000000000000000000000000000000000000000000000000098", - # 3 StakingAuRa.stakingEpoch - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4 StakingAuRa.stakingEpochStartBlock - "0x000000000000000000000000000000000000000000000000000000000000004d", - # 5 StakingAuRa.getPoolsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 6 StakingAuRa.candidateMinStake - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - # 7 StakingAuRa.delegatorMinStake - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - # 8 StakingAuRa.getPoolsLikelihood - "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000098a7d9b8314c000000000000000000000000000000000000000000000000000029a2241af62c0000", - # 9 StakingAuRa.getPoolsToBeElected - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e", - # 10 StakingAuRa.areStakeAndWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 11 StakingAuRa.erc677TokenContract - "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", - # 12 ValidatorSetAuRa.unremovableValidator - "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", - # 13 ValidatorSetAuRa.getValidators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c7800000000000000000000000075df42383afe6bf5194aa8fa0e9b3d5f9e869441000000000000000000000000522df396ae70a058bd69778408630fdb023389b2", - # 14 ValidatorSetAuRa.validatorSetApplyBlock - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # 1 StakingAuRa.getPools + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e000000000000000000000000db9cb2478d917719c53862008672166808258577000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9", + # 2 StakingAuRa.stakingEpochEndBlock + "0x0000000000000000000000000000000000000000000000000000000000000098", + # 3 StakingAuRa.stakingEpoch + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4 StakingAuRa.stakingEpochStartBlock + "0x000000000000000000000000000000000000000000000000000000000000004d", + # 5 StakingAuRa.getPoolsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 6 StakingAuRa.candidateMinStake + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + # 7 StakingAuRa.delegatorMinStake + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + # 8 StakingAuRa.getPoolsLikelihood + "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000098a7d9b8314c000000000000000000000000000000000000000000000000000029a2241af62c0000", + # 9 StakingAuRa.getPoolsToBeElected + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e", + # 10 StakingAuRa.areStakeAndWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11 StakingAuRa.erc677TokenContract + "0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3", + # 12 ValidatorSetAuRa.unremovableValidator + "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", + # 13 ValidatorSetAuRa.getValidators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c7800000000000000000000000075df42383afe6bf5194aa8fa0e9b3d5f9e869441000000000000000000000000522df396ae70a058bd69778408630fdb023389b2", + # 14 ValidatorSetAuRa.validatorSetApplyBlock + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} end ) @@ -143,10 +143,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # BlockRewardAuRa.validatorMinRewardPercent - "0x000000000000000000000000000000000000000000000000000000000000001e" - ])} + format_responses([ + # BlockRewardAuRa.validatorMinRewardPercent + "0x000000000000000000000000000000000000000000000000000000000000001e" + ])} end ) @@ -158,12 +158,12 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 2 {:ok, - format_responses([ - # ValidatorSetAuRa.getPendingValidators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", - # ValidatorSetAuRa.validatorsToBeFinalized - "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # ValidatorSetAuRa.getPendingValidators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", + # ValidatorSetAuRa.validatorsToBeFinalized + "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ])} end ) @@ -175,20 +175,20 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 6 {:ok, - format_responses([ - # 1 ValidatorSetAuRa.stakingByMiningAddress - "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", - # 2 ValidatorSetAuRa.stakingByMiningAddress - "0x000000000000000000000000aa94b687d3f9552a453b81b2834ca53778980dc0", - # 3 ValidatorSetAuRa.stakingByMiningAddress - "0x000000000000000000000000312c230e7d6db05224f60208a656e3541c5c42ba", - # 4 ValidatorSetAuRa.stakingByMiningAddress - "0x000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9", - # 5 ValidatorSetAuRa.stakingByMiningAddress - "0x000000000000000000000000db9cb2478d917719c53862008672166808258577", - # 6 ValidatorSetAuRa.stakingByMiningAddress - "0x000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e" - ])} + format_responses([ + # 1 ValidatorSetAuRa.stakingByMiningAddress + "0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", + # 2 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000aa94b687d3f9552a453b81b2834ca53778980dc0", + # 3 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000312c230e7d6db05224f60208a656e3541c5c42ba", + # 4 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9", + # 5 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000db9cb2478d917719c53862008672166808258577", + # 6 ValidatorSetAuRa.stakingByMiningAddress + "0x000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e" + ])} end ) @@ -197,100 +197,100 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 6*7 + assert length(requests) == 6 * 7 {:ok, - format_responses([ - # 1.1 StakingAuRa.poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 1.2 StakingAuRa.poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 1.3 StakingAuRa.isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.4 ValidatorSetAuRa.miningByStakingAddress - "0x000000000000000000000000522df396ae70a058bd69778408630fdb023389b2", - # 1.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.6 StakingAuRa.stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.7 BlockRewardAuRa.validatorRewardPercent - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 2.1 StakingAuRa.poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d788829c11f61972c6c43ff6a7aaef4b154006ba", - # 2.2 StakingAuRa.poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 2.3 StakingAuRa.isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 2.4 ValidatorSetAuRa.miningByStakingAddress - "0x000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", - # 2.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # 2.6 StakingAuRa.stakeAmountTotal - "0x00000000000000000000000000000000000000000000000029a2241af62c0000", - # 2.7 BlockRewardAuRa.validatorRewardPercent - "0x00000000000000000000000000000000000000000000000000000000000a2c2a", - - # 3.1 StakingAuRa.poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3.2 StakingAuRa.poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 3.3 StakingAuRa.isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.4 ValidatorSetAuRa.miningByStakingAddress - "0x00000000000000000000000075df42383afe6bf5194aa8fa0e9b3d5f9e869441", - # 3.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.6 StakingAuRa.stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.7 BlockRewardAuRa.validatorRewardPercent - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 4.1 StakingAuRa.poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 4.2 StakingAuRa.poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 4.3 StakingAuRa.isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4.4 ValidatorSetAuRa.miningByStakingAddress - "0x000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78", - # 4.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.6 StakingAuRa.stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.7 BlockRewardAuRa.validatorRewardPercent - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 5.1 StakingAuRa.poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000009000000000000000000000000d5bd381ffd0aba13265a7489f4a141d0ece91054000000000000000000000000682271d71c0412adb8ad7cd027a46da18f220315000000000000000000000000aa6a2866891a5c9046b06abb638bb8030e332724000000000000000000000000e90b1459d82917f1727b656756181b39f807044200000000000000000000000000898d801f6a565503f4df66ecb38292a9744828000000000000000000000000c69fe675984232f239cdfd3a35ad234b2b24988a000000000000000000000000fe9739a22165d48acae6b2385bfe0e43f3ea983000000000000000000000000044c331d263b5e319f34903adfd1621787fda381e000000000000000000000000629c7e8be1b2e0d40850689401ca59ea1769a08e", - # 5.2 StakingAuRa.poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 5.3 StakingAuRa.isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 5.4 ValidatorSetAuRa.miningByStakingAddress - "0x000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3", - # 5.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # 5.6 StakingAuRa.stakeAmountTotal - "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", - # 5.7 BlockRewardAuRa.validatorRewardPercent - "0x00000000000000000000000000000000000000000000000000000000000493e0", - - # 6.1 StakingAuRa.poolDelegators - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 6.2 StakingAuRa.poolDelegatorsInactive - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - # 6.3 StakingAuRa.isPoolActive - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 6.4 ValidatorSetAuRa.miningByStakingAddress - "0x000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb", - # 6.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # 6.6 StakingAuRa.stakeAmountTotal - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # 6.7 BlockRewardAuRa.validatorRewardPercent - "0x00000000000000000000000000000000000000000000000000000000000f4240" - ])} + format_responses([ + # 1.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 1.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 1.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000522df396ae70a058bd69778408630fdb023389b2", + # 1.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.6 StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.7 BlockRewardAuRa.validatorRewardPercent + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 2.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d788829c11f61972c6c43ff6a7aaef4b154006ba", + # 2.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 2.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 2.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000720e118ab1006cc97ed2ef6b4b49ac04bb3aa6d9", + # 2.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 2.6 StakingAuRa.stakeAmountTotal + "0x00000000000000000000000000000000000000000000000029a2241af62c0000", + # 2.7 BlockRewardAuRa.validatorRewardPercent + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + + # 3.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 3.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.4 ValidatorSetAuRa.miningByStakingAddress + "0x00000000000000000000000075df42383afe6bf5194aa8fa0e9b3d5f9e869441", + # 3.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.6 StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.7 BlockRewardAuRa.validatorRewardPercent + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 4.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 4.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 4.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c78", + # 4.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.6 StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.7 BlockRewardAuRa.validatorRewardPercent + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 5.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000009000000000000000000000000d5bd381ffd0aba13265a7489f4a141d0ece91054000000000000000000000000682271d71c0412adb8ad7cd027a46da18f220315000000000000000000000000aa6a2866891a5c9046b06abb638bb8030e332724000000000000000000000000e90b1459d82917f1727b656756181b39f807044200000000000000000000000000898d801f6a565503f4df66ecb38292a9744828000000000000000000000000c69fe675984232f239cdfd3a35ad234b2b24988a000000000000000000000000fe9739a22165d48acae6b2385bfe0e43f3ea983000000000000000000000000044c331d263b5e319f34903adfd1621787fda381e000000000000000000000000629c7e8be1b2e0d40850689401ca59ea1769a08e", + # 5.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 5.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 5.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000be69eb0968226a1808975e1a1f2127667f2bffb3", + # 5.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 5.6 StakingAuRa.stakeAmountTotal + "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", + # 5.7 BlockRewardAuRa.validatorRewardPercent + "0x00000000000000000000000000000000000000000000000000000000000493e0", + + # 6.1 StakingAuRa.poolDelegators + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 6.2 StakingAuRa.poolDelegatorsInactive + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + # 6.3 StakingAuRa.isPoolActive + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 6.4 ValidatorSetAuRa.miningByStakingAddress + "0x000000000000000000000000f67cc5231c5858ad6cc87b105217426e17b824bb", + # 6.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 6.6 StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # 6.7 BlockRewardAuRa.validatorRewardPercent + "0x00000000000000000000000000000000000000000000000000000000000f4240" + ])} end ) @@ -299,100 +299,100 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 6*7 + assert length(requests) == 6 * 7 {:ok, - format_responses([ - # 1.1 ValidatorSetAuRa.areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.2 ValidatorSetAuRa.banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.3 ValidatorSetAuRa.bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.4 ValidatorSetAuRa.bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.5 ValidatorSetAuRa.isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.6 ValidatorSetAuRa.validatorCounter - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 1.7 ValidatorSetAuRa.banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 2.1 ValidatorSetAuRa.areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.2 ValidatorSetAuRa.banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.3 ValidatorSetAuRa.bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.4 ValidatorSetAuRa.bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.5 ValidatorSetAuRa.isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.6 ValidatorSetAuRa.validatorCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.7 ValidatorSetAuRa.banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 3.1 ValidatorSetAuRa.areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.2 ValidatorSetAuRa.banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.3 ValidatorSetAuRa.bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.4 ValidatorSetAuRa.bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.5 ValidatorSetAuRa.isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.6 ValidatorSetAuRa.validatorCounter - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 3.7 ValidatorSetAuRa.banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 4.1 ValidatorSetAuRa.areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.2 ValidatorSetAuRa.banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.3 ValidatorSetAuRa.bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.4 ValidatorSetAuRa.bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.5 ValidatorSetAuRa.isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.6 ValidatorSetAuRa.validatorCounter - "0x0000000000000000000000000000000000000000000000000000000000000001", - # 4.7 ValidatorSetAuRa.banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 5.1 ValidatorSetAuRa.areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.2 ValidatorSetAuRa.banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.3 ValidatorSetAuRa.bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.4 ValidatorSetAuRa.bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.5 ValidatorSetAuRa.isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.6 ValidatorSetAuRa.validatorCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.7 ValidatorSetAuRa.banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 6.1 ValidatorSetAuRa.areDelegatorsBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.2 ValidatorSetAuRa.banReason - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.3 ValidatorSetAuRa.bannedUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.4 ValidatorSetAuRa.bannedDelegatorsUntil - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.5 ValidatorSetAuRa.isValidatorBanned - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.6 ValidatorSetAuRa.validatorCounter - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.7 ValidatorSetAuRa.banCounter - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # 1.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 1.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 2.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 3.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 3.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 4.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000001", + # 4.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 5.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 6.1 ValidatorSetAuRa.areDelegatorsBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.2 ValidatorSetAuRa.banReason + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.3 ValidatorSetAuRa.bannedUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.4 ValidatorSetAuRa.bannedDelegatorsUntil + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.5 ValidatorSetAuRa.isValidatorBanned + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.6 ValidatorSetAuRa.validatorCounter + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.7 ValidatorSetAuRa.banCounter + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} end ) @@ -401,186 +401,186 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 16*5 + assert length(requests) == 16 * 5 {:ok, - format_responses([ - # 1.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 1.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 2.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 3.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - - # 4.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - - # 5.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 5.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 6.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 6.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - - # 7.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 7.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - - # 8.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 8.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 8.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 8.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 8.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 9.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 9.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 9.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 9.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 9.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 10.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 10.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 10.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 10.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 10.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 11.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 11.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 11.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 11.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 11.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 12.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 12.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 12.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 12.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 12.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 13.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 13.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 13.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 13.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 13.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 14.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 14.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 14.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 14.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 14.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 15.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 15.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 15.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 15.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 15.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - - # 16.1 StakingAuRa.maxWithdrawOrderAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 16.2 StakingAuRa.maxWithdrawAllowed - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 16.3 StakingAuRa.orderedWithdrawAmount - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 16.4 StakingAuRa.orderWithdrawEpoch - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 16.5 StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # 1.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 1.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 2.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 3.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + + # 4.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + + # 5.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 5.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 6.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 6.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + + # 7.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 7.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + + # 8.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 8.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 9.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 9.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 10.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 10.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 11.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 11.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 12.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 12.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 12.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 12.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 12.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 13.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 13.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 13.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 13.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 13.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 14.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 14.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 14.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 14.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 14.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 15.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 15.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 15.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 15.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 15.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", + + # 16.1 StakingAuRa.maxWithdrawOrderAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 16.2 StakingAuRa.maxWithdrawAllowed + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 16.3 StakingAuRa.orderedWithdrawAmount + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 16.4 StakingAuRa.orderWithdrawEpoch + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 16.5 StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -592,20 +592,20 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 6 {:ok, - format_responses([ - # 1 BlockRewardAuRa.validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 BlockRewardAuRa.validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 BlockRewardAuRa.validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 BlockRewardAuRa.validatorShare - "0x00000000000000000000000000000000000000000000000000000000000a2c2a", - # 5 BlockRewardAuRa.validatorShare - "0x00000000000000000000000000000000000000000000000000000000000f4240", - # 6 BlockRewardAuRa.validatorShare - "0x00000000000000000000000000000000000000000000000000000000000493e0" - ])} + format_responses([ + # 1 BlockRewardAuRa.validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 BlockRewardAuRa.validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 BlockRewardAuRa.validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + # 5 BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000f4240", + # 6 BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000493e0" + ])} end ) @@ -617,40 +617,40 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 16 {:ok, - format_responses([ - # 1 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 2 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 3 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # 4 BlockRewardAuRa.delegatorShare - "0x00000000000000000000000000000000000000000000000000000000000a2c2a", - # 5 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000051615", - # 6 BlockRewardAuRa.delegatorShare - "0x00000000000000000000000000000000000000000000000000000000000f4240", - # 7 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 8 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 9 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 10 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 11 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 12 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 13 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 14 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000025fa3", - # 15 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 16 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1" - ])} + format_responses([ + # 1 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 2 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 3 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # 4 BlockRewardAuRa.delegatorShare + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + # 5 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000051615", + # 6 BlockRewardAuRa.delegatorShare + "0x00000000000000000000000000000000000000000000000000000000000f4240", + # 7 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 8 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 9 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 10 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 11 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 12 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 13 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 14 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000025fa3", + # 15 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # 16 BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1" + ])} end ) @@ -664,10 +664,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # ERC677BridgeTokenRewardable.balanceOf(BlockRewardAuRa) - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # ERC677BridgeTokenRewardable.balanceOf(BlockRewardAuRa) + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} end ) @@ -679,16 +679,16 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 4 {:ok, - format_responses([ - # ERC677BridgeTokenRewardable.decimals - "0x0000000000000000000000000000000000000000000000000000000000000012", - # ERC677BridgeTokenRewardable.name - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", - # ERC677BridgeTokenRewardable.symbol - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", - # ERC677BridgeTokenRewardable.totalSupply - "0x000000000000000000000000000000000000000000000001f399b1438a100000" - ])} + format_responses([ + # ERC677BridgeTokenRewardable.decimals + "0x0000000000000000000000000000000000000000000000000000000000000012", + # ERC677BridgeTokenRewardable.name + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", + # ERC677BridgeTokenRewardable.symbol + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000055354414b45000000000000000000000000000000000000000000000000000000", + # ERC677BridgeTokenRewardable.totalSupply + "0x000000000000000000000000000000000000000000000001f399b1438a100000" + ])} end ) @@ -702,12 +702,12 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 2 {:ok, - format_responses([ - # StakingAuRa.stakeAmountTotal - "0x0000000000000000000000000000000000000000000000000000000000000000", - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000000000000000000000", + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} end ) @@ -719,12 +719,12 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 2 {:ok, - format_responses([ - # StakingAuRa.stakeAmountTotal - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" - ])} + format_responses([ + # StakingAuRa.stakeAmountTotal + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000", + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} end ) @@ -736,12 +736,12 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 2 {:ok, - format_responses([ - # StakingAuRa.stakeAmountTotal - "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" - ])} + format_responses([ + # StakingAuRa.stakeAmountTotal + "0x00000000000000000000000000000000000000000000000098a7d9b8314c0000", + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} end ) @@ -753,12 +753,12 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 2 {:ok, - format_responses([ - # StakingAuRa.stakeAmountTotal - "0x00000000000000000000000000000000000000000000000029a2241af62c0000", - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" - ])} + format_responses([ + # StakingAuRa.stakeAmountTotal + "0x00000000000000000000000000000000000000000000000029a2241af62c0000", + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} end ) @@ -770,10 +770,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000000000000000000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000000000000000000" + ])} end ) @@ -785,10 +785,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} end ) @@ -800,10 +800,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -815,10 +815,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} end ) @@ -830,10 +830,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000001bc16d674ec80000" + ])} end ) @@ -845,10 +845,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -860,10 +860,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -875,10 +875,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -890,10 +890,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -905,10 +905,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -920,10 +920,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -935,10 +935,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -950,10 +950,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -965,10 +965,10 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 1 {:ok, - format_responses([ - # StakingAuRa.stakeAmount - "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - ])} + format_responses([ + # StakingAuRa.stakeAmount + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + ])} end ) @@ -980,16 +980,16 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 4 {:ok, - format_responses([ - # BlockRewardAuRa.validatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # BlockRewardAuRa.validatorShare - "0x00000000000000000000000000000000000000000000000000000000000a2c2a", - # BlockRewardAuRa.validatorShare - "0x00000000000000000000000000000000000000000000000000000000000f4240", - # BlockRewardAuRa.validatorShare - "0x00000000000000000000000000000000000000000000000000000000000493e0" - ])} + format_responses([ + # BlockRewardAuRa.validatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + # BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000f4240", + # BlockRewardAuRa.validatorShare + "0x00000000000000000000000000000000000000000000000000000000000493e0" + ])} end ) @@ -1001,36 +1001,36 @@ defmodule Explorer.Staking.ContractStateTest do assert length(requests) == 14 {:ok, - format_responses([ - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # BlockRewardAuRa.delegatorShare - "0x00000000000000000000000000000000000000000000000000000000000a2c2a", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000051615", - # BlockRewardAuRa.delegatorShare - "0x00000000000000000000000000000000000000000000000000000000000f4240", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000025fa3", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1" - ])} + format_responses([ + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000000000", + # BlockRewardAuRa.delegatorShare + "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000051615", + # BlockRewardAuRa.delegatorShare + "0x00000000000000000000000000000000000000000000000000000000000f4240", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000025fa3", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1", + # BlockRewardAuRa.delegatorShare + "0x0000000000000000000000000000000000000000000000000000000000012fd1" + ])} end ) end From f5cafea63fcb56bea7a99ccc03f0bbf53dfe3892 Mon Sep 17 00:00:00 2001 From: Vadim Date: Thu, 14 May 2020 10:38:13 +0300 Subject: [PATCH 74/75] Remove excess delegatorShare calls --- .../lib/explorer/staking/contract_state.ex | 34 ++++++++++++------ .../explorer/staking/stake_snapshotting.ex | 27 ++++++++++---- .../explorer/staking/contract_state_test.exs | 36 +++++-------------- 3 files changed, 51 insertions(+), 46 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/contract_state.ex b/apps/explorer/lib/explorer/staking/contract_state.ex index 591b4aea4ad8..962a32b78059 100644 --- a/apps/explorer/lib/explorer/staking/contract_state.ex +++ b/apps/explorer/lib/explorer/staking/contract_state.ex @@ -177,17 +177,22 @@ defmodule Explorer.Staking.ContractState do candidate_reward_responses = get_candidate_reward_responses(pool_staking_responses, global_responses, pool_staking_keys, contracts, abi) - # to keep sort order when using `perform_grouped_requests` (see below) - 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_responses = + Enum.reduce(staker_responses, %{}, fn {{pool_staking_address, staker_address, _is_active} = key, value}, acc -> + if pool_staking_address != staker_address do + Map.put(acc, key, value) + else + acc + end + end) + delegator_reward_responses = get_delegator_reward_responses( - staker_responses, + delegator_responses, pool_staking_responses, global_responses, - delegator_keys, contracts, abi ) @@ -325,14 +330,16 @@ defmodule Explorer.Staking.ContractState do end defp get_delegator_reward_responses( - staker_responses, + delegator_responses, pool_staking_responses, global_responses, - delegator_keys, contracts, abi ) do - staker_responses + # to keep sort order when using `perform_grouped_requests` (see below) + delegator_keys = Enum.map(delegator_responses, fn {key, _} -> key end) + + delegator_responses |> Enum.map(fn {{pool_staking_address, _staker_address, _is_active}, resp} -> staking_resp = pool_staking_responses[pool_staking_address] @@ -348,14 +355,19 @@ defmodule Explorer.Staking.ContractState do end defp get_delegator_entries(staker_responses, delegator_reward_responses) do - Enum.map(staker_responses, fn {{pool_address, delegator_address, is_active}, response} -> - delegator_reward_response = delegator_reward_responses[{pool_address, delegator_address, is_active}] + Enum.map(staker_responses, fn {{pool_address, delegator_address, is_active} = key, response} -> + delegator_share = + if Map.has_key?(delegator_reward_responses, key) do + delegator_reward_responses[key].delegator_share + else + 0 + end Map.merge(response, %{ address_hash: delegator_address, staking_address_hash: pool_address, is_active: is_active, - reward_ratio: Float.floor(delegator_reward_response.delegator_share / 10_000, 2) + reward_ratio: Float.floor(delegator_share / 10_000, 2) }) end) end diff --git a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex index 28a6f7400f3c..06fc07a7833e 100644 --- a/apps/explorer/lib/explorer/staking/stake_snapshotting.ex +++ b/apps/explorer/lib/explorer/staking/stake_snapshotting.ex @@ -98,13 +98,21 @@ defmodule Explorer.Staking.StakeSnapshotting do end) |> ContractReader.perform_grouped_requests(pool_staking_keys, contracts, abi) - # to keep sort order when using `perform_grouped_requests` (see below) - 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_responses = + Enum.reduce(staker_responses, %{}, fn {{pool_staking_address, staker_address} = key, value}, acc -> + if pool_staking_address != staker_address do + Map.put(acc, key, value) + else + acc + end + end) + + delegator_keys = Enum.map(delegator_responses, fn {key, _} -> key end) + delegator_reward_responses = - staker_responses + delegator_responses |> Enum.map(fn {{pool_staking_address, _staker_address}, resp} -> staking_resp = pool_staking_responses[pool_staking_address] @@ -145,8 +153,13 @@ defmodule Explorer.Staking.StakeSnapshotting do # form entries for updating the `staking_pools_delegators` table in DB delegator_entries = - Enum.map(staker_responses, fn {{pool_staking_address, staker_address}, resp} -> - delegator_reward_resp = delegator_reward_responses[{pool_staking_address, staker_address}] + Enum.map(staker_responses, fn {{pool_staking_address, staker_address} = key, resp} -> + delegator_share = + if Map.has_key?(delegator_reward_responses, key) do + delegator_reward_responses[key].delegator_share + else + 0 + end %{ address_hash: staker_address, @@ -155,7 +168,7 @@ defmodule Explorer.Staking.StakeSnapshotting do max_withdraw_allowed: 0, ordered_withdraw: 0, ordered_withdraw_epoch: 0, - snapshotted_reward_ratio: Float.floor(delegator_reward_resp.delegator_share / 10_000, 2), + snapshotted_reward_ratio: Float.floor(delegator_share / 10_000, 2), snapshotted_stake_amount: resp.snapshotted_stake_amount, stake_amount: 0, staking_address_hash: pool_staking_address diff --git a/apps/explorer/test/explorer/staking/contract_state_test.exs b/apps/explorer/test/explorer/staking/contract_state_test.exs index 7a76a7a61395..818939be1d6c 100644 --- a/apps/explorer/test/explorer/staking/contract_state_test.exs +++ b/apps/explorer/test/explorer/staking/contract_state_test.exs @@ -614,22 +614,22 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 16 + assert length(requests) == 10 {:ok, format_responses([ # 1 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000051615", # 2 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000012fd1", # 3 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000012fd1", # 4 BlockRewardAuRa.delegatorShare - "0x00000000000000000000000000000000000000000000000000000000000a2c2a", + "0x0000000000000000000000000000000000000000000000000000000000012fd1", # 5 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000051615", + "0x0000000000000000000000000000000000000000000000000000000000012fd1", # 6 BlockRewardAuRa.delegatorShare - "0x00000000000000000000000000000000000000000000000000000000000f4240", + "0x0000000000000000000000000000000000000000000000000000000000012fd1", # 7 BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000012fd1", # 8 BlockRewardAuRa.delegatorShare @@ -637,18 +637,6 @@ defmodule Explorer.Staking.ContractStateTest do # 9 BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000012fd1", # 10 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 11 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 12 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 13 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 14 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000025fa3", - # 15 BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000012fd1", - # 16 BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000012fd1" ])} end @@ -998,19 +986,13 @@ defmodule Explorer.Staking.ContractStateTest do EthereumJSONRPC.Mox, :json_rpc, fn requests, _opts -> - assert length(requests) == 14 + assert length(requests) == 10 {:ok, format_responses([ - # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000000000", - # BlockRewardAuRa.delegatorShare - "0x00000000000000000000000000000000000000000000000000000000000a2c2a", # BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000051615", # BlockRewardAuRa.delegatorShare - "0x00000000000000000000000000000000000000000000000000000000000f4240", - # BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000012fd1", # BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000012fd1", @@ -1025,8 +1007,6 @@ defmodule Explorer.Staking.ContractStateTest do # BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000012fd1", # BlockRewardAuRa.delegatorShare - "0x0000000000000000000000000000000000000000000000000000000000025fa3", - # BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000012fd1", # BlockRewardAuRa.delegatorShare "0x0000000000000000000000000000000000000000000000000000000000012fd1" From 356194303ecb83a7c02cbece86ed90d2d4b13b4d Mon Sep 17 00:00:00 2001 From: varasev <33550681+varasev@users.noreply.github.com> Date: Thu, 14 May 2020 17:17:29 +0300 Subject: [PATCH 75/75] Update .dialyzer-ignore --- .dialyzer-ignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.dialyzer-ignore b/.dialyzer-ignore index 9af33f21ff44..174062d396f5 100644 --- a/.dialyzer-ignore +++ b/.dialyzer-ignore @@ -14,4 +14,4 @@ apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The test 5 == ' lib/block_scout_web/router.ex:1 lib/phoenix/router.ex:324 lib/explorer/staking/stake_snapshotting.ex:14: Function do_snapshotting/6 has no local return -lib/explorer/staking/stake_snapshotting.ex:166 \ No newline at end of file +lib/explorer/staking/stake_snapshotting.ex:179