From cbb88f18fe93b99d63b51674359e1a9713037ee1 Mon Sep 17 00:00:00 2001 From: Lokraan Date: Fri, 14 Sep 2018 22:23:19 -0500 Subject: [PATCH 1/5] Validations are now viewable. Validation count, only shows validations if has them. Validated -> Blocks Validated, gettext(Validated) --- .../address_contract_controller.ex | 6 +- .../controllers/address_controller.ex | 4 + ...address_internal_transaction_controller.ex | 6 +- .../address_read_contract_controller.ex | 5 +- .../controllers/address_token_controller.ex | 3 +- .../address_transaction_controller.ex | 5 +- .../address_validation_controller.ex | 43 +++++ .../lib/block_scout_web/router.ex | 9 +- .../templates/address/overview.html.eex | 12 +- .../templates/address_contract/index.html.eex | 10 ++ .../index.html.eex | 32 +++- .../address_read_contract/index.html.eex | 10 ++ .../templates/address_token/index.html.eex | 65 +++++--- .../address_transaction/index.html.eex | 46 ++++-- .../address_validation/index.html.eex | 155 ++++++++++++++++++ .../views/address_validation_view.ex | 6 + apps/explorer/lib/explorer/chain.ex | 49 +++++- 17 files changed, 406 insertions(+), 60 deletions(-) create mode 100644 apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex create mode 100644 apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex create mode 100644 apps/block_scout_web/lib/block_scout_web/views/address_validation_view.ex diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex index 377be35b3c..4a965cee84 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex @@ -1,7 +1,7 @@ defmodule BlockScoutWeb.AddressContractController do use BlockScoutWeb, :controller - import BlockScoutWeb.AddressController, only: [transaction_count: 1] + import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token @@ -9,12 +9,14 @@ defmodule BlockScoutWeb.AddressContractController do def index(conn, %{"address_id" => address_hash_string}) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, address} <- Chain.find_contract_address(address_hash) do + render( conn, "index.html", address: address, exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), - transaction_count: transaction_count(address) + transaction_count: transaction_count(address), + validation_count: validation_count(address) ) else :error -> diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex index 2753dc8720..93ea2a688e 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex @@ -20,4 +20,8 @@ defmodule BlockScoutWeb.AddressController do def transaction_count(%Address{} = address) do Chain.address_to_transactions_estimated_count(address) end + + def validation_count(%Address{} = address) do + Chain.address_to_validation_count(address) + end end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex index b7e6079997..36c32740e7 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_internal_transaction_controller.ex @@ -5,7 +5,7 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do use BlockScoutWeb, :controller - import BlockScoutWeb.AddressController, only: [transaction_count: 1] + import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] import BlockScoutWeb.Chain, only: [current_filter: 1, paging_options: 1, next_page_params: 3, split_list_by_page: 1] alias Explorer.{Chain, Market} @@ -26,7 +26,6 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do |> Keyword.merge(current_filter(params)) internal_transactions_plus_one = Chain.address_to_internal_transactions(address, full_options) - {internal_transactions, next_page} = split_list_by_page(internal_transactions_plus_one) render( @@ -37,7 +36,8 @@ defmodule BlockScoutWeb.AddressInternalTransactionController do exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), filter: params["filter"], internal_transactions: internal_transactions, - transaction_count: transaction_count(address) + transaction_count: transaction_count(address), + validation_count: validation_count(address) ) else :error -> diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex index 1100fa3c8c..76c5147d2f 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex @@ -11,7 +11,7 @@ defmodule BlockScoutWeb.AddressReadContractController do alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token - import BlockScoutWeb.AddressController, only: [transaction_count: 1] + import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] def index(conn, %{"address_id" => address_hash_string}) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), @@ -21,7 +21,8 @@ defmodule BlockScoutWeb.AddressReadContractController do "index.html", address: address, exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), - transaction_count: transaction_count(address) + transaction_count: transaction_count(address), + validation_count: validation_count(address) ) else :error -> diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex index c2c7bea561..d5b77bd470 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex @@ -4,7 +4,7 @@ defmodule BlockScoutWeb.AddressTokenController do alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token - import BlockScoutWeb.AddressController, only: [transaction_count: 1] + import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] import BlockScoutWeb.Chain, only: [next_page_params: 3, paging_options: 1, split_list_by_page: 1] def index(conn, %{"address_id" => address_hash_string} = params) do @@ -19,6 +19,7 @@ defmodule BlockScoutWeb.AddressTokenController do address: address, exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), transaction_count: transaction_count(address), + validation_count: validation_count(address), next_page_params: next_page_params(next_page, tokens, params), tokens: tokens ) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex index 5bad1ddbae..584d28efba 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex @@ -5,7 +5,7 @@ defmodule BlockScoutWeb.AddressTransactionController do use BlockScoutWeb, :controller - import BlockScoutWeb.AddressController, only: [transaction_count: 1] + import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] import BlockScoutWeb.Chain, only: [current_filter: 1, paging_options: 1, next_page_params: 3, split_list_by_page: 1] alias Explorer.{Chain, Market} @@ -37,7 +37,8 @@ defmodule BlockScoutWeb.AddressTransactionController do exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), filter: params["filter"], transactions: transactions, - transaction_count: transaction_count(address) + transaction_count: transaction_count(address), + validation_count: validation_count(address) ) else :error -> diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex new file mode 100644 index 0000000000..0a4078d369 --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex @@ -0,0 +1,43 @@ + +defmodule BlockScoutWeb.AddressValidationController do + @moduledoc """ + Display all the blocks that this address validates. + """ + use BlockScoutWeb, :controller + + import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] + import BlockScoutWeb.Chain, only: + [paging_options: 1, next_page_params: 3, split_list_by_page: 1] + + alias Explorer.{Chain, Market} + alias Explorer.ExchangeRates.Token + + def index(conn, %{"address_id" => address_hash_string} = params) do + with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), + {:ok, address} <- Chain.hash_to_address(address_hash) do + + full_options = Keyword.merge( + [necessity_by_association: %{miner: :required, transactions: :optional}], + paging_options(params) + ) + + blocks_plus_one = Chain.get_blocks_validated_by_address(full_options, address) + {blocks, next_page} = split_list_by_page(blocks_plus_one) + + render(conn, "index.html", + address: address, + blocks: blocks, + transaction_count: transaction_count(address), + validation_count: validation_count(address), + exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), + next_page_params: next_page_params(next_page, blocks, params) + ) + else + :error -> + unprocessable_entity(conn) + + {:error, :not_found} -> + not_found(conn) + end + end +end diff --git a/apps/block_scout_web/lib/block_scout_web/router.ex b/apps/block_scout_web/lib/block_scout_web/router.ex index 44e2b90bd3..21a9838049 100644 --- a/apps/block_scout_web/lib/block_scout_web/router.ex +++ b/apps/block_scout_web/lib/block_scout_web/router.ex @@ -70,7 +70,7 @@ defmodule BlockScoutWeb.Router do resources "/address", AddressController, only: [:show] do resources("/transactions", AddressTransactionController, only: [:index], as: :transaction) - + resources( "/internal_transactions", AddressInternalTransactionController, @@ -78,6 +78,13 @@ defmodule BlockScoutWeb.Router do as: :internal_transaction ) + resources( + "/validations", + AddressValidationController, + only: [:index], + as: :validation + ) + resources( "/contracts", AddressContractController, diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex index ef8b5cd66c..eb593e04a9 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex @@ -17,15 +17,19 @@

<%= address_title(@address) %> <%= gettext "Details" %>

<%= @address.hash %>

-
<%= if address_name = primary_name(@address) do %> <%= address_name %> <% end %> - <%= Cldr.Number.to_string!(@transaction_count, format: "#,###") %> - - <%= gettext "Transactions" %> + + <%= Cldr.Number.to_string!(@transaction_count, format: "#,###") %> + <%= gettext("Transactions") %> + <%= if @validation_count > 0 do %> + + <%= Cldr.Number.to_string!(@validation_count, format: "#,###") %> + <%= gettext("Blocks Validated") %> + <% end %> <%= if @address.token do %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex index f8378f477d..0f2ed17229 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex @@ -29,6 +29,16 @@ to: address_internal_transaction_path(@conn, :index, @address.hash) ) %> + <%= if @validation_count > 0 do %> + + <% end %> + <%= if @validation_count > 0 do %> + + <% end %> <%= if contract?(@address) do %> + <%= if @validation_count > 0 do %> + + <% end %> - - - - + <%= if @validation_count > 0 do %> + + <% end %> <%= if AddressView.contract?(@address) do %> <% end %> - <%= if AddressView.smart_contract_with_read_only_functions?(@address) do %> + <%= if @validation_count > 0 do %> + + <% end %> <%= if contract?(@address) do %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex new file mode 100644 index 0000000000..91e70e8084 --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex @@ -0,0 +1,155 @@ +
+ <%= render BlockScoutWeb.AddressView, "overview.html", assigns %> + +
+
+
+ + + + +
+ +
+ + + + +

<%="Blocks #{gettext("Validated")}"%>

+ <%= if Enum.count(@blocks) > 0 do %> + + <%= for block <- @blocks do %> + <%= render BlockScoutWeb.BlockView, "_tile.html", block: block %> + <% end %> + + <% else %> +
+ <%= gettext "There are no validations for this address." %> +
+ <% end %> +
+ <%= if @next_page_params do %> + <%= link( + gettext("Older"), + class: "button button-secondary button-sm float-right mt-3", + to: address_validation_path( + @conn, + :index, + @address, + @next_page_params + ) + ) %> + <% end %> +
+
+
+
+
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_validation_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_validation_view.ex new file mode 100644 index 0000000000..f01bb31113 --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/views/address_validation_view.ex @@ -0,0 +1,6 @@ +defmodule BlockScoutWeb.AddressValidationView do + use BlockScoutWeb, :view + + import BlockScoutWeb.AddressView, + only: [contract?: 1, smart_contract_verified?: 1, smart_contract_with_read_only_functions?: 1] +end \ No newline at end of file diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 71ed5ea09e..f14055d417 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -826,7 +826,6 @@ defmodule Explorer.Chain do @doc """ Lists the top 250 `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance. - """ @spec list_top_addresses :: [Address.t()] def list_top_addresses do @@ -837,6 +836,54 @@ defmodule Explorer.Chain do |> Repo.all() end + @doc """ + Counts the number of `t:Explorer.Chain.Block.t/0` validated by the `address`. + """ + @spec address_to_validation_count(Address.t()) :: non_neg_integer() + def address_to_validation_count(%Address{hash: hash}) do + {:ok, %{rows: [[result]]}} = + SQL.query( + Repo, + """ + SELECT COUNT(hash) FROM "blocks" + WHERE "miner_hash" = $1 + """, + [hash.bytes] + ) + + result + end + + @doc """ + Finds all Blocks validated by the address given. + + ## Options + * `:necessity_by_association` - use to load `t:association/0` as `:required` or `:optional`. If an association is + `:required`, and the `t:Explorer.Chain.Block.t/0` has no associated record for that association, then the + `t:Explorer.Chain.Block.t/0` will not be included in the page `entries`. + * `:paging_options` - a `t:Explorer.PagingOptions.t/0` used to specify the `:page_size` and + `:key` (a tuple of the lowest/oldest `{block_number}`) and. Results will be the internal + transactions older than the `block_number` that are passed. + + Returns all blocks validated by the address given. + """ + @spec get_blocks_validated_by_address( + [paging_options | necessity_by_association_option], + Address.t() + ) :: [Block.t()] + def get_blocks_validated_by_address(options \\ [], %Address{hash: hash}) when is_list(options) do + necessity_by_association = Keyword.get(options, :necessity_by_association, %{}) + paging_options = Keyword.get(options, :paging_options, @default_paging_options) + + Block + |> join_associations(necessity_by_association) + |> where(miner_hash: ^hash) + |> page_blocks(paging_options) + |> limit(^paging_options.page_size) + |> order_by(desc: :number) + |> Repo.all() + end + @doc """ Returns a stream of unfetched `t:Explorer.Chain.Address.CoinBalance.t/0`. From a58b0bed6a46440a1a039c94e1f6e312f90d879d Mon Sep 17 00:00:00 2001 From: Lokraan Date: Sat, 15 Sep 2018 21:28:17 -0500 Subject: [PATCH 2/5] New validations are added to the page. Slice from end of list. --- .../assets/js/pages/address.js | 25 +++++++++++++++++++ .../block_scout_web/channels/block_channel.ex | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/js/pages/address.js b/apps/block_scout_web/assets/js/pages/address.js index c1ab083b36..4e99c1ddf8 100644 --- a/apps/block_scout_web/assets/js/pages/address.js +++ b/apps/block_scout_web/assets/js/pages/address.js @@ -93,6 +93,15 @@ export function reducer (state = initialState, action) { }) } } + case 'RECEIVED_NEW_BLOCK': { + if (state.channelDisconnected || state.beyondPageOne) return state + + return Object.assign({}, state, { + newBlock: action.msg.blockHtml, + minerHash: action.msg.blockMinerHash + }) + + } default: return state } @@ -116,6 +125,12 @@ if ($addressDetailsPage.length) { addressChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' })) addressChannel.on('balance', (msg) => store.dispatch({ type: 'RECEIVED_UPDATED_BALANCE', msg })) if (!state.beyondPageOne) { + const blocksChannel = socket.channel(`blocks:new_block`, {}) + blocksChannel.join() + blocksChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' })) + blocksChannel.on('new_block', (msg) => { + store.dispatch({ type: 'RECEIVED_NEW_BLOCK', msg: humps.camelizeKeys(msg) }) + }) addressChannel.on('transaction', batchChannel((msgs) => store.dispatch({ type: 'RECEIVED_NEW_TRANSACTION_BATCH', msgs }) )) @@ -135,6 +150,7 @@ if ($addressDetailsPage.length) { const $internalTransactionsList = $('[data-selector="internal-transactions-list"]') const $transactionCount = $('[data-selector="transaction-count"]') const $transactionsList = $('[data-selector="transactions-list"]') + const $validationsList = $('[data-selector="validations-list"]') if ($emptyInternalTransactionsList.length && state.newInternalTransactions.length) window.location.reload() if ($emptyTransactionsList.length && state.newTransactions.length) window.location.reload() @@ -159,6 +175,15 @@ if ($addressDetailsPage.length) { prependWithClingBottom($transactionsList, state.newTransactions.slice(oldState.newTransactions.length).reverse().join('')) updateAllAges() } + if (oldState.newBlock !== state.newBlock && state.minerHash == state.addressHash) { + const len = $validationsList.children().length + $validationsList + .children() + .slice(len - 1, len) + .remove() + + $validationsList.prepend(state.newBlock) + } } }) } diff --git a/apps/block_scout_web/lib/block_scout_web/channels/block_channel.ex b/apps/block_scout_web/lib/block_scout_web/channels/block_channel.ex index 3a78b40dfd..c499ae4a4a 100644 --- a/apps/block_scout_web/lib/block_scout_web/channels/block_channel.ex +++ b/apps/block_scout_web/lib/block_scout_web/channels/block_channel.ex @@ -34,7 +34,8 @@ defmodule BlockScoutWeb.BlockChannel do average_block_time: Timex.format_duration(average_block_time, :humanized), chain_block_html: rendered_chain_block, block_html: rendered_block, - block_number: block.number + block_number: block.number, + block_miner_hash: to_string(block.miner_hash) }) {:noreply, socket} From 92f99cac220069a3519daa0816811ba3565f0e91 Mon Sep 17 00:00:00 2001 From: Lokraan Date: Sat, 15 Sep 2018 22:01:37 -0500 Subject: [PATCH 3/5] Ran mix format on code. Confirm to CircleCi tests. Was failing due to not updating gettext, javascript lint standards, and an accidental edit in `block_controller.ex` where I added `:block => :required` to `necessity_by_association`. I also updated the query in `Explorer.Chain.address_to_validation_count/1` in order to make it more functional (use built in Ecto queries instead of hand written SQL query.) Conform to code review comments. Instances of "Blocks #{gettext("Validated")}" -> gettext("Blocks Validated") The class for the validation link in the mobile menus was "nav-link" instead of "dropdown-item" so I changed it. Ran `mix gettext.extract --merge` in order to update the gettext("Blocks Validated") Conform to code review. Added `active` classes to the corresponding links on mobile navs. Removed redundant if statements when in the page that required the content. Created a function in `address_view.ex` called `validator?` that accepts the number of validations and returns true if greater than 0. Replaced `if @validation_count > 0` with `if validator?(@validation_count`. "Please add the active class to the dropdown item." Added the `active` class where the page was active on for mobile and desktop navs. Also replaced `nav-item` with `dropdown-item` on the mobile navs where it was necessary. --- .../assets/js/pages/address.js | 1 - .../address_contract_controller.ex | 1 - .../address_validation_controller.ex | 20 +- .../lib/block_scout_web/router.ex | 2 +- .../templates/address_contract/index.html.eex | 54 +- .../index.html.eex | 65 +- .../address_read_contract/index.html.eex | 37 +- .../templates/address_token/index.html.eex | 40 +- .../address_transaction/index.html.eex | 51 +- .../address_validation/index.html.eex | 64 +- .../templates/chain/show.html.eex | 2 +- .../templates/tokens/token/show.html.eex | 94 + .../templates/transaction/index.html.eex | 4 +- .../address_internal_transaction_view.ex | 4 +- .../views/address_read_contract_view.ex | 2 +- .../views/address_transaction_view.ex | 4 +- .../views/address_validation_view.ex | 2 +- .../lib/block_scout_web/views/address_view.ex | 4 + apps/block_scout_web/priv/gettext/default.pot | 1840 ++++++++-------- .../priv/gettext/en/LC_MESSAGES/default.po | 1864 +++++++++-------- .../lib/ethereum_jsonrpc/receipt.ex | 15 +- apps/explorer/lib/explorer/chain.ex | 34 +- apps/explorer/lib/explorer/etherscan.ex | 3 +- apps/explorer/test/support/factory.ex | 3 +- 24 files changed, 2355 insertions(+), 1855 deletions(-) create mode 100644 apps/block_scout_web/lib/block_scout_web/templates/tokens/token/show.html.eex diff --git a/apps/block_scout_web/assets/js/pages/address.js b/apps/block_scout_web/assets/js/pages/address.js index 4e99c1ddf8..0ce909b513 100644 --- a/apps/block_scout_web/assets/js/pages/address.js +++ b/apps/block_scout_web/assets/js/pages/address.js @@ -100,7 +100,6 @@ export function reducer (state = initialState, action) { newBlock: action.msg.blockHtml, minerHash: action.msg.blockMinerHash }) - } default: return state diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex index 4a965cee84..4e694397e0 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_controller.ex @@ -9,7 +9,6 @@ defmodule BlockScoutWeb.AddressContractController do def index(conn, %{"address_id" => address_hash_string}) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, address} <- Chain.find_contract_address(address_hash) do - render( conn, "index.html", diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex index 0a4078d369..8ab0feccd9 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_validation_controller.ex @@ -1,4 +1,3 @@ - defmodule BlockScoutWeb.AddressValidationController do @moduledoc """ Display all the blocks that this address validates. @@ -6,8 +5,7 @@ defmodule BlockScoutWeb.AddressValidationController do use BlockScoutWeb, :controller import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] - import BlockScoutWeb.Chain, only: - [paging_options: 1, next_page_params: 3, split_list_by_page: 1] + import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] alias Explorer.{Chain, Market} alias Explorer.ExchangeRates.Token @@ -15,23 +13,25 @@ defmodule BlockScoutWeb.AddressValidationController do def index(conn, %{"address_id" => address_hash_string} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, address} <- Chain.hash_to_address(address_hash) do - - full_options = Keyword.merge( - [necessity_by_association: %{miner: :required, transactions: :optional}], - paging_options(params) - ) + full_options = + Keyword.merge( + [necessity_by_association: %{miner: :required, transactions: :optional}], + paging_options(params) + ) blocks_plus_one = Chain.get_blocks_validated_by_address(full_options, address) {blocks, next_page} = split_list_by_page(blocks_plus_one) - render(conn, "index.html", + render( + conn, + "index.html", address: address, blocks: blocks, transaction_count: transaction_count(address), validation_count: validation_count(address), exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), next_page_params: next_page_params(next_page, blocks, params) - ) + ) else :error -> unprocessable_entity(conn) diff --git a/apps/block_scout_web/lib/block_scout_web/router.ex b/apps/block_scout_web/lib/block_scout_web/router.ex index 21a9838049..7dedf9d87c 100644 --- a/apps/block_scout_web/lib/block_scout_web/router.ex +++ b/apps/block_scout_web/lib/block_scout_web/router.ex @@ -70,7 +70,7 @@ defmodule BlockScoutWeb.Router do resources "/address", AddressController, only: [:show] do resources("/transactions", AddressTransactionController, only: [:index], as: :transaction) - + resources( "/internal_transactions", AddressInternalTransactionController, diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex index 0f2ed17229..04a39a421a 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex @@ -9,34 +9,34 @@ @@ -87,6 +88,14 @@ "data-test": "internal_transactions_tab_link", to: address_internal_transaction_path(@conn, :index, @address.hash) ) %> + <%= if BlockScoutWeb.AddressView.validator?(@validation_count) do %> + <%= link( + gettext("Blocks Validated"), + class: "dropdown-item", + "data-test": "validations_tab_link", + to: address_validation_path(@conn, :index, @address.hash) + ) %> + <% end %> <%= link( to: address_contract_path(@conn, :index, @address.hash), class: "dropdown-item active") do %> @@ -165,7 +174,6 @@
- <% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex index 57151e522b..d677c803ed 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex @@ -10,30 +10,30 @@
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_read_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_read_contract/index.html.eex index 597095ef36..d4f9a41868 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_read_contract/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_read_contract/index.html.eex @@ -9,30 +9,30 @@ diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex index f4a2f910af..ccc19245bc 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex @@ -8,30 +8,30 @@