Merge branch 'master' into sa-log-rotation

pull/958/head
Andrew Cravenho 6 years ago committed by GitHub
commit f525aa44be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      apps/block_scout_web/assets/js/lib/market_history_chart.js
  2. 14
      apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
  3. 2
      apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
  4. 1
      apps/block_scout_web/lib/block_scout_web/templates/internal_transaction/_tile.html.eex
  5. 21
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  6. 55
      apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex
  7. 55
      apps/block_scout_web/lib/block_scout_web/templates/transaction/index.html.eex
  8. 31
      apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
  9. 83
      apps/block_scout_web/priv/gettext/default.pot
  10. 83
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  11. 8
      apps/block_scout_web/test/block_scout_web/features/pages/transaction_list_page.ex
  12. 9
      apps/block_scout_web/test/block_scout_web/features/viewing_transactions_test.exs
  13. 40
      apps/block_scout_web/test/block_scout_web/views/internal_transaction_view_test.exs
  14. 8
      apps/explorer/config/config.exs
  15. 3
      apps/explorer/config/test.exs
  16. 5
      apps/explorer/lib/explorer/chain.ex
  17. 18
      apps/explorer/lib/explorer/chain/supply.ex
  18. 6
      apps/explorer/lib/explorer/chain/supply/proof_of_authority.ex
  19. 78
      apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex
  20. 16
      apps/explorer/lib/explorer/chain/wei.ex
  21. 50
      apps/explorer/lib/explorer/exchange_rates/source/transaction_and_log.ex
  22. 122
      apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs
  23. 46
      apps/explorer/test/explorer/chain/wei_test.exs
  24. 11
      apps/explorer/test/explorer/exchange_rates/source/transaction_and_log_test.exs
  25. 25
      apps/explorer/test/support/fakes/one_coin_source.ex

@ -75,8 +75,12 @@ function getPriceData (marketHistoryData) {
}
function getMarketCapData (marketHistoryData, availableSupply) {
if (availableSupply !== null && typeof availableSupply === 'object') {
return marketHistoryData.map(({ date, closingPrice }) => ({x: date, y: closingPrice * availableSupply[date]}))
} else {
return marketHistoryData.map(({ date, closingPrice }) => ({x: date, y: closingPrice * availableSupply}))
}
}
class MarketHistoryChart {
constructor (el, availableSupply, marketHistoryData) {
@ -100,18 +104,25 @@ class MarketHistoryChart {
borderColor: sassVariables.secondary,
lineTension: 0
}
this.availableSupply = availableSupply
config.data.datasets = [this.price, this.marketCap]
this.chart = new Chart(el, config)
}
update (availableSupply, marketHistoryData) {
this.price.data = getPriceData(marketHistoryData)
if (this.availableSupply !== null && typeof this.availableSupply === 'object') {
const today = new Date().toJSON().slice(0, 10)
this.availableSupply[today] = availableSupply
this.marketCap.data = getMarketCapData(marketHistoryData, this.availableSupply)
} else {
this.marketCap.data = getMarketCapData(marketHistoryData, availableSupply)
}
this.chart.update()
}
}
export function createMarketHistoryChart (ctx) {
const availableSupply = ctx.dataset.available_supply
const availableSupply = JSON.parse(ctx.dataset.available_supply)
const marketHistoryData = humps.camelizeKeys(JSON.parse(ctx.dataset.market_history_data))
return new MarketHistoryChart(ctx, availableSupply, marketHistoryData)

@ -40,6 +40,7 @@ defmodule BlockScoutWeb.ChainController do
average_block_time: Chain.average_block_time(),
blocks: blocks,
exchange_rate: exchange_rate,
available_supply: available_supply(Chain.supply_for_days(30), exchange_rate),
market_history_data: market_history_data,
transaction_estimated_count: transaction_estimated_count,
transactions: transactions
@ -78,4 +79,17 @@ defmodule BlockScoutWeb.ChainController do
)
)
end
defp available_supply(:ok, exchange_rate) do
to_string(exchange_rate.available_supply || 0)
end
defp available_supply({:ok, supply_for_days}, _exchange_rate) do
supply_for_days
|> Jason.encode()
|> case do
{:ok, data} -> data
_ -> []
end
end
end

@ -3,7 +3,7 @@
<div class="container">
<div class="dashboard-banner">
<div class="dashboard-banner-chart">
<canvas data-chart="marketHistoryChart" data-available_supply='<%= @exchange_rate.available_supply %>' data-market_history_data='<%=raw encode_market_history_data(@market_history_data) %>' width="350" height="152"></canvas>
<canvas data-chart="marketHistoryChart" data-available_supply='<%=raw @available_supply %>' data-market_history_data='<%=raw encode_market_history_data(@market_history_data) %>' width="350" height="152"></canvas>
</div>
<div class="dashboard-banner-chart-legend">
<div class="dashboard-banner-chart-legend-item">

@ -2,6 +2,7 @@
<div class="row">
<div class="col-md-2 d-flex flex-row flex-md-column align-items-left justify-content-start justify-content-lg-center mb-1 mb-md-0 pl-md-4">
<%= gettext("Internal Transaction") %>
<span>(<%= type(@internal_transaction) %>)</span>
</div>
<div class="col-md-7 col-lg-8 d-flex flex-column text-nowrap pr-2 pr-sm-2 pr-md-0">
<%= render BlockScoutWeb.TransactionView, "_link.html", transaction_hash: @internal_transaction.transaction_hash %>

@ -15,7 +15,7 @@
</span>
<%= gettext("Blocks") %>
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-menu" aria-labelledby="navbarBlocksDropdown">
<%= link to: block_path(@conn, :index), class: "dropdown-item" do %>
<%= gettext("Blocks") %>
<% end %>
@ -27,13 +27,26 @@
<% end %>
</div>
</li>
<li class="nav-item">
<%= link to: transaction_path(@conn, :index), class: "nav-link topnav-nav-link" do %>
<li class="nav-item dropdown">
<a href="#" role="button" id="navbarTransactionsDropdown" class="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="nav-link-icon">
<%= render BlockScoutWeb.IconsView, "_transaction_icon.html" %>
</span>
<%= gettext("Transactions") %>
<% end %>
</a>
<div class="dropdown-menu" aria-labeledby="navbarTransactionsDropdown">
<%= link(
gettext("Validated"),
class: "dropdown-item",
to: transaction_path(@conn, :index)
) %>
<%= link(
gettext("Pending"),
class: "dropdown-item",
"data-test": "pending_transactions_link",
to: pending_transaction_path(@conn, :index)
) %>
</div>
</li>
<li class="nav-item">
<%= link to: address_path(@conn, :index), class: "nav-link topnav-nav-link" do %>

@ -1,48 +1,14 @@
<section class="container" data-page="transaction-pending-list">
<div class="card">
<div class="card-header">
<!-- DESKTOP TAB NAV -->
<ul class="nav nav-tabs card-header-tabs d-none d-md-inline-flex">
<li class="nav-item">
<%= link(
gettext("Validated"),
class: "nav-link",
to: transaction_path(@conn, :index)
) %>
</li>
<li class="nav-item">
<%= link(
gettext("Pending"),
class: "nav-link active",
"data-test": "pending_transactions_link",
to: pending_transaction_path(@conn, :index)
) %>
</li>
</ul>
<div class="card-body">
<!-- MOBILE DROPDOWN NAV -->
<ul class="nav nav-tabs card-header-tabs d-lg-none">
<li class="nav-item dropdown flex-fill text-center">
<a class="nav-link active dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"><%= gettext("Pending") %></a>
<div class="dropdown-menu">
<%= link(
gettext("Validated"),
class: "dropdown-item",
to: transaction_path(@conn, :index)
) %>
<%= link(
gettext("Pending"),
class: "dropdown-item active",
"data-test": "pending_transactions_link",
to: pending_transaction_path(@conn, :index)
) %>
</div>
</li>
</ul>
</div>
<h1><%= gettext "Pending Transactions" %></h1>
<p>
<%= gettext("Showing") %>
<span data-selector="transaction-pending-count"><%= Cldr.Number.to_string!(@pending_transaction_count, format: "#,###") %></span>
<%= gettext("Pending Transactions") %>
</p>
<div class="card-body">
<div data-selector="channel-batching-message" style="display:none;">
<div data-selector="reload-button" class="alert alert-info">
<a href="#" class="alert-link"><span data-selector="channel-batching-count"></span> <%= gettext "More transactions have come in" %></a>
@ -53,12 +19,7 @@
<a href="#" class="alert-link"><%= gettext "Connection Lost, click to load newer transactions" %></a>
</div>
</div>
<h2 class="card-title mb-0"><%= gettext "Transactions" %></h2>
<p>
<%= gettext("Showing") %>
<span data-selector="transaction-pending-count"><%= Cldr.Number.to_string!(@pending_transaction_count, format: "#,###") %></span>
<%= gettext("Pending Transactions") %>
</p>
<span data-selector="transactions-pending-list">
<%= for transaction <- @transactions do %>
<%= render BlockScoutWeb.TransactionView, "_tile.html", transaction: transaction %>

@ -1,48 +1,14 @@
<section class="container" data-page="transaction-list">
<div class="card">
<div class="card-header">
<!-- DESKTOP TAB NAV -->
<ul class="nav nav-tabs card-header-tabs d-none d-lg-inline-flex">
<li class="nav-item">
<%= link(
gettext("Validated"),
class: "nav-link active",
to: transaction_path(@conn, :index)
) %>
</li>
<li class="nav-item">
<%= link(
gettext("Pending"),
class: "nav-link",
"data-test": "pending_transactions_link",
to: pending_transaction_path(@conn, :index)
) %>
</li>
</ul>
<div class="card-body">
<!-- MOBILE DROPDOWN NAV -->
<ul class="nav nav-tabs card-header-tabs d-lg-none">
<li class="nav-item dropdown flex-fill text-center">
<a class="nav-link active dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"><%= gettext("Validated") %></a>
<div class="dropdown-menu">
<%= link(
gettext("Validated"),
class: "dropdown-item active",
to: transaction_path(@conn, :index)
) %>
<%= link(
gettext("Pending"),
class: "dropdown-item",
"data-test": "pending_transactions_link",
to: pending_transaction_path(@conn, :index)
) %>
</div>
</li>
</ul>
</div>
<h1><%= gettext "Validated Transactions" %></h1>
<p>
<%= gettext("Showing") %>
<span data-selector="transaction-count"><%= Cldr.Number.to_string!(@transaction_estimated_count, format: "#,###") %></span>
<%= gettext("Validated Transactions") %>
</p>
<div class="card-body">
<div data-selector="channel-batching-message" class="d-none">
<div data-selector="reload-button" class="alert alert-info">
<a href="#" class="alert-link"><span data-selector="channel-batching-count"></span> <%= gettext "More transactions have come in" %></a>
@ -53,12 +19,7 @@
<a href="#" class="alert-link"><%= gettext "Connection Lost, click to load newer transactions" %></a>
</div>
</div>
<h1><%= gettext "Transactions" %></h1>
<p>
<%= gettext("Showing") %>
<span data-selector="transaction-count"><%= Cldr.Number.to_string!(@transaction_estimated_count, format: "#,###") %></span>
<%= gettext("Validated Transactions") %>
</p>
<span data-selector="transactions-list">
<%= for transaction <- @transactions do %>
<%= render BlockScoutWeb.TransactionView, "_tile.html", transaction: transaction %>

@ -1,3 +1,34 @@
defmodule BlockScoutWeb.InternalTransactionView do
use BlockScoutWeb, :view
alias Explorer.Chain.InternalTransaction
import BlockScoutWeb.Gettext
@doc """
Returns the formatted string for the type of the internal transaction.
When the type is `call`, we return the formatted string for the call type.
Examples:
iex> BlockScoutWeb.InternalTransactionView.type(%Explorer.Chain.InternalTransaction{type: :reward})
"Reward"
iex> BlockScoutWeb.InternalTransactionView.type(%Explorer.Chain.InternalTransaction{type: :call, call_type: :delegatecall})
"Delegate Call"
"""
def type(%InternalTransaction{type: :call, call_type: call_type}) do
formatted_type(call_type)
end
def type(%InternalTransaction{type: type}) do
formatted_type(type)
end
defp formatted_type(:call), do: gettext("Call")
defp formatted_type(:delegatecall), do: gettext("Delegate Call")
defp formatted_type(:create), do: gettext("Create")
defp formatted_type(:suicide), do: gettext("Suicide")
defp formatted_type(:reward), do: gettext("Reward")
end

@ -84,7 +84,7 @@ msgid "A string with the name of the module to be invoked."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:51
#: lib/block_scout_web/templates/layout/_topnav.html.eex:64
msgid "API"
msgstr ""
@ -99,7 +99,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:43
#: lib/block_scout_web/templates/layout/_topnav.html.eex:56
msgid "Accounts"
msgstr ""
@ -144,7 +144,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_link.html.eex:2
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:22
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:44
msgid "Block #%{number}"
msgstr ""
@ -258,8 +258,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:14
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:53
#: lib/block_scout_web/templates/transaction/index.html.eex:53
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:19
#: lib/block_scout_web/templates/transaction/index.html.eex:19
msgid "Connection Lost, click to load newer transactions"
msgstr ""
@ -404,7 +404,7 @@ msgid "Error: (Awaiting internal transactions for reason)"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:15
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:16
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:19
#: lib/block_scout_web/templates/transaction/_tile.html.eex:26
#: lib/block_scout_web/templates/transaction/overview.html.eex:98
@ -484,7 +484,7 @@ msgid "Hide"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:31
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:32
#: lib/block_scout_web/templates/transaction/_tile.html.eex:46
msgid "IN"
msgstr ""
@ -579,8 +579,8 @@ msgid "More internal transactions have come in"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:48
#: lib/block_scout_web/templates/transaction/index.html.eex:48
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:14
#: lib/block_scout_web/templates/transaction/index.html.eex:14
msgid "More transactions have come in"
msgstr ""
@ -631,7 +631,7 @@ msgid "Nonce"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:29
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:30
#: lib/block_scout_web/templates/transaction/_tile.html.eex:42
msgid "OUT"
msgstr ""
@ -642,9 +642,9 @@ msgstr ""
#: lib/block_scout_web/templates/address_validation/index.html.eex:117
#: lib/block_scout_web/templates/block/index.html.eex:20
#: lib/block_scout_web/templates/block_transaction/index.html.eex:50
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:70
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:31
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:34
#: lib/block_scout_web/templates/transaction/index.html.eex:70
#: lib/block_scout_web/templates/transaction/index.html.eex:31
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:24
msgid "Older"
msgstr ""
@ -660,12 +660,12 @@ msgid "Owner Address"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:82
#: lib/block_scout_web/templates/layout/_topnav.html.eex:95
msgid "POA Core"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:81
#: lib/block_scout_web/templates/layout/_topnav.html.eex:94
msgid "POA Sokol"
msgstr ""
@ -685,11 +685,7 @@ msgid "Parent Hash"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:16
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:27
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:35
#: lib/block_scout_web/templates/transaction/index.html.eex:16
#: lib/block_scout_web/templates/transaction/index.html.eex:35
#: lib/block_scout_web/templates/layout/_topnav.html.eex:44
#: lib/block_scout_web/templates/transaction/overview.html.eex:54
#: lib/block_scout_web/views/transaction_view.ex:57
#: lib/block_scout_web/views/transaction_view.ex:83
@ -698,7 +694,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:60
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:60
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:5
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:9
msgid "Pending Transactions"
msgstr ""
@ -760,13 +757,13 @@ msgid "Responses"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:58
#: lib/block_scout_web/templates/layout/_topnav.html.eex:65
#: lib/block_scout_web/templates/layout/_topnav.html.eex:71
#: lib/block_scout_web/templates/layout/_topnav.html.eex:78
msgid "Search"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:58
#: lib/block_scout_web/templates/layout/_topnav.html.eex:71
msgid "Search by address, transaction hash, or block number"
msgstr ""
@ -792,8 +789,8 @@ msgid "Show QR Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:58
#: lib/block_scout_web/templates/transaction/index.html.eex:58
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:7
#: lib/block_scout_web/templates/transaction/index.html.eex:7
msgid "Showing"
msgstr ""
@ -1004,8 +1001,6 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35
#: lib/block_scout_web/templates/chain/show.html.eex:71
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:56
#: lib/block_scout_web/templates/transaction/index.html.eex:56
#: lib/block_scout_web/views/address_view.ex:208
msgid "Transactions"
msgstr ""
@ -1048,16 +1043,13 @@ msgid "Used"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:9
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:30
#: lib/block_scout_web/templates/transaction/index.html.eex:9
#: lib/block_scout_web/templates/transaction/index.html.eex:27
#: lib/block_scout_web/templates/transaction/index.html.eex:30
#: lib/block_scout_web/templates/layout/_topnav.html.eex:39
msgid "Validated"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/index.html.eex:60
#: lib/block_scout_web/templates/transaction/index.html.eex:5
#: lib/block_scout_web/templates/transaction/index.html.eex:9
msgid "Validated Transactions"
msgstr ""
@ -1194,3 +1186,28 @@ msgstr ""
#: lib/block_scout_web/views/address_contract_view.ex:15
msgid "true"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:29
msgid "Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:31
msgid "Create"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:30
msgid "Delegate Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:33
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:32
msgid "Suicide"
msgstr ""

@ -84,7 +84,7 @@ msgid "A string with the name of the module to be invoked."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:51
#: lib/block_scout_web/templates/layout/_topnav.html.eex:64
msgid "API"
msgstr ""
@ -99,7 +99,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:43
#: lib/block_scout_web/templates/layout/_topnav.html.eex:56
msgid "Accounts"
msgstr ""
@ -144,7 +144,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_link.html.eex:2
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:21
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:22
#: lib/block_scout_web/templates/tokens/transfer/_token_transfer.html.eex:44
msgid "Block #%{number}"
msgstr ""
@ -258,8 +258,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:14
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:53
#: lib/block_scout_web/templates/transaction/index.html.eex:53
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:19
#: lib/block_scout_web/templates/transaction/index.html.eex:19
msgid "Connection Lost, click to load newer transactions"
msgstr ""
@ -404,7 +404,7 @@ msgid "Error: (Awaiting internal transactions for reason)"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:15
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:16
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:19
#: lib/block_scout_web/templates/transaction/_tile.html.eex:26
#: lib/block_scout_web/templates/transaction/overview.html.eex:98
@ -484,7 +484,7 @@ msgid "Hide"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:31
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:32
#: lib/block_scout_web/templates/transaction/_tile.html.eex:46
msgid "IN"
msgstr ""
@ -579,8 +579,8 @@ msgid "More internal transactions have come in"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:48
#: lib/block_scout_web/templates/transaction/index.html.eex:48
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:14
#: lib/block_scout_web/templates/transaction/index.html.eex:14
msgid "More transactions have come in"
msgstr ""
@ -631,7 +631,7 @@ msgid "Nonce"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:29
#: lib/block_scout_web/templates/internal_transaction/_tile.html.eex:30
#: lib/block_scout_web/templates/transaction/_tile.html.eex:42
msgid "OUT"
msgstr ""
@ -642,9 +642,9 @@ msgstr ""
#: lib/block_scout_web/templates/address_validation/index.html.eex:117
#: lib/block_scout_web/templates/block/index.html.eex:20
#: lib/block_scout_web/templates/block_transaction/index.html.eex:50
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:70
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:31
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:34
#: lib/block_scout_web/templates/transaction/index.html.eex:70
#: lib/block_scout_web/templates/transaction/index.html.eex:31
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:24
msgid "Older"
msgstr ""
@ -660,12 +660,12 @@ msgid "Owner Address"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:82
#: lib/block_scout_web/templates/layout/_topnav.html.eex:95
msgid "POA Core"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:81
#: lib/block_scout_web/templates/layout/_topnav.html.eex:94
msgid "POA Sokol"
msgstr ""
@ -685,11 +685,7 @@ msgid "Parent Hash"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:16
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:27
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:35
#: lib/block_scout_web/templates/transaction/index.html.eex:16
#: lib/block_scout_web/templates/transaction/index.html.eex:35
#: lib/block_scout_web/templates/layout/_topnav.html.eex:44
#: lib/block_scout_web/templates/transaction/overview.html.eex:54
#: lib/block_scout_web/views/transaction_view.ex:57
#: lib/block_scout_web/views/transaction_view.ex:83
@ -698,7 +694,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:60
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:60
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:5
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:9
msgid "Pending Transactions"
msgstr ""
@ -760,13 +757,13 @@ msgid "Responses"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:58
#: lib/block_scout_web/templates/layout/_topnav.html.eex:65
#: lib/block_scout_web/templates/layout/_topnav.html.eex:71
#: lib/block_scout_web/templates/layout/_topnav.html.eex:78
msgid "Search"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:58
#: lib/block_scout_web/templates/layout/_topnav.html.eex:71
msgid "Search by address, transaction hash, or block number"
msgstr ""
@ -792,8 +789,8 @@ msgid "Show QR Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:58
#: lib/block_scout_web/templates/transaction/index.html.eex:58
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:7
#: lib/block_scout_web/templates/transaction/index.html.eex:7
msgid "Showing"
msgstr ""
@ -1004,8 +1001,6 @@ msgstr ""
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35
#: lib/block_scout_web/templates/chain/show.html.eex:71
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:56
#: lib/block_scout_web/templates/transaction/index.html.eex:56
#: lib/block_scout_web/views/address_view.ex:208
msgid "Transactions"
msgstr ""
@ -1048,16 +1043,13 @@ msgid "Used"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:9
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:30
#: lib/block_scout_web/templates/transaction/index.html.eex:9
#: lib/block_scout_web/templates/transaction/index.html.eex:27
#: lib/block_scout_web/templates/transaction/index.html.eex:30
#: lib/block_scout_web/templates/layout/_topnav.html.eex:39
msgid "Validated"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/index.html.eex:60
#: lib/block_scout_web/templates/transaction/index.html.eex:5
#: lib/block_scout_web/templates/transaction/index.html.eex:9
msgid "Validated Transactions"
msgstr ""
@ -1194,3 +1186,28 @@ msgstr ""
#: lib/block_scout_web/views/address_contract_view.ex:15
msgid "true"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:29
msgid "Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:31
msgid "Create"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:30
msgid "Delegate Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:33
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:32
msgid "Suicide"
msgstr ""

@ -11,10 +11,6 @@ defmodule BlockScoutWeb.TransactionListPage do
click(session, css("[data-transaction-hash='#{transaction_hash}'] [data-test='transaction_hash_link']"))
end
def click_pending(session) do
click(session, css("[data-test='pending_transactions_link']"))
end
def contract_creation(%Transaction{hash: hash}) do
css("[data-transaction-hash='#{hash}'] [data-test='transaction_type']", text: "Contract Creation")
end
@ -30,4 +26,8 @@ defmodule BlockScoutWeb.TransactionListPage do
def visit_page(session) do
visit(session, "/txs")
end
def visit_pending_transactions_page(session) do
visit(session, "/pending_transactions")
end
end

@ -74,10 +74,13 @@ defmodule BlockScoutWeb.ViewingTransactionsTest do
|> refute_has(TransactionListPage.transaction(pending))
end
test "viewing the pending tab", %{pending: pending, pending_contract: pending_contract, session: session} do
test "viewing the pending tranasctions list", %{
pending: pending,
pending_contract: pending_contract,
session: session
} do
session
|> TransactionListPage.visit_page()
|> TransactionListPage.click_pending()
|> TransactionListPage.visit_pending_transactions_page()
|> assert_has(TransactionListPage.transaction(pending))
|> assert_has(TransactionListPage.transaction(pending_contract))
|> assert_has(TransactionListPage.transaction_status(pending_contract))

@ -0,0 +1,40 @@
defmodule BlockScoutWeb.InternalTransactionViewTest do
use BlockScoutWeb.ConnCase, async: true
alias BlockScoutWeb.InternalTransactionView
alias Explorer.Chain.InternalTransaction
doctest BlockScoutWeb.InternalTransactionView
describe "type/1" do
test "returns the correct string when the type is :call and call type is :call" do
internal_transaction = %InternalTransaction{type: :call, call_type: :call}
assert InternalTransactionView.type(internal_transaction) == "Call"
end
test "returns the correct string when the type is :call and call type is :delegate_call" do
internal_transaction = %InternalTransaction{type: :call, call_type: :delegatecall}
assert InternalTransactionView.type(internal_transaction) == "Delegate Call"
end
test "returns the correct string when the type is :create" do
internal_transaction = %InternalTransaction{type: :create}
assert InternalTransactionView.type(internal_transaction) == "Create"
end
test "returns the correct string when the type is :suicide" do
internal_transaction = %InternalTransaction{type: :suicide}
assert InternalTransactionView.type(internal_transaction) == "Suicide"
end
test "returns the correct string when the type is :reward" do
internal_transaction = %InternalTransaction{type: :reward}
assert InternalTransactionView.type(internal_transaction) == "Reward"
end
end
end

@ -28,6 +28,14 @@ config :explorer, Explorer.Counters.TokenTransferCounter, enabled: true
config :explorer, Explorer.Counters.TokenHoldersCounter, enabled: true, enable_consolidation: true
if System.get_env("SUPPLY_MODULE") == "TransactionAndLog" do
config :explorer, supply: Explorer.Chain.Supply.TransactionAndLog
end
if System.get_env("SOURCE_MODULE") == "TransactionAndLog" do
config :explorer, Explorer.ExchangeRates, source: Explorer.ExchangeRates.Source.TransactionAndLog
end
config :explorer,
solc_bin_api_url: "https://solc-bin.ethereum.org"

@ -27,6 +27,9 @@ if File.exists?(file = "test.secret.exs") do
import_config file
end
config :explorer, Explorer.ExchangeRates.Source.TransactionAndLog,
secondary_source: Explorer.ExchangeRates.Source.OneCoinSource
variant =
if is_nil(System.get_env("ETHEREUM_JSONRPC_VARIANT")) do
"parity"

@ -1929,6 +1929,11 @@ defmodule Explorer.Chain do
Application.get_env(:explorer, :supply, Explorer.Chain.Supply.ProofOfAuthority)
end
@doc """
Calls supply_for_days from the configured supply_module
"""
def supply_for_days(days_count), do: supply_module().supply_for_days(days_count)
@doc """
Streams a lists token contract addresses that haven't been cataloged.
"""

@ -9,10 +9,24 @@ defmodule Explorer.Chain.Supply do
@doc """
The current total number of coins minted minus verifiably burned coins.
"""
@callback total :: non_neg_integer()
@callback total :: non_neg_integer() | %Decimal{sign: 1}
@doc """
The current number coins in the market for trading.
"""
@callback circulating :: non_neg_integer()
@callback circulating :: non_neg_integer() | %Decimal{sign: 1}
@doc """
A map of total supplies per day, optional.
"""
@callback supply_for_days(days_count :: integer) :: {:ok, term} | {:error, term} | :ok
defmacro __using__(_opts) do
quote do
@behaviour Explorer.Chain.Supply
def supply_for_days(_days_count), do: :ok
defoverridable supply_for_days: 1
end
end
end

@ -12,11 +12,9 @@ defmodule Explorer.Chain.Supply.ProofOfAuthority do
See https://github.com/poanetwork/wiki/wiki/POA-Token-Supply for more
information.
"""
use Explorer.Chain.Supply
alias Explorer.Chain
alias Explorer.Chain.Supply
@behaviour Supply
@initial_supply 252_460_800
@reserved_for_vesting 50_492_160
@ -31,12 +29,10 @@ defmodule Explorer.Chain.Supply.ProofOfAuthority do
~D[2019-12-15] => 0.125
}
@impl Supply
def circulating do
total() - reserved_supply(Date.utc_today())
end
@impl Supply
def total do
initial_supply = initial_supply()
block_height = block_height()

@ -0,0 +1,78 @@
defmodule Explorer.Chain.Supply.TransactionAndLog do
@moduledoc """
Defines the supply API for calculating the supply for smaller chains with
specific mint and burn events
"""
use Explorer.Chain.Supply
alias Explorer.Chain.{InternalTransaction, Log, Wei}
alias Explorer.{Repo, Chain}
{:ok, base_wei} = Wei.cast(0)
@base_wei base_wei
{:ok, burn_address} = Chain.string_to_address_hash("0x0000000000000000000000000000000000000000")
@burn_address burn_address
@bridge_edge "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a"
import Ecto.Query, only: [from: 2]
def circulating, do: total(Timex.now())
def total, do: total(Timex.now())
@doc false
@spec total(DateTime.t()) :: %Decimal{sign: 1}
def total(on_date) do
on_date
|> minted_value
|> Wei.sub(burned_value(on_date))
|> Wei.to(:ether)
end
def supply_for_days(days_count) when is_integer(days_count) and days_count > 0 do
past_days = -(days_count - 1)
result =
for i <- past_days..0, into: %{} do
datetime = Timex.shift(Timex.now(), days: i)
{DateTime.to_date(datetime), total(datetime)}
end
{:ok, result}
end
defp minted_value(on_date) do
query =
from(
l in Log,
join: t in assoc(l, :transaction),
join: b in assoc(t, :block),
where: b.timestamp <= ^on_date and l.first_topic == @bridge_edge,
select: fragment("concat('0x', encode(?, 'hex'))", l.data)
)
query
|> Repo.all()
|> Enum.reduce(@base_wei, fn data, acc ->
{:ok, wei_value} = Wei.cast(data)
Wei.sum(wei_value, acc)
end)
end
defp burned_value(on_date) do
query =
from(
it in InternalTransaction,
join: t in assoc(it, :transaction),
join: b in assoc(t, :block),
where: b.timestamp <= ^on_date and it.to_address_hash == ^@burn_address,
select: it.value
)
query
|> Repo.all()
|> Enum.reduce(@base_wei, fn data, acc -> Wei.sum(data, acc) end)
end
end

@ -130,6 +130,22 @@ defmodule Explorer.Chain.Wei do
|> from(:wei)
end
@doc """
Subtracts two Wei values.
## Example
iex> first = %Explorer.Chain.Wei{value: Decimal.new(1_123)}
iex> second = %Explorer.Chain.Wei{value: Decimal.new(1_000)}
iex> Explorer.Chain.Wei.sub(first, second)
%Explorer.Chain.Wei{value: Decimal.new(123)}
"""
def sub(%Wei{value: wei_1}, %Wei{value: wei_2}) do
wei_1
|> Decimal.sub(wei_2)
|> from(:wei)
end
@doc """
Converts `Decimal` representations of various wei denominations (wei, Gwei, ether) to
a wei base unit.

@ -0,0 +1,50 @@
defmodule Explorer.ExchangeRates.Source.TransactionAndLog do
@moduledoc """
Adapter for calculating the market cap and total supply from logs and transactions
while still getting other info like price in dollars and bitcoin from a secondary source
"""
alias Explorer.ExchangeRates.{Source, Token}
alias Explorer.Chain
@behaviour Source
@impl Source
def fetch_exchange_rates do
token_data =
secondary_source().fetch_exchange_rates()
|> elem(1)
|> Enum.find(fn token -> token.symbol == Explorer.coin() end)
|> build_struct
{:ok, [token_data]}
end
defp build_struct(original_token) do
%Token{
available_supply: to_decimal(Chain.circulating_supply()),
btc_value: original_token.btc_value,
id: original_token.id,
last_updated: original_token.last_updated,
market_cap_usd: Decimal.mult(to_decimal(Chain.circulating_supply()), original_token.usd_value),
name: original_token.name,
symbol: original_token.symbol,
usd_value: original_token.usd_value,
volume_24h_usd: original_token.volume_24h_usd
}
end
defp to_decimal(value) do
Decimal.new(value)
end
@spec secondary_source() :: module()
defp secondary_source do
config(:secondary_source) || Explorer.ExchangeRates.Source.CoinMarketCap
end
@spec config(atom()) :: term
defp config(key) do
Application.get_env(:explorer, __MODULE__, [])[key]
end
end

@ -0,0 +1,122 @@
defmodule Explorer.Chain.Supply.TransactionAndLogTest do
use Explorer.DataCase
alias Explorer.Chain
alias Explorer.Chain.Supply.TransactionAndLog
setup do
{:ok, burn_address_hash} = Chain.string_to_address_hash("0x0000000000000000000000000000000000000000")
burn_address =
case Chain.hash_to_address(burn_address_hash) do
{:ok, burn_address} -> burn_address
{:error, :not_found} -> insert(:address, hash: "0x0000000000000000000000000000000000000000")
end
{:ok, %{burn_address: burn_address}}
end
describe "total/1" do
test "today with no mints or burns brings zero" do
assert TransactionAndLog.total(Timex.now()) == Decimal.new(0)
end
test "today with mints and burns calculates a value", %{burn_address: burn_address} do
old_block = insert(:block, timestamp: Timex.shift(Timex.now(), days: -1), number: 1000)
insert(:log,
transaction:
insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 2),
first_topic: "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a",
data: "0x0000000000000000000000000000000000000000000000008ac7230489e80000"
)
insert(:internal_transaction,
index: 527,
transaction:
insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 3),
to_address: burn_address,
value: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
)
assert TransactionAndLog.total(Timex.now()) == Decimal.new(9)
end
test "yesterday with mints and burns calculates a value ignoring whatever happened today", %{
burn_address: burn_address
} do
old_block = insert(:block, timestamp: Timex.shift(Timex.now(), days: -1), number: 1000)
insert(:log,
transaction:
insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 2),
first_topic: "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a",
data: "0x0000000000000000000000000000000000000000000000008ac7230489e80000"
)
new_block = insert(:block, timestamp: Timex.now(), number: 1001)
insert(:internal_transaction,
index: 527,
transaction:
insert(:transaction, block: new_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 3),
to_address: burn_address,
value: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
)
assert TransactionAndLog.total(Timex.shift(Timex.now(), days: -1)) == Decimal.new(10)
end
end
describe "total/0" do
test "calculates the same value as total/1 receiving today's date", %{burn_address: burn_address} do
old_block = insert(:block, timestamp: Timex.shift(Timex.now(), days: -1), number: 1000)
insert(:log,
transaction:
insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 2),
first_topic: "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a",
data: "0x0000000000000000000000000000000000000000000000008ac7230489e80000"
)
insert(:internal_transaction,
index: 527,
transaction:
insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 3),
to_address: burn_address,
value: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
)
assert TransactionAndLog.total() == TransactionAndLog.total(Timex.now())
end
end
describe "supply_for_days/1" do
test "bring the supply of today and yesterday when receiving 2", %{burn_address: burn_address} do
old_block = insert(:block, timestamp: Timex.shift(Timex.now(), days: -1), number: 1000)
insert(:log,
transaction:
insert(:transaction, block: old_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 2),
first_topic: "0x3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a",
data: "0x0000000000000000000000000000000000000000000000008ac7230489e80000"
)
new_block = insert(:block, timestamp: Timex.now(), number: 1001)
insert(:internal_transaction,
index: 527,
transaction:
insert(:transaction, block: new_block, block_number: 1000, cumulative_gas_used: 1, gas_used: 1, index: 3),
to_address: burn_address,
value: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
)
expected_result = %{
Timex.shift(Timex.today(), days: -1) => Decimal.new(10),
Timex.today() => Decimal.new(9)
}
assert TransactionAndLog.supply_for_days(2) == {:ok, expected_result}
end
end
end

@ -54,4 +54,50 @@ defmodule Explorer.Chain.WeiTest do
test "type/0" do
assert Wei.type() == :decimal
end
describe "sum/1" do
test "with two positive values return the sum of them" do
first = %Explorer.Chain.Wei{value: Decimal.new(123)}
second = %Explorer.Chain.Wei{value: Decimal.new(1_000)}
assert Explorer.Chain.Wei.sum(first, second) == %Explorer.Chain.Wei{value: Decimal.new(1_123)}
end
test "with a positive and a negative value return the positive minus the negative's absolute" do
first = %Explorer.Chain.Wei{value: Decimal.new(123)}
second = %Explorer.Chain.Wei{value: Decimal.new(-100)}
assert Explorer.Chain.Wei.sum(first, second) == %Explorer.Chain.Wei{value: Decimal.new(23)}
end
end
describe "sub/1" do
test "with a negative second parameter return the sum of the absolute values" do
first = %Explorer.Chain.Wei{value: Decimal.new(123)}
second = %Explorer.Chain.Wei{value: Decimal.new(-100)}
assert Explorer.Chain.Wei.sub(first, second) == %Explorer.Chain.Wei{value: Decimal.new(223)}
end
test "with a negative first parameter return the negative of the sum of the absolute values" do
first = %Explorer.Chain.Wei{value: Decimal.new(-123)}
second = %Explorer.Chain.Wei{value: Decimal.new(100)}
assert Explorer.Chain.Wei.sub(first, second) == %Explorer.Chain.Wei{value: Decimal.new(-223)}
end
test "with a larger first parameter return a positive number" do
first = %Explorer.Chain.Wei{value: Decimal.new(123)}
second = %Explorer.Chain.Wei{value: Decimal.new(100)}
assert Explorer.Chain.Wei.sub(first, second) == %Explorer.Chain.Wei{value: Decimal.new(23)}
end
test "with a larger second parameter return a negative number" do
first = %Explorer.Chain.Wei{value: Decimal.new(23)}
second = %Explorer.Chain.Wei{value: Decimal.new(100)}
assert Explorer.Chain.Wei.sub(first, second) == %Explorer.Chain.Wei{value: Decimal.new(-77)}
end
end
end

@ -0,0 +1,11 @@
defmodule Explorer.ExchangeRates.Source.TransactionAndLogTest do
use Explorer.DataCase
alias Explorer.ExchangeRates.Source.TransactionAndLog
alias Explorer.ExchangeRates.Token
describe "fetch_exchange_rates/1" do
test "bring a list with one %Token{}" do
assert {:ok, [%Token{}]} = TransactionAndLog.fetch_exchange_rates()
end
end
end

@ -0,0 +1,25 @@
defmodule Explorer.ExchangeRates.Source.OneCoinSource do
@moduledoc false
alias Explorer.ExchangeRates.Source
alias Explorer.ExchangeRates.Token
@behaviour Source
@impl Source
def fetch_exchange_rates do
pseudo_token = %Token{
available_supply: Decimal.new(10_000_000),
btc_value: Decimal.new(1),
id: "",
last_updated: Timex.now(),
name: "",
market_cap_usd: Decimal.new(10_000_000),
symbol: Explorer.coin(),
usd_value: Decimal.new(1),
volume_24h_usd: Decimal.new(1)
}
{:ok, [pseudo_token]}
end
end
Loading…
Cancel
Save