Merge branch 'master' into pp-address-controllers-improvements

pull/2305/head
Victor Baranov 5 years ago committed by GitHub
commit 770e9bdb7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      CHANGELOG.md
  2. 1
      README.md
  3. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
  4. 5
      apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex
  5. 25
      apps/block_scout_web/test/block_scout_web/views/api_docs_view_test.exs
  6. 4
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex
  7. 4
      apps/explorer/config/config.exs
  8. 78
      apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex
  9. 4
      apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex
  10. 122
      apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs
  11. 6
      apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs
  12. 4
      docs/env-variables.md

@ -2,15 +2,20 @@
### Features
[#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint
- [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint
### Fixes
- [#2310](https://github.com/poanetwork/blockscout/pull/2310) - parse url for api docs
- [#2299](https://github.com/poanetwork/blockscout/pull/2299) - fix interpolation in error message
- [#2303](https://github.com/poanetwork/blockscout/pull/2303) - fix transaction csv download link
- [#2304](https://github.com/poanetwork/blockscout/pull/2304) - footer grid fix for md resolution
- [#2291](https://github.com/poanetwork/blockscout/pull/2291) - dashboard fix for md resolution, transactions load fix, block info row fix, addresses page issue, check mark issue
### Chore
- [#2305](https://github.com/poanetwork/blockscout/pull/2305) - Improve Address controllers
- [#2302](https://github.com/poanetwork/blockscout/pull/2302) - fix names for xDai source
- [#2289](https://github.com/poanetwork/blockscout/pull/2289) - Optional websockets for dev environment
- [#2307](https://github.com/poanetwork/blockscout/pull/2307) - add GoJoy to README
## 2.0.1-beta

@ -41,6 +41,7 @@ Currently available full-featured block explorers (Etherscan, Etherchain, Blockc
| | | [Kotti Testnet](https://kottiexplorer.ethernode.io/) |
| | | [Loom](http://plasma-blockexplorer.dappchains.com/) |
| | | [Tenda](https://tenda.network) |
| | | [GoJoy Chain](https://gojoychain.com/) |
Current BlockScout versions for hosted projects are available [on the forum](https://forum.poa.network/t/deployed-instances-on-blockscout-com/1938).

@ -66,10 +66,10 @@
</div>
<div data-items></div>
<div class="transaction-bottom-panel">
<div class="download-all-transactions">
Download <a class="download-all-transactions-link" href=<%= address_transaction_path(@conn, :token_transfers_csv, %{"address_id" => to_string(@address.hash)}) %>><%= gettext("CSV") %></span>
Download <a class="download-all-transactions-link" href=<%= address_transaction_path(@conn, :transactions_csv, %{"address_id" => to_string(@address.hash)}) %>><%= gettext("CSV") %></span>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="16">
<path fill="#333333" fill-rule="evenodd" d="M13 16H1c-.999 0-1-1-1-1V1s-.004-1 1-1h6l7 7v8s-.032 1-1 1zm-1-8c0-.99-1-1-1-1H8s-1 .001-1-1V3c0-.999-1-1-1-1H2v12h10V8z"/>
</svg>

@ -36,7 +36,10 @@ defmodule BlockScoutWeb.APIDocsView do
def blockscout_url do
if System.get_env("BLOCKSCOUT_HOST") do
"http://" <> System.get_env("BLOCKSCOUT_HOST")
%URI{host: host, scheme: scheme} = URI.parse(Endpoint.url())
path = System.get_env("NETWORK_PATH") || "/"
scheme <> "://" <> host <> path
else
Endpoint.url()
end

@ -0,0 +1,25 @@
defmodule BlockScoutWeb.ApiDocsViewTest do
use BlockScoutWeb.ConnCase, async: true
alias BlockScoutWeb.{APIDocsView, Endpoint}
describe "blockscout_url/0" do
test "returns url with scheme and host without port" do
System.put_env("BLOCKSCOUT_HOST", "localhost")
System.put_env("NETWORK_PATH", "")
assert APIDocsView.blockscout_url() == "http://localhost"
assert Endpoint.url() == "http://localhost:4002"
end
test "returns url with scheme and host with path" do
System.put_env("BLOCKSCOUT_HOST", "localhost/chain/dog")
System.put_env("NETWORK_PATH", "/chain/dog")
assert APIDocsView.blockscout_url() == "http://localhost/chain/dog"
assert Endpoint.url() == "http://localhost:4002"
System.put_env("NETWORK_PATH", "")
end
end
end

@ -141,7 +141,9 @@ defmodule EthereumJSONRPC.HTTP do
case unstandardized do
%{"result" => _, "error" => _} ->
raise ArgumentError,
"result and error keys are mutually exclusive in JSONRPC 2.0 response objects, but got #{unstandardized}"
"result and error keys are mutually exclusive in JSONRPC 2.0 response objects, but got #{
inspect(unstandardized)
}"
%{"result" => result} ->
Map.put(standardized, :result, result)

@ -85,8 +85,8 @@ case System.get_env("SUPPLY_MODULE") do
:ok
end
if System.get_env("SOURCE_MODULE") == "TransactionAndLog" do
config :explorer, Explorer.ExchangeRates.Source, source: Explorer.ExchangeRates.Source.TransactionAndLog
if System.get_env("SOURCE_MODULE") == "TokenBridge" do
config :explorer, Explorer.ExchangeRates.Source, source: Explorer.ExchangeRates.Source.TokenBridge
end
config :explorer,

@ -1,78 +0,0 @@
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.{Chain, Repo}
{: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

@ -1,6 +1,6 @@
defmodule Explorer.ExchangeRates.Source.TransactionAndLog do
defmodule Explorer.ExchangeRates.Source.TokenBridge do
@moduledoc """
Adapter for calculating the market cap and total supply from logs and transactions
Adapter for calculating the market cap and total supply from token bridge
while still getting other info like price in dollars and bitcoin from a secondary source
"""

@ -1,122 +0,0 @@
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

@ -1,6 +1,6 @@
defmodule Explorer.ExchangeRates.Source.TransactionAndLogTest do
defmodule Explorer.ExchangeRates.Source.TokenBridgeTest do
use Explorer.DataCase
alias Explorer.ExchangeRates.Source.TransactionAndLog
alias Explorer.ExchangeRates.Source.TokenBridge
alias Explorer.ExchangeRates.Token
@json """
@ -27,7 +27,7 @@ defmodule Explorer.ExchangeRates.Source.TransactionAndLogTest do
describe "format_data/1" do
test "bring a list with one %Token{}" do
assert [%Token{}] = TransactionAndLog.format_data(@json)
assert [%Token{}] = TokenBridge.format_data(@json)
end
end
end

@ -21,7 +21,7 @@ Below is a table outlining the environment variables utilized by BlockScout.
| `METADATA_CONTRACT` | | This environment variable is specifically used by POA Network to obtain Validators information to display in the UI. | (empty) | all |
| `VALIDATORS_CONTRACT` | | This environment variable is specifically used by POA Network to obtain the Emission Fund contract. | (empty) | all |
| `SUPPLY_MODULE` | | This environment variable is used by the xDai Chain in order to tell the application how to calculate the total supply of the chain. | false | all |
| `SOURCE_MODULE` | | This environment variable is used to calculate the total supply and is specifically used by the xDai Chain. | false | all |
| `SOURCE_MODULE` | | This environment variable is used to calculate the exchange rate and is specifically used by the xDai Chain. | false | all |
| `DATABASE_URL` | | Production environment variable to define the Database endpoint. | (empty) | all |
| `POOL_SIZE` | | Production environment variable to define the number of database connections allowed. | 20 | all |
| `ECTO_USE_SSL`| | Production environment variable to use SSL on Ecto queries. | true | all |
@ -33,7 +33,7 @@ Below is a table outlining the environment variables utilized by BlockScout.
| `HEART_COMMAND` | | Production environment variable to restart the application in the event of a crash. | systemctl restart explorer.service | all |
| `BLOCKSCOUT_VERSION` | | Added to the footer to signify the current BlockScout version. | (empty) | v1.3.4+ |
| `RELEASE_LINK` | | The link to Blockscout release notes in the footer. | https://github.com/poanetwork/ <br /> <u>blockscout/releases/</u> <br /> <u>tag/${BLOCKSCOUT_VERSION}</u> | v1.3.5+ |
| `ELIXIR_VERSION` | | Elixir version to install on the node before Blockscout deploy. | (empty) | all |
| `ELIXIR_VERSION` | | Elixir version to install on the node before Blockscout deploy. | (empty) | all |
| `BLOCK_TRANSFORMER` | | Transformer for blocks: base or clique. | base | v1.3.4+ |
| `GRAPHIQL _TRANSACTION` | | Default transaction in query to GraphiQL. | (empty) | v1.3.4+ |
| `FIRST_BLOCK` | | The block number, where indexing begins from. | 0 | v1.3.8+ |

Loading…
Cancel
Save