Merge branch 'master' into ab-remove-coin-geck-id-env-var

pull/2662/head
Ayrat Badykov 5 years ago committed by GitHub
commit 408de7fd59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      CHANGELOG.md
  2. 1
      apps/block_scout_web/assets/css/app.scss
  3. 86
      apps/block_scout_web/assets/css/components/_custom_tooltips_block_details.scss
  4. 12
      apps/block_scout_web/assets/css/components/_dashboard-banner.scss
  5. 7
      apps/block_scout_web/assets/css/components/_transaction.scss
  6. 10
      apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex
  7. 6
      apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
  8. 31
      apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex
  9. 9
      apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
  10. 388
      apps/block_scout_web/priv/gettext/default.pot
  11. 388
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  12. 20
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs
  13. 47
      apps/block_scout_web/test/block_scout_web/views/address_contract_view_test.exs
  14. 19
      apps/explorer/config/config.exs
  15. 4
      apps/explorer/lib/explorer/application.ex
  16. 98
      apps/explorer/lib/explorer/chain.ex
  17. 5
      apps/explorer/lib/explorer/chain/address_transaction_csv_exporter.ex
  18. 4
      apps/explorer/lib/explorer/chain/cache/block_number.ex
  19. 4
      apps/explorer/lib/explorer/chain/cache/blocks.ex
  20. 4
      apps/explorer/lib/explorer/chain/cache/transactions.ex
  21. 42
      apps/explorer/lib/explorer/chain/ordered_cache.ex
  22. 39
      apps/explorer/lib/explorer/chain/smart_contract.ex
  23. 44
      apps/explorer/lib/explorer/chain/transaction.ex
  24. 54
      apps/explorer/lib/explorer/chain_spec/parity/importer.ex
  25. 89
      apps/explorer/lib/explorer/chain_spec/poa/importer.ex
  26. 6
      apps/explorer/test/explorer/chain/cache/block_number_test.exs
  27. 2
      docs/env-variables.md

@ -1,6 +1,9 @@
## Current
### Features
- [#2588](https://github.com/poanetwork/blockscout/pull/2588) - add verification submission comment
- [#2505](https://github.com/poanetwork/blockscout/pull/2505) - support POA Network emission rewards
- [#2636](https://github.com/poanetwork/blockscout/pull/2636) - Execute all address' transactions page queries in parallel
- [#2596](https://github.com/poanetwork/blockscout/pull/2596) - support AuRa's empty step reward type
- [#2581](https://github.com/poanetwork/blockscout/pull/2581) - Add generic Map-like Cache behaviour and implementation
- [#2561](https://github.com/poanetwork/blockscout/pull/2561) - Add token's type to the response of tokenlist method
@ -9,6 +12,8 @@
- [#2497](https://github.com/poanetwork/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation
### Fixes
- [#2612](https://github.com/poanetwork/blockscout/pull/2612) - Add cache updating independently from Indexer
- [#2659](https://github.com/poanetwork/blockscout/pull/2659) - Multipurpose front-end part update
- [#2468](https://github.com/poanetwork/blockscout/pull/2468) - fix confirmations for non consensus blocks
- [#2610](https://github.com/poanetwork/blockscout/pull/2610) - use CoinGecko instead of CoinMarketcap for exchange rates
- [#2640](https://github.com/poanetwork/blockscout/pull/2640) - SVG network icons

@ -113,6 +113,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "components/new_smart_contract";
@import "components/radio_big";
@import "components/btn_no_border";
@import "components/custom_tooltips_block_details";
@import "theme/dark-theme";

@ -0,0 +1,86 @@
/* Custom Tooltips for Block Details Page */
.tooltipCustom {
position: relative;
display: inline-block;
}
.tooltipCustom .tooltiptextTopMiner {
visibility: hidden;
position: absolute;
width: 50%;
background-color: white;
color: black;
text-align: center;
border-radius: 6px;
left: 25%;
bottom: 100%;
padding: 15px 0px;
display: inline-block;
z-index: 1;
font-family: Nunito;
margin-bottom: 15px;
opacity: 0;
transition: opacity 0.5s;
@include media-breakpoint-down(lg) {
left: 60%;
}
}
.tooltipCustom .tooltiptextTopMiner::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: white transparent transparent transparent;
}
.tooltipCustom:hover .tooltiptextTopMiner {
visibility: visible;
opacity: 1;
}
.tooltipCustom .tooltiptextTopR {
visibility: hidden;
position: absolute;
width: 50%;
background-color: $primary;
color: white;
text-align: center;
border-radius: 6px;
left: 52%;
bottom: 120%;
padding: 15px 10px;
font-family: Nunito;
display: inline-block;
z-index: 1;
margin-bottom: 15px;
opacity: 0;
transition: opacity 0.5s;
@include media-breakpoint-down(lg) {
bottom: 100%;
padding: 9px 10px;
}
}
.tooltipCustom .tooltiptextTopR::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: $primary transparent transparent transparent;
}
.tooltipCustom:hover .tooltiptextTopR {
visibility: visible;
opacity: 1;
}
/* Custom Tooltips for Block Details Page end*/

@ -3,7 +3,7 @@ $dashboard-banner-gradient-end: lighten(
$dashboard-banner-gradient-start,
5%
) !default;
$dashboard-banner-network-plain-container-background-color: lighten($dashboard-banner-gradient-end, 5%)!default;
$dashboard-banner-network-plain-container-background-color: lighten($dashboard-banner-gradient-end, 5%) !default;
$dashboard-line-color-price: lighten($dashboard-banner-gradient-end, 5%) !default;
$dashboard-line-color-market: $secondary !default;
$dashboard-stats-item-label-color: #fff !default;
@ -20,6 +20,13 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa
overflow: hidden;
padding: 0;
position: relative;
height: 249px;
@include media-breakpoint-down(sm) {
height: auto;
}
@include media-breakpoint-down(md) {
height: auto;
}
}
.dashboard-banner {
@ -65,7 +72,7 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa
}
.dashboard-banner-chart-legend {
display: grid;
display: flex;
grid-template-columns: 1fr 1fr;
padding-bottom: 12px;
@ -74,6 +81,7 @@ $dashboard-banner-chart-axis-font-color: $dashboard-stats-item-value-color !defa
padding-left: 12px;
padding-top: 3px;
position: relative;
padding-right: 60px;
@include media-breakpoint-down(md) {
display: flex;

@ -43,4 +43,11 @@
text-decoration: underline;
}
}
}
.block-detail-number {
width: 25%;
@include media-breakpoint-down(sm) {
width: 60%;
}
}

@ -6,8 +6,8 @@
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
<div class="card-body" data-async-listing="<%= @current_path %>">
<div data-selector="channel-disconnected-message" style="display:none;">
<div data-selector="reload-button" class="alert alert-danger">
<a href="#" class="alert-link"><%= gettext "Connection Lost, click to load newer blocks" %></a>
<div data-selector="reload-button" class="alert alert-danger" style="padding: 0.75rem 0rem; cursor: pointer;">
<span href="#" class="alert alert-danger"><%= gettext "Connection Lost, click to load newer blocks" %></span>
</div>
</div>
@ -30,9 +30,9 @@
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
</button>
<div data-error-message class="alert alert-danger col-12 text-left" style="display: none; padding: 0.75rem 0rem; cursor: pointer;">
<span href="#" class="alert alert-danger"><%= gettext("Something went wrong, click to reload.") %></span>
</div>
<div data-empty-response-message style="display: none;">
<div class="tile tile-muted text-center" data-selector="empty-coin-balances-list">

@ -66,14 +66,14 @@
</button>
</div>
<div class="tile tile-muted mb-4">
<pre class="pre-scrollable line-numbers" data-activate-highlight><code class="solidity"><%= for {line, number} <- contract_lines_with_index(@address.smart_contract.contract_source_code) do %><div data-line-number="<%= number %>"><%= line %></div><% end %></code></pre>
<pre class="pre-scrollable line-numbers" data-activate-highlight><code class="solidity"><%= for {line, number} <- contract_lines_with_index(@address.smart_contract.contract_source_code, @address.smart_contract.inserted_at) do %><div data-line-number="<%= number %>"><%= line %></div><% end %></code></pre>
</div>
</section>
<section>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "Contract ABI" %></h3>
<button type="button" class="button button-secondary button-sm" id="button" data-clipboard-text="<%= format_smart_contract_abi(@address.smart_contract.abi) %>" aria-label="Copy Contract ABI">
<button type="button" class="btn-line" id="button" data-clipboard-text="<%= format_smart_contract_abi(@address.smart_contract.abi) %>" aria-label="Copy Contract ABI">
<%= gettext "Copy ABI" %>
</button>
</div>
@ -89,7 +89,7 @@
<% {:selfdestructed, transaction_init} -> %>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "Contract Creation Code" %></h3>
<button type="button" class="button button-secondary button-sm" id="button" data-clipboard-text="<%= transaction_init %>" aria-label="copy contract creation code">
<button type="button" class="btn-line" id="button" data-clipboard-text="<%= transaction_init %>" aria-label="copy contract creation code">
<%= gettext "Copy Contract Creation Code" %>
</button>
</div>

@ -8,7 +8,7 @@
<%= gettext("%{block_type} Details", block_type: block_type(@block)) %>
</h1>
<!-- Block Height -->
<h3 data-test="block_detail_number">
<h3 class="block-detail-number" data-test="block_detail_number" data-toggle="tooltip" data-placement="top" title="" data-original-title="The block number in which transactions were recorded.">
<%= if block_type(@block) == "Block" do %>
<%= gettext("Block Height: %{height}", height: @block.number) %> <%= if @block.number == 0, do: "- " <> gettext("Genesis Block")%>
<% else %>
@ -30,13 +30,12 @@
</div>
<hr>
<!-- Block details description list -->
<!-- Block Hash -->
<dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Hash" %></dt>
<dd class="col-sm-9"><a class="transaction__link"><%= to_string(@block.hash) %></a></dd>
<dd class="col-sm-9"><a class="transaction__link" data-toggle="tooltip" data-placement="top" title="" data-original-title="The SHA256 hash of the block."><%= to_string(@block.hash) %></a></dd>
</dl>
<%= unless @block.number == 0 do %>
@ -44,11 +43,13 @@
<dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Parent Hash" %></dt>
<dd class="col-sm-9">
<span data-toggle="tooltip" data-placement="top" title="" data-original-title="The SHA256 hash of the parent block." >
<%= link(
@block.parent_hash,
class: "transaction__link",
to: block_path(@conn, :show, @block.number - 1)
) %>
</span>
</dd>
</dl>
<% end %>
@ -57,7 +58,7 @@
<dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Difficulty" %></dt>
<dd class="col-sm-9">
<span><%= @block.difficulty |> BlockScoutWeb.Cldr.Number.to_string! %></span>
<span data-toggle="tooltip" data-placement="top" title="" data-original-title="Block difficulty for miner, used to calibrate block generation time (Note: constant in POA based networks)."><%= @block.difficulty |> BlockScoutWeb.Cldr.Number.to_string! %></span>
</dd>
</dl>
@ -65,13 +66,13 @@
<!-- Total Difficulty -->
<dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Total Difficulty" %></dt>
<dd class="col-sm-9"><span><%= @block.total_difficulty |> BlockScoutWeb.Cldr.Number.to_string! %></span></dd>
<dd class="col-sm-9"><span data-toggle="tooltip" data-placement="top" title="" data-original-title="Integer of the total difficulty of the chain until this block."><%= @block.total_difficulty |> BlockScoutWeb.Cldr.Number.to_string! %></span></dd>
</dl>
<!-- Nonce -->
<dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Nonce" %></dt>
<dd class="col-sm-9"><span><%= to_string(@block.nonce) %></span></dd>
<dd class="col-sm-9"><span data-toggle="tooltip" data-placement="top" title="" data-original-title="64-bit hash of value verifying proof-of-work (note: null for POA chains)."><%= to_string(@block.nonce) %></span></dd>
</dl>
<%= if length(@block.uncle_relations) > 0 do %>
@ -83,6 +84,9 @@
<%= link(
gettext("Position %{index}", index: index),
class: "transaction__link",
"data-toggle": "tooltip",
"data-placement": "top" ,
"data-original-title": "Index position(s) of referenced stale blocks." ,
"data-test": "uncle_link",
"data-uncle-hash": to_string(relation.uncle_hash),
to: block_path(@conn, :show, relation.uncle_hash)
@ -97,14 +101,14 @@
<dl class="row">
<dt class="col-sm-3 text-muted"><%= gettext "Gas Used" %></dt>
<dd class="col-sm-9">
<span><%= @block.gas_used |> BlockScoutWeb.Cldr.Number.to_string! %></span>
<span class="text-muted">(<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> BlockScoutWeb.Cldr.Number.to_string!(format: "#.#%") %>)</span>
<span data-toggle="tooltip" data-placement="top" title="" data-original-title="Total gas used by all transactions in this block (limit)."><%= @block.gas_used |> BlockScoutWeb.Cldr.Number.to_string! %></span>
<span class="text-muted" data-toggle="tooltip" data-placement="top" title="" data-original-title="Total gas used by all transactions in this block (% used).">(<%= (Decimal.to_integer(@block.gas_used) / Decimal.to_integer(@block.gas_limit)) |> BlockScoutWeb.Cldr.Number.to_string!(format: "#.#%") %>)</span>
</dt>
</dl>
<dl class="row mb-0">
<dt class="col-sm-3 text-muted"><%= gettext "Gas Limit" %></dt>
<dd class="col-sm-9">
<span><%= BlockScoutWeb.Cldr.Number.to_string!(@block.gas_limit) %></span>
<span data-toggle="tooltip" data-placement="top" title="" data-original-title="The maximum gas allowed in this block."><%= BlockScoutWeb.Cldr.Number.to_string!(@block.gas_limit) %></span>
</dd>
</dl>
<% end %>
@ -119,9 +123,12 @@
<div class="card card-background-1 flex-grow-1">
<div class="card-body card-body-flex-column-space-between">
<h2 class="card-title balance-card-title"><%= gettext "Miner" %></h2>
<div class="text-right">
<div class="text-right tooltipCustom">
<!-- Validator's Name -->
<h3 class="address-balance-text text-truncate">
<span class="tooltiptextTopMiner"> Validator's Name</span>
<h3 class="address-balance-text text-truncate" >
<%= render BlockScoutWeb.AddressView,
"_link.html",
address: @block.miner,
@ -137,7 +144,7 @@
<div class="card-body card-body-flex-column-space-between">
<%= if show_reward?(@block.rewards) do %>
<h2 class="card-title balance-card-title"><%= gettext "Block Rewards" %></h2>
<div class="text-right">
<div class="text-right" style="margin-left: 50%;" data-toggle="tooltip" data-placement="top" title="" data-original-title="Amount of distributed reward. Miners receive a static block reward + Tx fees + uncle fees.">
<%= for block_reward <- @block.rewards do %>
<p class="address-current-balance"><%= block_reward_text(block_reward) %> <span class="text-muted"><%= format_wei_value(block_reward.reward, :ether) %></span></p>
<% end %>

@ -2,7 +2,7 @@ defmodule BlockScoutWeb.AddressContractView do
use BlockScoutWeb, :view
alias ABI.{FunctionSelector, TypeDecoder}
alias Explorer.Chain.{Address, Data, InternalTransaction}
alias Explorer.Chain.{Address, Data, InternalTransaction, SmartContract}
def render("scripts.html", %{conn: conn}) do
render_scripts(conn, "address_contract/code_highlighting.js")
@ -63,8 +63,11 @@ defmodule BlockScoutWeb.AddressContractView do
end)
end
def contract_lines_with_index(contract_source_code) do
contract_lines = String.split(contract_source_code, "\n")
def contract_lines_with_index(source_code, inserted_at \\ nil) do
contract_lines =
source_code
|> String.split("\n")
|> SmartContract.add_submitted_comment(inserted_at)
max_digits =
contract_lines

@ -226,11 +226,6 @@ msgstr ""
msgid "Block Pending"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:139
msgid "Block Rewards"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/block_transaction_view.ex:15
msgid "Block not found, please try again later."
@ -484,6 +479,11 @@ msgstr ""
msgid "Copy Txn Hash"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:59
msgid "Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:66
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:119
@ -560,6 +560,20 @@ msgstr ""
msgid "Decompiler version"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:56
#: lib/block_scout_web/templates/block/overview.html.eex:109
#: lib/block_scout_web/templates/block/overview.html.eex:159
msgid "Gas Limit"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:61
#: lib/block_scout_web/templates/block/overview.html.eex:102
#: lib/block_scout_web/templates/block/overview.html.eex:153
msgid "Gas Used"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:23
msgid "Delegate Call"
@ -580,11 +594,6 @@ msgstr ""
msgid "Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:58
msgid "Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:98
msgid "Displaying the init data provided of the creating transaction."
@ -646,6 +655,13 @@ msgstr ""
msgid "Error rendering value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:125
#: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_balance_card.html.eex:32
msgid "Error trying to fetch balances."
@ -695,6 +711,12 @@ msgstr ""
msgid "Execute"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:74
#: lib/block_scout_web/templates/transaction/overview.html.eex:79
msgid "Nonce"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:120
msgid "External libraries"
@ -745,22 +767,13 @@ msgid "GET"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:227
msgid "Gas"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:56
#: lib/block_scout_web/templates/block/overview.html.eex:105
#: lib/block_scout_web/templates/block/overview.html.eex:152
msgid "Gas Limit"
#: lib/block_scout_web/templates/block/overview.html.eex:85
msgid "Position %{index}"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:61
#: lib/block_scout_web/templates/block/overview.html.eex:98
#: lib/block_scout_web/templates/block/overview.html.eex:146
msgid "Gas Used"
#: lib/block_scout_web/templates/transaction/overview.html.eex:227
msgid "Gas"
msgstr ""
#, elixir-format
@ -785,7 +798,7 @@ msgid "Gwei"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:37
msgid "Hash"
msgstr ""
@ -816,6 +829,156 @@ msgstr ""
msgid "If it still does not show up after 1 hour, please check with your sender/exchange/wallet/transaction provider for additional information."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:185
msgid "Success"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:21
#: lib/block_scout_web/templates/transaction/_tile.html.eex:32
#: lib/block_scout_web/templates/transaction/overview.html.eex:84
msgid "TX Fee"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_footer.html.eex:25
msgid "Telegram"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:26
msgid "There are no holders for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:65
msgid "There are no internal transactions for this address."
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:15
msgid "There are no internal transactions for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:18
msgid "There are no logs for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:15
msgid "There are no token transfers for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:18
msgid "There are no tokens for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:26
msgid "There are no tokens."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:64
msgid "There are no transactions for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block_transaction/index.html.eex:28
msgid "There are no transactions for this block."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:25
msgid "There are no transfers for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:35
msgid "This transaction is pending confirmation."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:33
#: lib/block_scout_web/templates/address_transaction/index.html.eex:29
#: lib/block_scout_web/views/address_internal_transaction_view.ex:6
#: lib/block_scout_web/views/address_transaction_view.ex:6
msgid "To"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Toggle navigation"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:10
msgid "Token Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:16
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:9
#: lib/block_scout_web/views/tokens/overview_view.ex:36
msgid "Token Holders"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/_token.html.eex:11
msgid "Token ID"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:5
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
#: lib/block_scout_web/views/transaction_view.ex:259
msgid "Token Transfer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:3
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:15
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7
#: lib/block_scout_web/views/tokens/overview_view.ex:35
#: lib/block_scout_web/views/transaction_view.ex:313
msgid "Token Transfers"
msgstr ""
#, elixir-format
#: 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
msgid "Tokens"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_metatags.html.eex:13
msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:68
msgid "Total Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:56
msgid "Total transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:18
#: lib/block_scout_web/views/transaction_view.ex:262
msgid "Transaction"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/not_found.html.eex:12
msgid "If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page."
@ -984,13 +1147,6 @@ msgstr ""
msgid "Method Id"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:121
#: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/block_view.ex:56
msgid "Miner Reward"
@ -1045,12 +1201,6 @@ msgstr ""
msgid "No"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:73
#: lib/block_scout_web/templates/transaction/overview.html.eex:79
msgid "Nonce"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:36
#: lib/block_scout_web/templates/transaction/_tile.html.eex:68
@ -1097,7 +1247,7 @@ msgid "Parameters"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:45
#: lib/block_scout_web/templates/block/overview.html.eex:44
msgid "Parent Hash"
msgstr ""
@ -1113,11 +1263,6 @@ msgstr ""
msgid "Pending Transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:84
msgid "Position %{index}"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:17
msgid "Potential matches from our contract method database:"
@ -1259,6 +1404,11 @@ msgstr ""
msgid "Show Validator Info"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:146
msgid "Block Rewards"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
@ -1300,29 +1450,11 @@ msgstr ""
msgid "Submit an Issue"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:185
msgid "Success"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_footer.html.eex:37
msgid "Support"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:21
#: lib/block_scout_web/templates/transaction/_tile.html.eex:32
#: lib/block_scout_web/templates/transaction/overview.html.eex:84
msgid "TX Fee"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_footer.html.eex:25
msgid "Telegram"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_footer.html.eex:57
msgid "Test Networks"
@ -1343,77 +1475,26 @@ msgstr ""
msgid "There are no blocks."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:26
msgid "There are no holders for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:65
msgid "There are no internal transactions for this address."
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:15
msgid "There are no internal transactions for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:26
msgid "There are no logs for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:18
msgid "There are no logs for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:23
msgid "There are no pending transactions."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:15
msgid "There are no token transfers for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:17
msgid "There are no token transfers for this transaction"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:18
msgid "There are no tokens for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:26
msgid "There are no tokens."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:64
msgid "There are no transactions for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block_transaction/index.html.eex:28
msgid "There are no transactions for this block."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/index.html.eex:26
msgid "There are no transactions."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:25
msgid "There are no transfers for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:39
msgid "There is no coin history for this address."
@ -1450,19 +1531,6 @@ msgstr ""
msgid "This is useful to allow sending requests to blockscout without having to change anything about the request."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:35
msgid "This transaction is pending confirmation."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:33
#: lib/block_scout_web/templates/address_transaction/index.html.eex:29
#: lib/block_scout_web/views/address_internal_transaction_view.ex:6
#: lib/block_scout_web/views/address_transaction_view.ex:6
msgid "To"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:19
msgid "To have guaranteed accuracy, use the link above to verify the contract's source code."
@ -1475,58 +1543,6 @@ msgstr ""
msgid "To see accurate decoded input data, the contract must be verified."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Toggle navigation"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:10
msgid "Token Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:16
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:9
#: lib/block_scout_web/views/tokens/overview_view.ex:36
msgid "Token Holders"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/_token.html.eex:11
msgid "Token ID"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:5
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
#: lib/block_scout_web/views/transaction_view.ex:259
msgid "Token Transfer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:3
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:15
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7
#: lib/block_scout_web/views/tokens/overview_view.ex:35
#: lib/block_scout_web/views/transaction_view.ex:313
msgid "Token Transfers"
msgstr ""
#, elixir-format
#: 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
msgid "Tokens"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_metatags.html.eex:13
msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:12
msgid "Topic"
@ -1538,11 +1554,6 @@ msgstr ""
msgid "Topics"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:75
msgid "Total Supply"
@ -1553,17 +1564,6 @@ msgstr ""
msgid "Total blocks"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:56
msgid "Total transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:18
#: lib/block_scout_web/views/transaction_view.ex:262
msgid "Transaction"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_metatags.html.eex:3
msgid "Transaction %{transaction} - %{subnetwork} Explorer"
@ -1647,7 +1647,7 @@ msgid "Uncle Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/block/overview.html.eex:81
#: lib/block_scout_web/templates/layout/_topnav.html.eex:38
msgid "Uncles"
msgstr ""

@ -226,11 +226,6 @@ msgstr ""
msgid "Block Pending"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:139
msgid "Block Rewards"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/block_transaction_view.ex:15
msgid "Block not found, please try again later."
@ -484,6 +479,11 @@ msgstr ""
msgid "Copy Txn Hash"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:59
msgid "Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:66
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:119
@ -560,6 +560,20 @@ msgstr ""
msgid "Decompiler version"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:56
#: lib/block_scout_web/templates/block/overview.html.eex:109
#: lib/block_scout_web/templates/block/overview.html.eex:159
msgid "Gas Limit"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:61
#: lib/block_scout_web/templates/block/overview.html.eex:102
#: lib/block_scout_web/templates/block/overview.html.eex:153
msgid "Gas Used"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:23
msgid "Delegate Call"
@ -580,11 +594,6 @@ msgstr ""
msgid "Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:58
msgid "Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:98
msgid "Displaying the init data provided of the creating transaction."
@ -646,6 +655,13 @@ msgstr ""
msgid "Error rendering value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:125
#: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_balance_card.html.eex:32
msgid "Error trying to fetch balances."
@ -695,6 +711,12 @@ msgstr ""
msgid "Execute"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:74
#: lib/block_scout_web/templates/transaction/overview.html.eex:79
msgid "Nonce"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:120
msgid "External libraries"
@ -745,22 +767,13 @@ msgid "GET"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:227
msgid "Gas"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:56
#: lib/block_scout_web/templates/block/overview.html.eex:105
#: lib/block_scout_web/templates/block/overview.html.eex:152
msgid "Gas Limit"
#: lib/block_scout_web/templates/block/overview.html.eex:85
msgid "Position %{index}"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:61
#: lib/block_scout_web/templates/block/overview.html.eex:98
#: lib/block_scout_web/templates/block/overview.html.eex:146
msgid "Gas Used"
#: lib/block_scout_web/templates/transaction/overview.html.eex:227
msgid "Gas"
msgstr ""
#, elixir-format
@ -785,7 +798,7 @@ msgid "Gwei"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:37
msgid "Hash"
msgstr ""
@ -816,6 +829,156 @@ msgstr ""
msgid "If it still does not show up after 1 hour, please check with your sender/exchange/wallet/transaction provider for additional information."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:185
msgid "Success"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:21
#: lib/block_scout_web/templates/transaction/_tile.html.eex:32
#: lib/block_scout_web/templates/transaction/overview.html.eex:84
msgid "TX Fee"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_footer.html.eex:25
msgid "Telegram"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:26
msgid "There are no holders for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:65
msgid "There are no internal transactions for this address."
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:15
msgid "There are no internal transactions for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:18
msgid "There are no logs for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:15
msgid "There are no token transfers for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:18
msgid "There are no tokens for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:26
msgid "There are no tokens."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:64
msgid "There are no transactions for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block_transaction/index.html.eex:28
msgid "There are no transactions for this block."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:25
msgid "There are no transfers for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:35
msgid "This transaction is pending confirmation."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:33
#: lib/block_scout_web/templates/address_transaction/index.html.eex:29
#: lib/block_scout_web/views/address_internal_transaction_view.ex:6
#: lib/block_scout_web/views/address_transaction_view.ex:6
msgid "To"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Toggle navigation"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:10
msgid "Token Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:16
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:9
#: lib/block_scout_web/views/tokens/overview_view.ex:36
msgid "Token Holders"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/_token.html.eex:11
msgid "Token ID"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:5
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
#: lib/block_scout_web/views/transaction_view.ex:259
msgid "Token Transfer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:3
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:15
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7
#: lib/block_scout_web/views/tokens/overview_view.ex:35
#: lib/block_scout_web/views/transaction_view.ex:313
msgid "Token Transfers"
msgstr ""
#, elixir-format
#: 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
msgid "Tokens"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_metatags.html.eex:13
msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:68
msgid "Total Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:56
msgid "Total transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:18
#: lib/block_scout_web/views/transaction_view.ex:262
msgid "Transaction"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/not_found.html.eex:12
msgid "If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page."
@ -984,13 +1147,6 @@ msgstr ""
msgid "Method Id"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:121
#: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/block_view.ex:56
msgid "Miner Reward"
@ -1045,12 +1201,6 @@ msgstr ""
msgid "No"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:73
#: lib/block_scout_web/templates/transaction/overview.html.eex:79
msgid "Nonce"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:36
#: lib/block_scout_web/templates/transaction/_tile.html.eex:68
@ -1097,7 +1247,7 @@ msgid "Parameters"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:45
#: lib/block_scout_web/templates/block/overview.html.eex:44
msgid "Parent Hash"
msgstr ""
@ -1113,11 +1263,6 @@ msgstr ""
msgid "Pending Transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:84
msgid "Position %{index}"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:17
msgid "Potential matches from our contract method database:"
@ -1259,6 +1404,11 @@ msgstr ""
msgid "Show Validator Info"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:146
msgid "Block Rewards"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
@ -1300,29 +1450,11 @@ msgstr ""
msgid "Submit an Issue"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:185
msgid "Success"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_footer.html.eex:37
msgid "Support"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:21
#: lib/block_scout_web/templates/transaction/_tile.html.eex:32
#: lib/block_scout_web/templates/transaction/overview.html.eex:84
msgid "TX Fee"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_footer.html.eex:25
msgid "Telegram"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_footer.html.eex:57
msgid "Test Networks"
@ -1343,77 +1475,26 @@ msgstr ""
msgid "There are no blocks."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:26
msgid "There are no holders for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:65
msgid "There are no internal transactions for this address."
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:15
msgid "There are no internal transactions for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:26
msgid "There are no logs for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:18
msgid "There are no logs for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:23
msgid "There are no pending transactions."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:15
msgid "There are no token transfers for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:17
msgid "There are no token transfers for this transaction"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:18
msgid "There are no tokens for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:26
msgid "There are no tokens."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:64
msgid "There are no transactions for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block_transaction/index.html.eex:28
msgid "There are no transactions for this block."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/index.html.eex:26
msgid "There are no transactions."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:25
msgid "There are no transfers for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:39
msgid "There is no coin history for this address."
@ -1450,19 +1531,6 @@ msgstr ""
msgid "This is useful to allow sending requests to blockscout without having to change anything about the request."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/overview.html.eex:35
msgid "This transaction is pending confirmation."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:33
#: lib/block_scout_web/templates/address_transaction/index.html.eex:29
#: lib/block_scout_web/views/address_internal_transaction_view.ex:6
#: lib/block_scout_web/views/address_transaction_view.ex:6
msgid "To"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:19
msgid "To have guaranteed accuracy, use the link above to verify the contract's source code."
@ -1475,58 +1543,6 @@ msgstr ""
msgid "To see accurate decoded input data, the contract must be verified."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:20
msgid "Toggle navigation"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:10
msgid "Token Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:16
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:9
#: lib/block_scout_web/views/tokens/overview_view.ex:36
msgid "Token Holders"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/_token.html.eex:11
msgid "Token ID"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:5
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
#: lib/block_scout_web/views/transaction_view.ex:259
msgid "Token Transfer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:3
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:15
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7
#: lib/block_scout_web/views/tokens/overview_view.ex:35
#: lib/block_scout_web/views/transaction_view.ex:313
msgid "Token Transfers"
msgstr ""
#, elixir-format
#: 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
msgid "Tokens"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_metatags.html.eex:13
msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:12
msgid "Topic"
@ -1538,11 +1554,6 @@ msgstr ""
msgid "Topics"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:75
msgid "Total Supply"
@ -1553,17 +1564,6 @@ msgstr ""
msgid "Total blocks"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:56
msgid "Total transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:18
#: lib/block_scout_web/views/transaction_view.ex:262
msgid "Transaction"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_metatags.html.eex:3
msgid "Transaction %{transaction} - %{subnetwork} Explorer"
@ -1647,7 +1647,7 @@ msgid "Uncle Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/block/overview.html.eex:81
#: lib/block_scout_web/templates/layout/_topnav.html.eex:38
msgid "Uncles"
msgstr ""

@ -1,6 +1,6 @@
defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
use BlockScoutWeb.ConnCase
alias Explorer.Factory
alias Explorer.{Chain, Factory}
describe "listcontracts" do
setup do
@ -450,7 +450,9 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
expected_result = [
%{
"Address" => to_string(contract.address_hash),
"SourceCode" => contract.contract_source_code,
"SourceCode" =>
"/**\n* Submitted for verification at blockscout.com on #{contract.inserted_at}\n*/\n" <>
contract.contract_source_code,
"ABI" => Jason.encode!(contract.abi),
"ContractName" => contract.name,
"CompilerVersion" => contract.compiler_version,
@ -496,9 +498,13 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
|> get("/api", params)
|> json_response(200)
verified_contract = Chain.address_hash_to_smart_contract(contract_address.hash)
expected_result = %{
"Address" => to_string(contract_address.hash),
"SourceCode" => contract_code_info.source_code,
"SourceCode" =>
"/**\n* Submitted for verification at blockscout.com on #{verified_contract.inserted_at}\n*/\n" <>
contract_code_info.source_code,
"ABI" => Jason.encode!(contract_code_info.abi),
"ContractName" => contract_code_info.name,
"CompilerVersion" => contract_code_info.version,
@ -563,8 +569,14 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
result = response["result"]
verified_contract = Chain.address_hash_to_smart_contract(contract_address.hash)
assert result["Address"] == to_string(contract_address.hash)
assert result["SourceCode"] == contract_source_code
assert result["SourceCode"] ==
"/**\n* Submitted for verification at blockscout.com on #{verified_contract.inserted_at}\n*/\n" <>
contract_source_code
assert result["ContractName"] == name
assert result["DecompiledSourceCode"] == "Contract source code not decompiled."
assert result["DecompilerVersion"] == ""

@ -38,22 +38,25 @@ defmodule BlockScoutWeb.AddressContractViewTest do
result = AddressContractView.contract_lines_with_index(code)
assert result == [
{"pragma solidity >=0.4.22 <0.6.0;", " 1"},
{"", " 2"},
{"struct Proposal {", " 3"},
{" uint voteCount;", " 4"},
{"}", " 5"},
{"", " 6"},
{"address chairperson;", " 7"},
{"mapping(address => Voter) voters;", " 8"},
{"Proposal[] proposals;", " 9"},
{"", "10"},
{"constructor(uint8 _numProposals) public {", "11"},
{" chairperson = msg.sender;", "12"},
{" voters[chairperson].weight = 1;", "13"},
{" proposals.length = _numProposals;", "14"},
{"}", "15"},
{"", "16"}
{"/**", " 1"},
{"* Submitted for verification at blockscout.com on ", " 2"},
{"*/", " 3"},
{"pragma solidity >=0.4.22 <0.6.0;", " 4"},
{"", " 5"},
{"struct Proposal {", " 6"},
{" uint voteCount;", " 7"},
{"}", " 8"},
{"", " 9"},
{"address chairperson;", "10"},
{"mapping(address => Voter) voters;", "11"},
{"Proposal[] proposals;", "12"},
{"", "13"},
{"constructor(uint8 _numProposals) public {", "14"},
{" chairperson = msg.sender;", "15"},
{" voters[chairperson].weight = 1;", "16"},
{" proposals.length = _numProposals;", "17"},
{"}", "18"},
{"", "19"}
]
end
@ -66,7 +69,17 @@ defmodule BlockScoutWeb.AddressContractViewTest do
test "returns a list of tuples and the first element is just a line from the original string" do
result = AddressContractView.contract_lines_with_index("a\nb\nc\nd\ne")
assert Enum.map(result, fn {line, _number} -> line end) == ["a", "b", "c", "d", "e"]
assert Enum.map(result, fn {line, _number} -> line end) == [
"/**",
"* Submitted for verification at blockscout.com on ",
"*/",
"a",
"b",
"c",
"d",
"e"
]
end
end
end

@ -27,9 +27,16 @@ config :explorer, Explorer.Counters.AverageBlockTime,
enabled: true,
period: average_block_period
config :explorer, Explorer.ChainSpec.GenesisData, enabled: false, chain_spec_path: System.get_env("CHAIN_SPEC_PATH")
config :explorer, Explorer.ChainSpec.GenesisData,
enabled: true,
chain_spec_path: System.get_env("CHAIN_SPEC_PATH"),
emission_format: System.get_env("EMISSION_FORMAT", "DEFAULT"),
rewards_contract_address: System.get_env("REWARDS_CONTRACT_ADDRESS", "0xeca443e8e1ab29971a45a9c57a6a9875701698a5")
config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true
config :explorer, Explorer.Chain.Cache.BlockNumber,
enabled: true,
ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false),
global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5))
balances_update_interval =
if System.get_env("ADDRESS_WITH_BALANCES_UPDATE_INTERVAL") do
@ -121,6 +128,14 @@ market_history_cache_period =
config :explorer, Explorer.Market.MarketHistoryCache, period: market_history_cache_period
config :explorer, Explorer.Chain.Cache.Blocks,
ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false),
global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5))
config :explorer, Explorer.Chain.Cache.Transactions,
ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false),
global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5))
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"

@ -56,9 +56,7 @@ defmodule Explorer.Application do
opts = [strategy: :one_for_one, name: Explorer.Supervisor]
res = Supervisor.start_link(children, opts)
res
Supervisor.start_link(children, opts)
end
defp configurable_children do

@ -230,9 +230,8 @@ defmodule Explorer.Chain do
Reward.fetch_emission_rewards_tuples(address_hash, paging_options)
end)
address_hash
|> address_to_transactions_without_rewards(paging_options, options)
|> Enum.concat(Task.await(rewards_task, :timer.seconds(20)))
[rewards_task | address_to_transactions_tasks(address_hash, options)]
|> wait_for_address_transactions()
|> Enum.sort_by(fn item ->
case item do
{%Reward{} = emission_reward, _} ->
@ -242,25 +241,76 @@ defmodule Explorer.Chain do
{-item.block_number, -item.index}
end
end)
|> Enum.dedup_by(fn item ->
case item do
{%Reward{} = emission_reward, _} ->
{emission_reward.block_hash, emission_reward.address_hash, emission_reward.address_type}
transaction ->
transaction.hash
end
end)
|> Enum.take(paging_options.page_size)
else
address_to_transactions_without_rewards(address_hash, paging_options, options)
address_to_transactions_without_rewards(address_hash, options)
end
end
def address_to_transactions_without_rewards(address_hash, paging_options, options) do
def address_to_transactions_without_rewards(address_hash, options) do
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
address_hash
|> address_to_transactions_tasks(options)
|> wait_for_address_transactions()
|> Enum.sort_by(&{&1.block_number, &1.index}, &>=/2)
|> Enum.dedup_by(& &1.hash)
|> Enum.take(paging_options.page_size)
end
defp address_to_transactions_tasks(address_hash, options) do
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
direction = Keyword.get(options, :direction)
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
transaction_hashes_from_token_transfers =
TokenTransfer.where_any_address_fields_match(direction, address_hash, paging_options)
base_query =
paging_options
|> fetch_transactions()
|> join_associations(necessity_by_association)
|> Transaction.preload_token_transfers(address_hash)
paging_options
|> fetch_transactions()
|> Transaction.where_transaction_matches(transaction_hashes_from_token_transfers, direction, address_hash)
|> join_associations(necessity_by_association)
|> Transaction.preload_token_transfers(address_hash)
|> Repo.all()
direction_tasks =
base_query
|> Transaction.matching_address_queries_list(direction, address_hash)
|> Enum.map(fn query -> Task.async(fn -> Repo.all(query) end) end)
token_transfers_task =
Task.async(fn ->
transaction_hashes_from_token_transfers =
TokenTransfer.where_any_address_fields_match(direction, address_hash, paging_options)
final_query = where(base_query, [t], t.hash in ^transaction_hashes_from_token_transfers)
Repo.all(final_query)
end)
[token_transfers_task | direction_tasks]
end
defp wait_for_address_transactions(tasks) do
tasks
|> Task.yield_many(:timer.seconds(20))
|> Enum.flat_map(fn {_task, res} ->
case res do
{:ok, result} ->
result
{:exit, reason} ->
raise "Query fetching address transactions terminated: #{inspect(reason)}"
nil ->
raise "Query fetching address transactions timed out."
end
end)
end
@spec address_to_logs(Hash.Address.t(), Keyword.t()) :: [Log.t()]
@ -2542,8 +2592,26 @@ defmodule Explorer.Chain do
@spec address_hash_to_address_with_source_code(Hash.Address.t()) :: Address.t() | nil
def address_hash_to_address_with_source_code(address_hash) do
case Repo.get(Address, address_hash) do
nil -> nil
address -> Repo.preload(address, [:smart_contract, :decompiled_smart_contracts])
nil ->
nil
address ->
address_with_smart_contract = Repo.preload(address, [:smart_contract, :decompiled_smart_contracts])
if address_with_smart_contract.smart_contract do
formatted_code =
SmartContract.add_submitted_comment(
address_with_smart_contract.smart_contract.contract_source_code,
address_with_smart_contract.smart_contract.inserted_at
)
%{
address_with_smart_contract
| smart_contract: %{address_with_smart_contract.smart_contract | contract_source_code: formatted_code}
}
else
address_with_smart_contract
end
end
end

@ -42,8 +42,9 @@ defmodule Explorer.Chain.AddressTransactionCsvExporter do
end
defp fetch_all_transactions(address_hash, paging_options, acc \\ []) do
transactions =
Chain.address_to_transactions_without_rewards(address_hash, paging_options, @necessity_by_association)
options = Keyword.put(@necessity_by_association, :paging_options, paging_options)
transactions = Chain.address_to_transactions_without_rewards(address_hash, options)
new_acc = transactions ++ acc

@ -7,7 +7,9 @@ defmodule Explorer.Chain.Cache.BlockNumber do
use Explorer.Chain.MapCache,
name: :block_number,
keys: [:min, :max]
keys: [:min, :max],
ttl_check_interval: Application.get_env(:explorer, __MODULE__)[:ttl_check_interval],
global_ttl: Application.get_env(:explorer, __MODULE__)[:global_ttl]
alias Explorer.Chain

@ -11,7 +11,9 @@ defmodule Explorer.Chain.Cache.Blocks do
ids_list_key: "block_numbers",
preload: :transactions,
preload: [miner: :names],
preload: :rewards
preload: :rewards,
ttl_check_interval: Application.get_env(:explorer, __MODULE__)[:ttl_check_interval],
global_ttl: Application.get_env(:explorer, __MODULE__)[:global_ttl]
@type element :: Block.t()

@ -16,7 +16,9 @@ defmodule Explorer.Chain.Cache.Transactions do
token_transfers: :token,
token_transfers: :from_address,
token_transfers: :to_address
]
],
ttl_check_interval: Application.get_env(:explorer, __MODULE__)[:ttl_check_interval],
global_ttl: Application.get_env(:explorer, __MODULE__)[:global_ttl]
@type element :: Transaction.t()

@ -26,7 +26,10 @@ defmodule Explorer.Chain.OrderedCache do
preload: [transaction: :hash]
```
Additionally all of the options accepted by `ConCache.start_link/1` can be
provided as well. By default only `ttl_check_interval:` is set (to `false`).
provided as well. Unless specified, only these values have defaults:
- `:ttl_check_interval` is set (to `false`).
- `:callback` is only set if `:ttl_check_interval` is not `false` to call the
`remove_deleted_from_index` function, that removes expired values from the index.
It's also possible, and advised, to override the implementation of the `c:prevails?/2`
and `c:element_to_id/1` callbacks.
@ -131,10 +134,7 @@ defmodule Explorer.Chain.OrderedCache do
max_size = Keyword.get(opts, :max_size, 100)
preloads = Keyword.get(opts, :preloads) || Keyword.get_values(opts, :preload)
concache_params =
opts
|> Keyword.drop([:ids_list_key, :max_size, :preloads, :preload])
|> Keyword.put_new(:ttl_check_interval, false)
concache_params = Keyword.drop(opts, [:ids_list_key, :max_size, :preloads, :preload])
# credo:disable-for-next-line Credo.Check.Refactor.LongQuoteBlocks
quote do
@ -206,6 +206,19 @@ defmodule Explorer.Chain.OrderedCache do
### Updating function
def remove_deleted_from_index({:delete, _cache_pid, id}) do
# simply check with `ConCache.get` because it is faster
if Enum.member?(ids_list(), id) do
ConCache.update(cache_name(), ids_list_key(), fn ids ->
updated_list = List.delete(ids || [], id)
# ids_list is set to never expire
{:ok, %ConCache.Item{value: updated_list, ttl: :infinity}}
end)
end
end
def remove_deleted_from_index(_), do: nil
@impl OrderedCache
def update(elements) when is_nil(elements), do: :ok
@ -217,7 +230,8 @@ defmodule Explorer.Chain.OrderedCache do
|> Enum.sort(&prevails?(&1, &2))
|> merge_and_update(ids || [], max_size())
{:ok, updated_list}
# ids_list is set to never expire
{:ok, %ConCache.Item{value: updated_list, ttl: :infinity}}
end)
end
@ -308,7 +322,21 @@ defmodule Explorer.Chain.OrderedCache do
provided to this function will override the ones set by using the macro
"""
def child_spec(params) do
params = Keyword.merge(unquote(concache_params), params)
# params specified in `use`
merged_params =
unquote(concache_params)
# params specified in `child_spec`
|> Keyword.merge(params)
# `:ttl_check_interval` needs to be specified, defaults to `false`
|> Keyword.put_new(:ttl_check_interval, false)
# if `:ttl_check_interval` is not `false` the expired values need to be
# removed from the cache's index
params =
case merged_params[:ttl_check_interval] do
false -> merged_params
_ -> Keyword.put_new(merged_params, :callback, &remove_deleted_from_index/1)
end
Supervisor.child_spec({ConCache, params}, id: child_id())
end

@ -271,6 +271,45 @@ defmodule Explorer.Chain.SmartContract do
|> add_error(:contract_source_code, error_message(error))
end
def add_submitted_comment(code, inserted_at) when is_binary(code) do
code
|> String.split("\n")
|> add_submitted_comment(inserted_at)
|> Enum.join("\n")
end
def add_submitted_comment(contract_lines, inserted_at) when is_list(contract_lines) do
etherscan_index =
Enum.find_index(contract_lines, fn line ->
String.contains?(line, "Submitted for verification at Etherscan.io")
end)
blockscout_index =
Enum.find_index(contract_lines, fn line ->
String.contains?(line, "Submitted for verification at blockscout.com")
end)
cond do
etherscan_index && blockscout_index ->
List.replace_at(contract_lines, etherscan_index, "*")
etherscan_index && !blockscout_index ->
List.replace_at(
contract_lines,
etherscan_index,
"* Submitted for verification at blockscout.com on #{inserted_at}"
)
!etherscan_index && !blockscout_index ->
header = ["/**", "* Submitted for verification at blockscout.com on #{inserted_at}", "*/"]
header ++ contract_lines
true ->
contract_lines
end
end
defp upsert_contract_methods(%Ecto.Changeset{changes: %{abi: abi}} = changeset) do
ContractMethod.upsert_from_abi(abi, get_field(changeset, :address_hash))

@ -484,40 +484,26 @@ defmodule Explorer.Chain.Transaction do
end
@doc """
Modifies a query to filter for transactions whose hash is in a list or that are
linked to the given address_hash through a direction.
Be careful to not pass a large list, because this will lead to performance
problems.
Produces a list of queries starting from the given one and adding filters for
transactions that are linked to the given address_hash through a direction.
"""
def where_transaction_matches(query, transaction_hashes, :from, address_hash) do
where(
query,
[t],
t.hash in ^transaction_hashes or
t.from_address_hash == ^address_hash
)
def matching_address_queries_list(query, :from, address_hash) do
[where(query, [t], t.from_address_hash == ^address_hash)]
end
def where_transaction_matches(query, transaction_hashes, :to, address_hash) do
where(
query,
[t],
t.hash in ^transaction_hashes or
t.to_address_hash == ^address_hash or
t.created_contract_address_hash == ^address_hash
)
def matching_address_queries_list(query, :to, address_hash) do
[
where(query, [t], t.to_address_hash == ^address_hash),
where(query, [t], t.created_contract_address_hash == ^address_hash)
]
end
def where_transaction_matches(query, transaction_hashes, _direction, address_hash) do
where(
query,
[t],
t.hash in ^transaction_hashes or
t.from_address_hash == ^address_hash or
t.to_address_hash == ^address_hash or
t.created_contract_address_hash == ^address_hash
)
def matching_address_queries_list(query, _direction, address_hash) do
[
where(query, [t], t.from_address_hash == ^address_hash),
where(query, [t], t.to_address_hash == ^address_hash),
where(query, [t], t.created_contract_address_hash == ^address_hash)
]
end
@collated_fields ~w(block_number cumulative_gas_used gas_used index)a

@ -3,18 +3,23 @@ defmodule Explorer.ChainSpec.Parity.Importer do
Imports data from parity chain spec.
"""
require Logger
alias Explorer.{Chain, Repo}
alias Explorer.Chain.Block.{EmissionReward, Range}
alias Explorer.Chain.Hash.Address, as: AddressHash
alias Explorer.Chain.Wei
alias Explorer.ChainSpec.GenesisData
alias Explorer.ChainSpec.POA.Importer, as: PoaEmissionImporter
@max_block_number :infinity
def import_emission_rewards(chain_spec) do
rewards = emission_rewards(chain_spec)
{_, nil} = Repo.delete_all(EmissionReward)
{_, nil} = Repo.insert_all(EmissionReward, rewards)
if Application.get_env(:explorer, GenesisData)[:emission_format] == "POA" do
PoaEmissionImporter.import_emission_rewards()
else
import_rewards_from_chain_spec(chain_spec)
end
end
def import_genesis_coin_balances(chain_spec) do
@ -38,18 +43,37 @@ defmodule Explorer.ChainSpec.Parity.Importer do
Chain.import(params)
end
defp import_rewards_from_chain_spec(chain_spec) do
rewards = emission_rewards(chain_spec)
{_, nil} = Repo.delete_all(EmissionReward)
{_, nil} = Repo.insert_all(EmissionReward, rewards)
end
def genesis_coin_balances(chain_spec) do
accounts = chain_spec["accounts"]
parse_accounts(accounts)
if accounts do
parse_accounts(accounts)
else
Logger.warn(fn -> "No accounts are defined in chain spec" end)
[]
end
end
def emission_rewards(chain_spec) do
rewards = chain_spec["engine"]["Ethash"]["params"]["blockReward"]
rewards
|> parse_hex_numbers()
|> format_ranges()
if rewards do
rewards
|> parse_hex_numbers()
|> format_ranges()
else
Logger.warn(fn -> "No rewards are defined in chain spec" end)
[]
end
end
defp parse_accounts(accounts) do
@ -59,7 +83,7 @@ defmodule Explorer.ChainSpec.Parity.Importer do
end)
|> Stream.map(fn {address, %{"balance" => value}} ->
{:ok, address_hash} = AddressHash.cast(address)
balance = parse_hex_number(value)
balance = parse_number(value)
%{address_hash: address_hash, value: balance}
end)
@ -92,16 +116,22 @@ defmodule Explorer.ChainSpec.Parity.Importer do
defp parse_hex_numbers(rewards) do
Enum.map(rewards, fn {hex_block_number, hex_reward} ->
block_number = parse_hex_number(hex_block_number)
{:ok, reward} = hex_reward |> parse_hex_number() |> Wei.cast()
block_number = parse_number(hex_block_number)
{:ok, reward} = hex_reward |> parse_number() |> Wei.cast()
{block_number, reward}
end)
end
defp parse_hex_number("0x" <> hex_number) do
defp parse_number("0x" <> hex_number) do
{number, ""} = Integer.parse(hex_number, 16)
number
end
defp parse_number(string_number) do
{number, ""} = Integer.parse(string_number, 10)
number
end
end

@ -0,0 +1,89 @@
defmodule Explorer.ChainSpec.POA.Importer do
@moduledoc """
Imports emission reward range for POA chain.
"""
require Logger
alias Explorer.Chain.Wei
alias Explorer.Repo
alias Explorer.SmartContract.Reader
alias Explorer.Chain.Block.{EmissionReward, Range}
alias Explorer.ChainSpec.GenesisData
@block_reward_amount_abi %{
"type" => "function",
"stateMutability" => "view",
"payable" => false,
"outputs" => [%{"type" => "uint256", "name" => ""}],
"name" => "blockRewardAmount",
"inputs" => [],
"constant" => true
}
@block_reward_amount_params %{"blockRewardAmount" => []}
@emission_funds_amount_abi %{
"type" => "function",
"stateMutability" => "view",
"payable" => false,
"outputs" => [%{"type" => "uint256", "name" => ""}],
"name" => "emissionFundsAmount",
"inputs" => [],
"constant" => true
}
@emission_funds_amount_params %{"emissionFundsAmount" => []}
@emission_funds_block_start 5_098_087
def import_emission_rewards do
if is_nil(rewards_contract_address()) do
Logger.warn(fn -> "No rewards contract address is defined" end)
else
block_reward = block_reward_amount()
emission_funds = emission_funds_amount()
rewards = [
%{
block_range: %Range{from: 0, to: @emission_funds_block_start},
reward: %Wei{value: block_reward}
},
%{
block_range: %Range{from: @emission_funds_block_start + 1, to: :infinity},
reward: %Wei{value: Decimal.add(block_reward, emission_funds)}
}
]
{_, nil} = Repo.delete_all(EmissionReward)
{_, nil} = Repo.insert_all(EmissionReward, rewards)
end
end
def block_reward_amount do
call_contract(rewards_contract_address(), @block_reward_amount_abi, @block_reward_amount_params)
end
def emission_funds_amount do
call_contract(rewards_contract_address(), @emission_funds_amount_abi, @emission_funds_amount_params)
end
defp rewards_contract_address do
Application.get_env(:explorer, GenesisData)[:rewards_contract_address]
end
defp call_contract(address, abi, params) do
abi = [abi]
method_name =
params
|> Enum.map(fn {key, _value} -> key end)
|> List.first()
Reader.query_contract(address, abi, params)
value =
case Reader.query_contract(address, abi, params) do
%{^method_name => {:ok, [result]}} -> result
_ -> 0
end
Decimal.new(value)
end
end

@ -11,7 +11,7 @@ defmodule Explorer.Chain.Cache.BlockNumberTest do
end)
end
describe "get_max/1" do
describe "get_max/0" do
test "returns max number" do
insert(:block, number: 5)
@ -19,7 +19,7 @@ defmodule Explorer.Chain.Cache.BlockNumberTest do
end
end
describe "get_min/1" do
describe "get_min/0" do
test "returns min number" do
insert(:block, number: 2)
@ -27,7 +27,7 @@ defmodule Explorer.Chain.Cache.BlockNumberTest do
end
end
describe "get_all/1" do
describe "get_all/0" do
test "returns min and max number" do
insert(:block, number: 6)

@ -65,3 +65,5 @@ $ export NETWORK=POA
| `WEBAPP_URL` | | Link to web application instance, e.g. `http://host/path` | (empty) | v2.0.3+ | | |
| `API_URL` | | Link to API instance, e.g. `http://host/path` | (empty) | v2.0.3+ | | |
| `CHAIN_SPEC_PATH` | | Chain specification path (absolute file system path or url) to import block emission reward ranges and genesis account balances from | (empty) | master | | |
| `EMISSION_FORMAT` | | Should be set to `POA` if you have block emission indentical to POA Network. This env var is used only if `CHAIN_SPEC_PATH` is set | `STANDARD` | master | | |
| `REWARDS_CONTRACT_ADDRESS` | | Emission rewards contract address. This env var is used only if `EMISSION_FORMAT` is set to `POA` | `0xeca443e8e1ab29971a45a9c57a6a9875701698a5` | master | | |

Loading…
Cancel
Save