diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5a83d3e09..1c18c34df3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.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
diff --git a/README.md b/README.md
index 5dc91fb8ef..3c95a5d125 100644
--- a/README.md
+++ b/README.md
@@ -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).
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
index 5abd8285c6..c3a4c94129 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
@@ -66,10 +66,10 @@
-
+
- Download
to_string(@address.hash)}) %>><%= gettext("CSV") %>
+ Download to_string(@address.hash)}) %>><%= gettext("CSV") %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex
index f9c280925a..40860e37bb 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex
@@ -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
diff --git a/apps/block_scout_web/test/block_scout_web/views/api_docs_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/api_docs_view_test.exs
new file mode 100644
index 0000000000..8501f27abc
--- /dev/null
+++ b/apps/block_scout_web/test/block_scout_web/views/api_docs_view_test.exs
@@ -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
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex
index 5c39243110..6d9f946554 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex
@@ -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)
diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs
index c63fe3e24c..10012bbc67 100644
--- a/apps/explorer/config/config.exs
+++ b/apps/explorer/config/config.exs
@@ -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,
diff --git a/apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex b/apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex
deleted file mode 100644
index 36432094fa..0000000000
--- a/apps/explorer/lib/explorer/chain/supply/transaction_and_log.ex
+++ /dev/null
@@ -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
diff --git a/apps/explorer/lib/explorer/exchange_rates/source/transaction_and_log.ex b/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex
similarity index 90%
rename from apps/explorer/lib/explorer/exchange_rates/source/transaction_and_log.ex
rename to apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex
index 2b8699accc..03234ff649 100644
--- a/apps/explorer/lib/explorer/exchange_rates/source/transaction_and_log.ex
+++ b/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex
@@ -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
"""
diff --git a/apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs b/apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs
deleted file mode 100644
index 5126d7acaf..0000000000
--- a/apps/explorer/test/explorer/chain/supply/transaction_and_log_test.exs
+++ /dev/null
@@ -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
diff --git a/apps/explorer/test/explorer/exchange_rates/source/transaction_and_log_test.exs b/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs
similarity index 78%
rename from apps/explorer/test/explorer/exchange_rates/source/transaction_and_log_test.exs
rename to apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs
index 47aa09f805..d5bd5f9b96 100644
--- a/apps/explorer/test/explorer/exchange_rates/source/transaction_and_log_test.exs
+++ b/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs
@@ -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
diff --git a/docs/env-variables.md b/docs/env-variables.md
index 4cbef49e82..0c93460150 100644
--- a/docs/env-variables.md
+++ b/docs/env-variables.md
@@ -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/
blockscout/releases/
tag/${BLOCKSCOUT_VERSION} | 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+ |