Merge branch 'master' into 943-read-contract-query-styling

pull/1020/head
Andrew Cravenho 6 years ago committed by GitHub
commit 9c6cb25971
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      .dockerignore
  2. 18
      apps/block_scout_web/assets/css/_typography.scss
  3. 2
      apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex
  4. 2
      apps/block_scout_web/lib/block_scout_web/templates/internal_transaction/_tile.html.eex
  5. 18
      apps/block_scout_web/lib/block_scout_web/views/currency_helpers.ex
  6. 2
      apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex
  7. 2
      apps/block_scout_web/lib/block_scout_web/views/tokens/holder_view.ex
  8. 12
      apps/block_scout_web/test/block_scout_web/views/currency_helpers_test.exs
  9. 2
      apps/block_scout_web/test/block_scout_web/views/tokens/helpers_test.exs
  10. 2
      apps/block_scout_web/test/block_scout_web/views/tokens/holder_view_test.exs
  11. 2
      apps/explorer/lib/explorer/chain/token.ex
  12. 17
      apps/explorer/priv/repo/migrations/20181029174420_update_tokens_table_decimals_from_bigint_to_numeric.exs
  13. 2
      apps/explorer/test/explorer/chain/address/token_test.exs
  14. 2
      apps/explorer/test/explorer/chain_test.exs
  15. 4
      apps/indexer/test/indexer/token/fetcher_test.exs
  16. 39
      docker/Dockerfile
  17. 101
      docker/Makefile
  18. 77
      docker/README.md

@ -0,0 +1,9 @@
_build
deps
apps/block_scout_web/assets/node_modules
apps/explorer/node_modules
test
.git
.circleci
logs
apps/*/test

@ -99,10 +99,24 @@ label, textarea.form-control {
} }
} }
[data-transaction-status="Success"] { [data-transaction-status="Success"],
[data-internal-transaction-type="Reward"] {
color: $success; color: $success;
} }
[data-transaction-status^="Error"] { [data-internal-transaction-type="Call"] {
color: $info;
}
[data-internal-transaction-type="Delegate Call"] {
color: $purple;
}
[data-internal-transaction-type="Create"] {
color: $pink;
}
[data-transaction-status^="Error"],
[data-internal-transaction-type="Suicide"] {
color: $danger; color: $danger;
} }

@ -44,7 +44,7 @@
<%= gettext("Code") %> <%= gettext("Code") %>
<%= if smart_contract_verified?(@address) do %> <%= if smart_contract_verified?(@address) do %>
<i class="far fa-check-circle"></i> <i class="far fa-check-circle text-success"></i>
<% end %> <% end %>
<% end %> <% end %>
</li> </li>

@ -2,7 +2,7 @@
<div class="row"> <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"> <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") %> <%= gettext("Internal Transaction") %>
<span>(<%= type(@internal_transaction) %>)</span> <span data-internal-transaction-type="<%= type(@internal_transaction) %>"><%= type(@internal_transaction) %></span>
</div> </div>
<div class="col-md-7 col-lg-8 d-flex flex-column text-nowrap pr-2 pr-sm-2 pr-md-0"> <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 %> <%= render BlockScoutWeb.TransactionView, "_link.html", transaction_hash: @internal_transaction.transaction_hash %>

@ -25,24 +25,24 @@ defmodule BlockScoutWeb.CurrencyHelpers do
## Examples ## Examples
iex> format_according_to_decimals(Decimal.new(20500000), 5) iex> format_according_to_decimals(Decimal.new(20500000), Decimal.new(5))
"205" "205"
iex> format_according_to_decimals(Decimal.new(20500000), 7) iex> format_according_to_decimals(Decimal.new(20500000), Decimal.new(7))
"2.05" "2.05"
iex> format_according_to_decimals(Decimal.new(205000), 12) iex> format_according_to_decimals(Decimal.new(205000), Decimal.new(12))
"0.000000205" "0.000000205"
iex> format_according_to_decimals(Decimal.new(205000), 2) iex> format_according_to_decimals(Decimal.new(205000), Decimal.new(2))
"2,050" "2,050"
iex> format_according_to_decimals(205000, 2) iex> format_according_to_decimals(205000, Decimal.new(2))
"2,050" "2,050"
""" """
@spec format_according_to_decimals(non_neg_integer(), non_neg_integer()) :: String.t() @spec format_according_to_decimals(non_neg_integer(), nil) :: String.t()
def format_according_to_decimals(value, nil) do def format_according_to_decimals(value, nil) do
format_according_to_decimals(value, 0) format_according_to_decimals(value, Decimal.new(0))
end end
def format_according_to_decimals(value, decimals) when is_integer(value) do def format_according_to_decimals(value, decimals) when is_integer(value) do
@ -51,10 +51,10 @@ defmodule BlockScoutWeb.CurrencyHelpers do
|> format_according_to_decimals(decimals) |> format_according_to_decimals(decimals)
end end
@spec format_according_to_decimals(Decimal.t(), non_neg_integer()) :: String.t() @spec format_according_to_decimals(Decimal.t(), Decimal.t()) :: String.t()
def format_according_to_decimals(%Decimal{sign: sign, coef: coef, exp: exp}, decimals) do def format_according_to_decimals(%Decimal{sign: sign, coef: coef, exp: exp}, decimals) do
sign sign
|> Decimal.new(coef, exp - decimals) |> Decimal.new(coef, exp - Decimal.to_integer(decimals))
|> Decimal.reduce() |> Decimal.reduce()
|> thousands_separator() |> thousands_separator()
end end

@ -25,7 +25,7 @@ defmodule BlockScoutWeb.Tokens.Helpers do
end end
defp do_token_transfer_amount(%Token{type: "ERC-20", decimals: nil}, amount, _token_id) do defp do_token_transfer_amount(%Token{type: "ERC-20", decimals: nil}, amount, _token_id) do
CurrencyHelpers.format_according_to_decimals(amount, 0) CurrencyHelpers.format_according_to_decimals(amount, Decimal.new(0))
end end
defp do_token_transfer_amount(%Token{type: "ERC-20", decimals: decimals}, amount, _token_id) do defp do_token_transfer_amount(%Token{type: "ERC-20", decimals: decimals}, amount, _token_id) do

@ -49,7 +49,7 @@ defmodule BlockScoutWeb.Tokens.HolderView do
## Examples ## Examples
iex> token = build(:token, type: "ERC-20", decimals: 2) iex> token = build(:token, type: "ERC-20", decimals: Decimal.new(2))
iex> BlockScoutWeb.Tokens.HolderView.format_token_balance_value(100000, token) iex> BlockScoutWeb.Tokens.HolderView.format_token_balance_value(100000, token)
"1,000" "1,000"

@ -8,42 +8,42 @@ defmodule BlockScoutWeb.CurrencyHelpersTest do
describe "format_according_to_decimals/1" do describe "format_according_to_decimals/1" do
test "formats the amount as value considering the given decimals" do test "formats the amount as value considering the given decimals" do
amount = Decimal.new(205_000_000_000_000) amount = Decimal.new(205_000_000_000_000)
decimals = 12 decimals = Decimal.new(12)
assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "205" assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "205"
end end
test "considers the decimal places according to the given decimals" do test "considers the decimal places according to the given decimals" do
amount = Decimal.new(205_000) amount = Decimal.new(205_000)
decimals = 12 decimals = Decimal.new(12)
assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "0.000000205" assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "0.000000205"
end end
test "does not consider right zeros in decimal places" do test "does not consider right zeros in decimal places" do
amount = Decimal.new(90_000_000) amount = Decimal.new(90_000_000)
decimals = 6 decimals = Decimal.new(6)
assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "90" assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "90"
end end
test "returns the full number when there is no right zeros in decimal places" do test "returns the full number when there is no right zeros in decimal places" do
amount = Decimal.new(9_324_876) amount = Decimal.new(9_324_876)
decimals = 6 decimals = Decimal.new(6)
assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "9.324876" assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "9.324876"
end end
test "formats the value considering thousands separators" do test "formats the value considering thousands separators" do
amount = Decimal.new(1_000_450) amount = Decimal.new(1_000_450)
decimals = 2 decimals = Decimal.new(2)
assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "10,004.5" assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "10,004.5"
end end
test "supports value as integer" do test "supports value as integer" do
amount = 1_000_450 amount = 1_000_450
decimals = 2 decimals = Decimal.new(2)
assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "10,004.5" assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "10,004.5"
end end

@ -12,7 +12,7 @@ defmodule BlockScoutWeb.Tokens.HelpersTest do
end end
test "returns the formatted amount according to token decimals with ERC-20 token" do test "returns the formatted amount according to token decimals with ERC-20 token" do
token = build(:token, type: "ERC-20", decimals: 6) token = build(:token, type: "ERC-20", decimals: Decimal.new(6))
token_transfer = build(:token_transfer, token: token, amount: Decimal.new(1_000_000)) token_transfer = build(:token_transfer, token: token, amount: Decimal.new(1_000_000))
assert Helpers.token_transfer_amount(token_transfer) == "1" assert Helpers.token_transfer_amount(token_transfer) == "1"

@ -44,7 +44,7 @@ defmodule BlockScoutWeb.Tokens.HolderViewTest do
describe "format_token_balance_value/1" do describe "format_token_balance_value/1" do
test "formats according to token decimals when it's a ERC-20" do test "formats according to token decimals when it's a ERC-20" do
token = build(:token, type: "ERC-20", decimals: 2) token = build(:token, type: "ERC-20", decimals: Decimal.new(2))
token_balance = build(:token_balance, value: 2_000_000) token_balance = build(:token_balance, value: 2_000_000)
assert HolderView.format_token_balance_value(token_balance.value, token) == "20,000" assert HolderView.format_token_balance_value(token_balance.value, token) == "20,000"

@ -50,7 +50,7 @@ defmodule Explorer.Chain.Token do
field(:name, :string) field(:name, :string)
field(:symbol, :string) field(:symbol, :string)
field(:total_supply, :decimal) field(:total_supply, :decimal)
field(:decimals, :integer) field(:decimals, :decimal)
field(:type, :string) field(:type, :string)
field(:cataloged, :boolean) field(:cataloged, :boolean)

@ -0,0 +1,17 @@
defmodule Explorer.Repo.Migrations.UpdateTokensTableDecimalsFromBigintToNumeric do
use Ecto.Migration
def up do
alter table("tokens") do
modify(:decimals, :decimal)
end
end
def down do
execute("""
ALTER TABLE tokens
ALTER COLUMN decimals TYPE bigint
USING CASE WHEN decimals > 9223372036854775807 THEN NULL ELSE decimals END;
""")
end
end

@ -48,7 +48,7 @@ defmodule Explorer.Chain.Address.TokenTest do
name: "token-c", name: "token-c",
symbol: "TC", symbol: "TC",
balance: Decimal.new(1000), balance: Decimal.new(1000),
decimals: 0, decimals: Decimal.new(0),
type: "ERC-721", type: "ERC-721",
transfers_count: 2 transfers_count: 2
} }

@ -2795,7 +2795,7 @@ defmodule Explorer.ChainTest do
name: "Hodl Token", name: "Hodl Token",
symbol: "HT", symbol: "HT",
total_supply: 10, total_supply: 10,
decimals: 1, decimals: Decimal.new(1),
cataloged: true cataloged: true
} }

@ -64,12 +64,14 @@ defmodule Indexer.Token.FetcherTest do
expected_supply = Decimal.new(1_000_000_000_000_000_000) expected_supply = Decimal.new(1_000_000_000_000_000_000)
decimals_expected = Decimal.new(18)
assert {:ok, assert {:ok,
%Token{ %Token{
name: "Bancor", name: "Bancor",
symbol: "BNT", symbol: "BNT",
total_supply: ^expected_supply, total_supply: ^expected_supply,
decimals: 18, decimals: ^decimals_expected,
cataloged: true cataloged: true
}} = Chain.token_from_address_hash(contract_address_hash) }} = Chain.token_from_address_hash(contract_address_hash)
end end

@ -0,0 +1,39 @@
FROM bitwalker/alpine-elixir-phoenix:latest
RUN apk --no-cache --update add automake libtool inotify-tools autoconf
EXPOSE 4000
ENV PORT=4000 \
MIX_ENV="prod" \
SECRET_KEY_BASE="RMgI4C1HSkxsEjdhtGMfwAHfyT6CKWXOgzCboJflfSm4jeAlic52io05KB6mqzc5"
# Cache elixir deps
ADD mix.exs mix.lock ./
ADD apps/block_scout_web/mix.exs ./apps/block_scout_web/
ADD apps/explorer/mix.exs ./apps/explorer/
ADD apps/ethereum_jsonrpc/mix.exs ./apps/ethereum_jsonrpc/
ADD apps/indexer/mix.exs ./apps/indexer/
RUN mix do deps.get, deps.compile
ADD . .
# Run forderground build and phoenix digest
RUN mix compile
# Add blockscout npm deps
RUN cd apps/block_scout_web/assets/ && \
npm install && \
npm run deploy && \
cd -
RUN cd apps/explorer/ && \
npm install && \
cd -
# RUN mix do ecto.drop --force, ecto.create, ecto.migrate
# USER default
# CMD ["mix", "phx.server"]

@ -0,0 +1,101 @@
SYSTEM = $(shell uname -s)
HOST = host.docker.internal
DOCKER_IMAGE = blockscout_prod
PG_CONTAINER_NAME = postgres
PG_CONTAINER_IMAGE = postgres:10.4
THIS_FILE = $(lastword $(MAKEFILE_LIST))
ifeq ($(SYSTEM), Linux)
HOST=localhost
endif
DB_URL = postgresql://postgres:@$(HOST):5432/explorer?ssl=false
BLOCKSCOUT_CONTAINNER_PARAMS = -e 'MIX_ENV=prod' \
-e 'DATABASE_URL=$(DB_URL)'
ifeq ($(SYSTEM), Linux)
BLOCKSCOUT_CONTAINNER_PARAMS += --network=host
endif
ifdef ETHEREUM_JSONRPC_VARIANT
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_VARIANT=$(ETHEREUM_JSONRPC_VARIANT)'
endif
ifdef ETHEREUM_JSONRPC_HTTP_URL
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_HTTP_URL=$(ETHEREUM_JSONRPC_HTTP_URL)'
endif
ifdef ETHEREUM_JSONRPC_WS_URL
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_WS_URL=$(ETHEREUM_JSONRPC_WS_URL)'
endif
ifdef ETHEREUM_JSONRPC_TRACE_URL
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_TRACE_URL=$(ETHEREUM_JSONRPC_TRACE_URL)'
endif
ifdef COIN
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'COIN=$(COIN)'
endif
ifdef LOGO
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'LOGO=$(LOGO)'
endif
ifdef NETWORK
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK=$(NETWORK)'
endif
ifdef SUBNETWORK
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SUBNETWORK=$(SUBNETWORK)'
endif
ifdef NETWORK_ICON
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK_ICON=$(NETWORK_ICON)'
endif
ifdef NETWORK_PATH
BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK_PATH=$(NETWORK_PATH)'
endif
HAS_BLOCKSCOUT_IMAGE := $(shell docker images | grep ${DOCKER_IMAGE})
build:
@echo "==> Checking for blockscout image $(DOCKER_IMAGE)"
ifdef HAS_BLOCKSCOUT_IMAGE
@echo "==> Image exist. Using $(DOCKER_IMAGE)"
else
@echo "==> No image found trying to build one..."
@docker build -f ./Dockerfile -t $(DOCKER_IMAGE) ../
endif
migrate: build postgres
@echo "==> Running migrations"
@docker run --rm \
$(BLOCKSCOUT_CONTAINNER_PARAMS) \
$(DOCKER_IMAGE) /bin/sh -c "echo $$MIX_ENV && mix do ecto.drop --force, ecto.create, ecto.migrate"
PG_EXIST := $(shell docker ps -a | grep ${PG_CONTAINER_NAME})
PG_STARTED := $(shell docker ps | grep ${PG_CONTAINER_NAME})
postgres:
ifdef PG_EXIST
@echo "==> Checking PostrgeSQL container"
ifdef PG_STARTED
@echo "==> PostgreSQL Already started"
else
@echo "==> Starting PostgreSQL container"
@docker start $(PG_CONTAINER_NAME)
endif
else
@echo "==> Creating new PostgreSQL container"
@docker run -d --name $(PG_CONTAINER_NAME) \
-e POSTGRES_PASSWORD="" \
-e POSTGRES_USER="postgres" \
-p 5432:5432 \
$(PG_CONTAINER_IMAGE)
@sleep 1
@$(MAKE) -f $(THIS_FILE) migrate
endif
start: build postgres
@echo "==> Starting blockscout"
@docker run --rm \
$(BLOCKSCOUT_CONTAINNER_PARAMS) \
-p 4000:4000 \
$(DOCKER_IMAGE) /bin/sh -c "mix phx.server"
run: start
.PHONY: build \
migrate \
start \
postgres \
run

@ -0,0 +1,77 @@
# BlockScout Docker integration
For now this integration is not production ready. It made only for local usage only !
## How to use ?
First of all blockscout requires `PostgreSQL` server for working.
It will be provided by starting script (new docker image will be created named `postgres`)
**Starting command**
`make start` - will set everything up and start blockscout in container.
To connect it to your local environment you will have to configure it using [env variables](#env-variables)
Exmaple connecting to local `ganache` instance running on port `2000` on Mac/Windows:
```bash
COIN=DAI \
ETHEREUM_JSONRPC_VARIANT=ganache \
ETHEREUM_JSONRPC_HTTP_URL=http://host.docker.internal:2000 \
ETHEREUM_JSONRPC_WEB_SOCKET_URL=ws://host.docker.internal:2000 \
make start
```
Blockscout will be available on `localhost:4000`
**Note**
On mac/Windows Docker provides with a special URL `host.docker.internal` that will be available into container and routed to your local machine.
On Linux docker is starting using `--network=host` and all services should be available on `localhost`
### Migrations
By default `Makefile` will do migrations for you on `PostgreSQL` creation.
But you could run migrations manualy using `make migrate` command.
**WARNING** Migrations will clean up your local database !
## Env variables
BlockScout support 3 different JSON RPC Variants.
Vriant could be configured using `ETHEREUM_JSONRPC_VARIANT` environment variable.
Example:
```bash
ETHEREUM_JSONRPC_VARIANT=ganache make start
```
Available options are:
* `parity` - Parity JSON RPC (**Default one**)
* `geth` - Geth JSON RPC
* `ganache` - Ganache JSON RPC
| Variable | Description | Default value |
| -------- | ----------- | ------------- |
| `ETHEREUM_JSONRPC_VARIANT` | Variant of your JSON RPC service: `parity`, `geth` or `ganache` | `parity` |
| `ETHEREUM_JSONRPC_HTTP_URL` | HTTP JSON RPC URL Only for `geth` or `ganache` variant | Different per JSONRPC variant |
| `ETHEREUM_JSONRPC_WS_URL` | WS JSON RPC url | Different per JSONRPC variant |
| `ETHEREUM_JSONRPC_TRACE_URL` | Trace URL **Only for `parity` variant** | `https://sokol-trace.poa.network` |
| `COIN` | Default Coin | `POA` |
| `LOGO` | Coin logo | Empty |
| `NETWORK` | Network | Empty |
| `SUBNETWORK` | Subnetwork | Empty |
| `NETWORK_ICON` | Network icon | Empty |
| `NETWORK_PATH` | Network path | `/` |
`ETHEREUM_JSONRPC_HTTP_URL` default values:
* For `parity` - `https://sokol.poa.network`
* For `geth` - `https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY`
* For `ganache` - `http://localhost:7545`
`ETHEREUM_JSONRPC_WS_URL` default values:
* For `parity` - `wss://sokol-ws.poa.network/ws`
* For `geth` - `wss://mainnet.infura.io/8lTvJTKmHPCHazkneJsY/ws`
* For `ganache` - `ws://localhost:7545`
Loading…
Cancel
Save