Merge branch 'production-mainnet-verification-alternatives' into verify-link-to-other-explorers

pull/1890/head
Victor Baranov 6 years ago committed by GitHub
commit be76748415
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .dialyzer-ignore
  2. 42
      CHANGELOG.md
  3. 178
      README.md
  4. 2
      apps/block_scout_web/assets/css/_code.scss
  5. 10
      apps/block_scout_web/assets/css/_helpers.scss
  6. 2
      apps/block_scout_web/assets/css/app.scss
  7. 2
      apps/block_scout_web/assets/css/components/_button.scss
  8. 6
      apps/block_scout_web/assets/css/components/_card.scss
  9. 4
      apps/block_scout_web/assets/css/components/_dropdown.scss
  10. 2
      apps/block_scout_web/assets/css/components/_modal.scss
  11. 42
      apps/block_scout_web/assets/css/components/_pagination.scss
  12. 113
      apps/block_scout_web/assets/css/components/_pagination_container.scss
  13. 3
      apps/block_scout_web/assets/css/components/_tile.scss
  14. 1
      apps/block_scout_web/assets/css/components/_tooltip.scss
  15. 111
      apps/block_scout_web/assets/css/theme/_dai_variables.scss
  16. 52
      apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss
  17. 53
      apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
  18. 50
      apps/block_scout_web/assets/css/theme/_goerli_variables.scss
  19. 50
      apps/block_scout_web/assets/css/theme/_kovan_variables.scss
  20. 2
      apps/block_scout_web/assets/css/theme/_lukso_variables.scss
  21. 55
      apps/block_scout_web/assets/css/theme/_poa_variables.scss
  22. 53
      apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss
  23. 50
      apps/block_scout_web/assets/css/theme/_ropsten_variables.scss
  24. 50
      apps/block_scout_web/assets/css/theme/_rsk_variables.scss
  25. 51
      apps/block_scout_web/assets/css/theme/_sokol_variables.scss
  26. 8
      apps/block_scout_web/assets/js/lib/async_listing_load.js
  27. 4
      apps/block_scout_web/assets/js/lib/list_morph.js
  28. 2
      apps/block_scout_web/assets/static/images/classic_ethereum_logo.svg
  29. 50
      apps/block_scout_web/assets/static/images/dai_logo.svg
  30. 41
      apps/block_scout_web/assets/static/images/ethereum_logo.svg
  31. 1
      apps/block_scout_web/assets/static/images/goerli_logo.svg
  32. 468
      apps/block_scout_web/assets/static/images/kovan_logo.svg
  33. 4
      apps/block_scout_web/assets/static/images/poa_logo.svg
  34. 37
      apps/block_scout_web/assets/static/images/rinkeby_logo.svg
  35. 49
      apps/block_scout_web/assets/static/images/ropsten_logo.svg
  36. 47
      apps/block_scout_web/assets/static/images/rsk_logo.svg
  37. 2
      apps/block_scout_web/assets/static/images/sokol_logo.svg
  38. 60
      apps/block_scout_web/config/config.exs
  39. 25
      apps/block_scout_web/lib/block_scout_web/chain.ex
  40. 57
      apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
  41. 46
      apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
  42. 18
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/address_controller.ex
  43. 8
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/block_controller.ex
  44. 26
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/contract_controller.ex
  45. 37
      apps/block_scout_web/lib/block_scout_web/controllers/block_controller.ex
  46. 4
      apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
  47. 181
      apps/block_scout_web/lib/block_scout_web/etherscan.ex
  48. 7
      apps/block_scout_web/lib/block_scout_web/router.ex
  49. 7
      apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex
  50. 16
      apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex
  51. 12
      apps/block_scout_web/lib/block_scout_web/templates/address_coin_balance/index.html.eex
  52. 58
      apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
  53. 80
      apps/block_scout_web/lib/block_scout_web/templates/address_internal_transaction/index.html.eex
  54. 82
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex
  55. 45
      apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex
  56. 4
      apps/block_scout_web/lib/block_scout_web/templates/address_token_balance/_token_balances.html.eex
  57. 12
      apps/block_scout_web/lib/block_scout_web/templates/address_token_transfer/index.html.eex
  58. 79
      apps/block_scout_web/lib/block_scout_web/templates/address_transaction/index.html.eex
  59. 9
      apps/block_scout_web/lib/block_scout_web/templates/address_validation/index.html.eex
  60. 6
      apps/block_scout_web/lib/block_scout_web/templates/block/_tile.html.eex
  61. 18
      apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex
  62. 4
      apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex
  63. 19
      apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex
  64. 9
      apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination.html.eex
  65. 60
      apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex
  66. 4
      apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex
  67. 11
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  68. 16
      apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex
  69. 15
      apps/block_scout_web/lib/block_scout_web/templates/tokens/transfer/index.html.eex
  70. 2
      apps/block_scout_web/lib/block_scout_web/templates/transaction/_tabs.html.eex
  71. 14
      apps/block_scout_web/lib/block_scout_web/templates/transaction/index.html.eex
  72. 19
      apps/block_scout_web/lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex
  73. 19
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/index.html.eex
  74. 9
      apps/block_scout_web/lib/block_scout_web/templates/transaction_raw_trace/index.html.eex
  75. 44
      apps/block_scout_web/lib/block_scout_web/templates/transaction_token_transfer/index.html.eex
  76. 13
      apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
  77. 252
      apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex
  78. 3
      apps/block_scout_web/lib/block_scout_web/views/address_logs_view.ex
  79. 1
      apps/block_scout_web/lib/block_scout_web/views/address_view.ex
  80. 21
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/address_view.ex
  81. 28
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/block_view.ex
  82. 54
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/contract_view.ex
  83. 33
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/eth_rpc_view.ex
  84. 3
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/transaction_view.ex
  85. 118
      apps/block_scout_web/lib/block_scout_web/views/layout_view.ex
  86. 330
      apps/block_scout_web/priv/gettext/default.pot
  87. 330
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  88. 117
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/address_controller_test.exs
  89. 89
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs
  90. 3
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/transaction_controller_test.exs
  91. 3
      apps/block_scout_web/test/block_scout_web/controllers/block_controller_test.exs
  92. 38
      apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs
  93. 147
      apps/block_scout_web/test/block_scout_web/views/layout_view_test.exs
  94. 3
      apps/explorer/.gitignore
  95. 12
      apps/explorer/config/config.exs
  96. 2
      apps/explorer/config/test.exs
  97. 8
      apps/explorer/lib/explorer/application.ex
  98. 166
      apps/explorer/lib/explorer/chain.ex
  99. 3
      apps/explorer/lib/explorer/chain/address.ex
  100. 6
      apps/explorer/lib/explorer/chain/block.ex
  101. Some files were not shown because too many files have changed in this diff Show More

@ -3,4 +3,5 @@
:0: Unknown type 'Elixir.Map':t/0
apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex:400: Function timestamp_to_datetime/1 has no local return
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: Function microseconds_time/1 has no local return
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: The call 'Elixir.System':convert_time_unit(__@1::any(),'native','microseconds') breaks the contract (integer(),time_unit() | 'native',time_unit() | 'native') -> integer()
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: The call 'Elixir.System':convert_time_unit(__@1::any(),'native','microseconds') breaks the contract (integer(),time_unit() | 'native',time_unit() | 'native') -> integer()
apps/block_scout_web/lib/block_scout_web/views/layout_view.ex:174: The call 'Elixir.Poison.Parser':'parse!'(any(),#{'keys':='atoms!'}) will never return since the success typing is (binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | []),[{atom(),_}]) -> 'false' | 'nil' | 'true' | binary() | ['false' | 'nil' | 'true' | binary() | [any()] | number() | map()] | number() | map() and the contract is (iodata(),'Elixir.Keyword':t()) -> t()

@ -1,16 +1,38 @@
## Current
### Features
- [#1963](https://github.com/poanetwork/blockscout/pull/1963) - added rinkeby theme and rinkeby logo
- [#1959](https://github.com/poanetwork/blockscout/pull/1959) - added goerli theme and goerli logo
- [#1928](https://github.com/poanetwork/blockscout/pull/1928) - pagination styles were updated
- [#1948](https://github.com/poanetwork/blockscout/pull/1948) - added ropsten theme and ropsten logo
- [#1940](https://github.com/poanetwork/blockscout/pull/1940) - qr modal button and background issue
- [#1936](https://github.com/poanetwork/blockscout/pull/1936) - added kovan, sokol themes and logos
- [#1925](https://github.com/poanetwork/blockscout/pull/1925) - added dai theme and logo
- [#1922](https://github.com/poanetwork/blockscout/pull/1922) - added ethereum classic theme and logo
- [#1907](https://github.com/poanetwork/blockscout/pull/1907) - dropdown color bug fix (lukso theme) and tooltip color bug fix
- [#1903](https://github.com/poanetwork/blockscout/pull/1903) - added rsk theme and rsk logo
- [#1895](https://github.com/poanetwork/blockscout/pull/1895) - add changes to poa theme and poa logo
- [#1812](https://github.com/poanetwork/blockscout/pull/1812) - add pagination to addresses page
- [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo
- [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x"
- [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page
- [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request
- [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir
- [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir
- [#1859](https://github.com/poanetwork/blockscout/pull/1859) - feat: show raw transaction traces
- [#1890](https://github.com/poanetwork/blockscout/pull/1890) - Verification links to other explorers for ETH Mainnet
- [#1920](https://github.com/poanetwork/blockscout/pull/1920) - fix: remove source code fields from list endpoint
- [#1876](https://github.com/poanetwork/blockscout/pull/1876) - async calculate a count of blocks
- [#1941](https://github.com/poanetwork/blockscout/pull/1941) - feat: add on demand fetching and stale attr to rpc
- [#1957](https://github.com/poanetwork/blockscout/pull/1957) - Calculate stakes ratio before insert pools
- [#1956](https://github.com/poanetwork/blockscout/pull/1956) - add logs tab to address
- [#1933](https://github.com/poanetwork/blockscout/pull/1933) - add eth_BlockNumber json rpc method
- [#1952](https://github.com/poanetwork/blockscout/pull/1952) - feat: exclude empty contracts by default
- [#1954](https://github.com/poanetwork/blockscout/pull/1954) - feat: use creation init on self destruct
### Fixes
- [#1944](https://github.com/poanetwork/blockscout/pull/1944) - fixed styles for token's dropdown.
- [#1926](https://github.com/poanetwork/blockscout/pull/1926) - status label alignment
- [#1829](https://github.com/poanetwork/blockscout/pull/1829) - Handle nil quantities in block decoding routine
- [#1830](https://github.com/poanetwork/blockscout/pull/1830) - Make block size field nullable
- [#1840](https://github.com/poanetwork/blockscout/pull/1840) - Handle case when total supply is nil
@ -18,11 +40,27 @@
- [#1849](https://github.com/poanetwork/blockscout/pull/1849) - Improve chains menu
- [#1869](https://github.com/poanetwork/blockscout/pull/1869) - Fix output and gas extraction in JS tracer for Geth
- [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance
- [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view
- [#1885](https://github.com/poanetwork/blockscout/pull/1885) - highlight reserved words in decompiled code
- [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete
- [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance
- [#1905](https://github.com/poanetwork/blockscout/pull/1905) - fix reorgs, uncles pagination
- [#1875](https://github.com/poanetwork/blockscout/pull/1875) - fix: resolve false positive constructor arguments
- [#1904](https://github.com/poanetwork/blockscout/pull/1904) - fix `BLOCK_COUNT_CACHE_TTL` env var type
- [#1898](https://github.com/poanetwork/blockscout/pull/1898) - check if the constructor has arguments before verifying constructor arguments
- [#1915](https://github.com/poanetwork/blockscout/pull/1915) - fallback to 2 latest evm versions
- [#1937](https://github.com/poanetwork/blockscout/pull/1937) - Check the presence of overlap[i] object before retrieving properties from it
- [#1960](https://github.com/poanetwork/blockscout/pull/1960) - do not remove bold text in decompiled contacts
- [#1917](https://github.com/poanetwork/blockscout/pull/1917) - Force block refetch if transaction is re-collated in a different block
### Chore
- [#1814](https://github.com/poanetwork/blockscout/pull/1814) - Clear build artefacts script
- [#1837](https://github.com/poanetwork/blockscout/pull/1837) - Add -f flag to clear_build.sh script delete static folder
- [#1900](https://github.com/poanetwork/blockscout/pull/1900) - SUPPORTED_CHAINS ENV var
- [#1892](https://github.com/poanetwork/blockscout/pull/1892) - Remove temporary worker modules
- [#1958](https://github.com/poanetwork/blockscout/pull/1958) - Default value for release link env var
- [#1975](https://github.com/poanetwork/blockscout/pull/1975) - add log index to transaction view
## 1.3.10-beta

@ -16,7 +16,9 @@ BlockScout provides a comprehensive, easy-to-use interface for users to view, co
Following is an overview of the project and instructions for [getting started](#getting-started).
Visit the [POA BlockScout forum](https://forum.poa.network/c/blockscout) or the [Gitter Channel](https://gitter.im/poanetwork/blockscout) to access additional information or post questions.
Visit the [POA BlockScout forum](https://forum.poa.network/c/blockscout) for additional deployment instructions, FAQs, troubleshooting, and other BlockScout related items. You can also post and answer questions here.
You can also access the dev chatroom on our [Gitter Channel](https://gitter.im/poanetwork/blockscout).
## About BlockScout
@ -41,30 +43,16 @@ Currently available block explorers (i.e. Etherscan and Etherchain) are closed s
### Supported Projects
#### Hosted Chains
* [POA Core Network](https://blockscout.com/poa/core)
* [POA Sokol Testnet](https://blockscout.com/poa/sokol)
* [xDai Chain](https://blockscout.com/poa/dai)
* [Ethereum Mainnet](https://blockscout.com/eth/mainnet)
* [Kovan Testnet](https://blockscout.com/eth/kovan)
* [Ropsten Testnet](https://blockscout.com/eth/ropsten)
* [Goerli Testnet](https://blockscout.com/eth/goerli)
* [Rinkeby Testnet](https://blockscout.com/eth/rinkeby)
* [Ethereum Classic](https://blockscout.com/etc/mainnet)
* [Aerum](https://blockscout.com/aerum/mainnet)
* [Callisto](https://blockscout.com/callisto/mainnet)
* [RSK](https://blockscout.com/rsk/mainnet)
#### Additional Chains Utilizing BlockScout
* [Oasis Labs](https://blockexplorer.oasiscloud.io/)
* [Fuse Network](https://explorer.fuse.io/)
* [ARTIS](https://explorer.sigma1.artis.network)
* [SafeChain](https://explorer.safechain.io)
* [SpringChain](https://explorer.springrole.com/)
* [PIRL](http://pirl.es/)
* [Petrichor](https://explorer.petrichor-dev.com/)
| **Hosted Mainnets** | **Hosted Testnets** | **Additional Chains using BlockScout** |
|--------------------------------------------------------|-------------------------------------------------------|----------------------------------------------------|
| [Aerum](https://blockscout.com/aerum/mainnet) | [Goerli Testnet](https://blockscout.com/eth/goerli) | [ARTIS](https://explorer.sigma1.artis.network) |
| [Callisto](https://blockscout.com/callisto/mainnet) | [Kovan Testnet](https://blockscout.com/eth/kovan) | [Ether-1](https://blocks.ether1.wattpool.net/) |
| [Ethereum Classic](https://blockscout.com/etc/mainnet) | [POA Sokol Testnet](https://blockscout.com/poa/sokol) | [Fuse Network](https://explorer.fuse.io/) |
| [Ethereum Mainnet](https://blockscout.com/eth/mainnet) | [Rinkeby Testnet](https://blockscout.com/eth/rinkeby) | [Oasis Labs](https://blockexplorer.oasiscloud.io/) |
| [POA Core Network](https://blockscout.com/poa/core) | [Ropsten Testnet](https://blockscout.com/eth/ropsten) | [Petrichor](https://explorer.petrachor.com/) |
| [RSK](https://blockscout.com/rsk/mainnet) | | [PIRL](http://pirl.es/) |
| [xDai Chain](https://blockscout.com/poa/dai) | | [SafeChain](https://explorer.safechain.io) |
| | | [SpringChain](https://explorer.springrole.com/) |
### Visual Interface
@ -73,13 +61,24 @@ Interface for the POA network _updated 02/2019_
![BlockScout Example](explorer_example_2_2019.gif)
## Getting Started
We use [Terraform](https://www.terraform.io/intro/getting-started/install.html) to build the correct infrastructure to run BlockScout. See [https://github.com/poanetwork/blockscout-terraform](https://github.com/poanetwork/blockscout-terraform) for details.
### Umbrella Project Organization
### Requirements
This repository is an [umbrella project](https://elixir-lang.org/getting-started/mix-otp/dependencies-and-umbrella-projects.html). Each directory under `apps/` is a separate [Mix](https://hexdocs.pm/mix/Mix.html) project and [OTP application](https://hexdocs.pm/elixir/Application.html), but the projects can use each other as a dependency in their `mix.exs`.
The [development stack page](https://github.com/poanetwork/blockscout/wiki/Development-Stack) contains more information about these frameworks.
Each OTP application has a restricted domain.
| Directory | OTP Application | Namespace | Purpose |
|:------------------------|:--------------------|:------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `apps/ethereum_jsonrpc` | `:ethereum_jsonrpc` | `EthereumJSONRPC` | Ethereum JSONRPC client. It is allowed to know `Explorer`'s param format, but it cannot directly depend on `:explorer` |
| `apps/explorer` | `:explorer` | `Explorer` | Storage for the indexed chain. Can read and write to the backing storage. MUST be able to boot in a read-only mode when run independently from `:indexer`, so cannot depend on `:indexer` as that would start `:indexer` indexing. |
| `apps/block_scout_web` | `:block_scout_web` | `BlockScoutWeb` | Phoenix interface to `:explorer`. The minimum interface to allow web access should go in `:block_scout_web`. Any business rules or interface not tied directly to `Phoenix` or `Plug` should go in `:explorer`. MUST be able to boot in a read-only mode when run independently from `:indexer`, so cannot depend on `:indexer` as that would start `:indexer` indexing. |
| `apps/indexer` | `:indexer` | `Indexer` | Uses `:ethereum_jsonrpc` to index chain and batch import data into `:explorer`. Any process, `Task`, or `GenServer` that automatically reads from the chain and writes to `:explorer` should be in `:indexer`. This restricts automatic writes to `:indexer` and read-only mode can be achieved by not running `:indexer`. |
## Getting Started
### Requirements
| Dependency | Mac | Linux |
|-------------|-----|-------|
@ -95,121 +94,42 @@ The [development stack page](https://github.com/poanetwork/blockscout/wiki/Devel
### Build and Run
1. Clone the repository.
`git clone https://github.com/poanetwork/blockscout`
2. Go to the explorer subdirectory.
`cd blockscout`
3. Set up default configurations.
`cp apps/explorer/config/dev.secret.exs.example apps/explorer/config/dev.secret.exs`
`cp apps/block_scout_web/config/dev.secret.exs.example apps/block_scout_web/config/dev.secret.exs`
<br />Linux: Update the database username and password configuration in `apps/explorer/config/dev.secret.exs`
<br />Mac: Remove the `username` and `password` fields from `apps/explorer/config/dev.secret.exs`
<br />Optional: Set up default configuration for testing.
`cp apps/explorer/config/test.secret.exs.example apps/explorer/config/test.secret.exs`
Example usage: Changing the default Postgres port from localhost:15432 if [Boxen](https://github.com/boxen/boxen) is installed.
4. Install dependencies.
`mix do deps.get, local.rebar --force, deps.compile, compile`
5. Create and migrate database.
`mix ecto.create && mix ecto.migrate`
<br />_Note:_ If you have run previously, drop the previous database
`mix do ecto.drop, ecto.create, ecto.migrate`
#### Playbook Deployment
6. Install Node.js dependencies.
`cd apps/block_scout_web/assets && npm install; cd -`
`cd apps/explorer && npm install; cd -`
We use [Ansible](https://docs.ansible.com/ansible/latest/index.html) & [Terraform](https://www.terraform.io/intro/getting-started/install.html) to build the correct infrastructure to run BlockScout. See [https://github.com/poanetwork/blockscout-terraform](https://github.com/poanetwork/blockscout-terraform) for details and instructions.
7. Update your JSON RPC Variant in `apps/explorer/config/dev.exs` and `apps/indexer/config/dev.exs`.
For `variant`, enter `ganache`, `geth`, `parity`, or `rsk`
#### Manual Deployment
8. Update your JSON RPC Endpoint in `apps/explorer/config/dev/` and `apps/indexer/config/dev/`
For the `variant` chosen in step 7, enter the correct information for the corresponding JSON RPC Endpoint in `parity.exs`, `geth.exs`, or `ganache.exs`
See [Manual BlockScout Deployment](https://forum.poa.network/t/manual-blockscout-deployment/2458) for instructions.
9. Enable HTTPS in development. The Phoenix server only runs with HTTPS.
* `cd apps/block_scout_web`
* `mix phx.gen.cert blockscout blockscout.local; cd -`
* Add blockscout and blockscout.local to your `/etc/hosts`
```
127.0.0.1 localhost blockscout blockscout.local
255.255.255.255 broadcasthost
::1 localhost blockscout blockscout.local
```
* If using Chrome, Enable `chrome://flags/#allow-insecure-localhost`.
#### Environment Variables
9. Start Phoenix Server.
`mix phx.server`
Our forum contains a [full list of BlockScout environment variables](https://forum.poa.network/t/faq-blockscout-environment-variables/1814).
Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
#### Configuring EVM Chains
_Additional runtime options:_
* **CSS:** Update the import instruction in `apps/block_scout_web/assets/css/theme/_variables.scss` to select a preset css file. This is reflected in the `production-${chain}` branch for each instance. For example, in the `production-xdai` branch, it is set to `@import "dai-variables"`.
* Run Phoenix Server with IEx (Interactive Elixer)
`iex -S mix phx.server`
* **ENV:** Update the [environment variables](https://forum.poa.network/t/faq-blockscout-environment-variables/1814) to match the chain specs.
* Run Phoenix Server with real time indexer
`iex -S mix phx.server`
### Automating Restarts
#### Automating Restarts
By default `blockscout` does not restart if it crashes. To enable automated
restarts, set the environment variable `HEART_COMMAND` to whatever you run to
start `blockscout`. You can configure the heart beat timeout, which will change
how long it will wait before considering the application to be unresponsive. At
that point, it will kill the current blockscout and execute `HEART_COMMAND`.
By default a crash dump is not written unless you set `ERL_CRASH_DUMP_SECONDS`
to a positive or negative integer. See the documentation for
[heart](http://erlang.org/doc/man/heart.html) for more information.
### Configuring Ethereum Classic and other EVM Chains
**Note: Most of these modifications will be consolidated into a single file in the future.**
1. Update the import file in `apps/block_scout_web/assets/css/theme/_variables.scss`. There are several preset css files for our supported chains which include Ethereum Classic, Ethereum Mainnet, Ropsten Testnet, Kovan Testnet, POA Core, and POA Sokol. To deploy Ethereum Classic, change the import to `ethereum_classic_variables`.
2. Update the logo file in `apps/block_scout_web/config/config.exs`. To deploy Ethereum Classic, change this file to `classic_ethereum_logo.svg`.
3. Update the `check_origin` configuration in `apps/block_scout_web/config/prod.exs`. This allows realtime events to occur on your endpoint.
4. Update the node configuration. You will need a full tracing node with WebSockets enabled. Make the changes in the following files (dev/prod):
* `apps/explorer/config/dev/parity.exs`
* `apps/explorer/config/prod/parity.exs`
* `apps/indexer/config/dev/parity.exs`
* `apps/indexer/config/prod/parity.exs`
5. Update the dropdown menu in the main navigation `apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex`
6. Update the coin in `apps/explorer/config/config.exs`. This will pull relevant information from Coinmarketcap.com.
### Umbrella Project Organization
This repository is an [umbrella project](https://elixir-lang.org/getting-started/mix-otp/dependencies-and-umbrella-projects.html). Each directory under `apps/` is a separate [Mix](https://hexdocs.pm/mix/Mix.html) project and [OTP application](https://hexdocs.pm/elixir/Application.html), but the projects can use each other as a dependency in their `mix.exs`.
Each OTP application has a restricted domain.
| Directory | OTP Application | Namespace | Purpose |
|:------------------------|:--------------------|:------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `apps/ethereum_jsonrpc` | `:ethereum_jsonrpc` | `EthereumJSONRPC` | Ethereum JSONRPC client. It is allowed to know `Explorer`'s param format, but it cannot directly depend on `:explorer` |
| `apps/explorer` | `:explorer` | `Explorer` | Storage for the indexed chain. Can read and write to the backing storage. MUST be able to boot in a read-only mode when run independently from `:indexer`, so cannot depend on `:indexer` as that would start `:indexer` indexing. |
| `apps/block_scout_web` | `:block_scout_web` | `BlockScoutWeb` | Phoenix interface to `:explorer`. The minimum interface to allow web access should go in `:block_scout_web`. Any business rules or interface not tied directly to `Phoenix` or `Plug` should go in `:explorer`. MUST be able to boot in a read-only mode when run independently from `:indexer`, so cannot depend on `:indexer` as that would start `:indexer` indexing. |
| `apps/indexer` | `:indexer` | `Indexer` | Uses `:ethereum_jsonrpc` to index chain and batch import data into `:explorer`. Any process, `Task`, or `GenServer` that automatically reads from the chain and writes to `:explorer` should be in `:indexer`. This restricts automatic writes to `:indexer` and read-only mode can be achieved by not running `:indexer`. |
restarts, set the environment variable `HEART_COMMAND` to whatever command you run to start `blockscout`. Configure the heart beat timeout to change how long it waits before considering the application unresponsive. At that point, it will kill the current blockscout instance and execute the `HEART_COMMAND`. By default a crash dump is not written unless you set `ERL_CRASH_DUMP_SECONDS` to a positive or negative integer. See the [heart](http://erlang.org/doc/man/heart.html) documentation for more information.
### CircleCI Updates
#### CircleCI Updates
To monitor build status, configure your local [CCMenu](http://ccmenu.org/) with the following url: [`https://circleci.com/gh/poanetwork/blockscout.cc.xml?circle-token=f8823a3d0090407c11f87028c73015a331dbf604`](https://circleci.com/gh/poanetwork/blockscout.cc.xml?circle-token=f8823a3d0090407c11f87028c73015a331dbf604)
### Testing
## Testing
#### Requirements
### Requirements
* PhantomJS (for wallaby)
#### Running the tests
### Running the tests
1. Build the assets.
`cd apps/block_scout_web/assets && npm run build; cd -`
@ -236,9 +156,9 @@ To monitor build status, configure your local [CCMenu](http://ccmenu.org/) with
8. Test the JavaScript code.
`cd apps/block_scout_web/assets && npm run test; cd -`
##### Parity
#### Parity
###### Mox
##### Mox
**This is the default setup. `mix coveralls.html --umbrella` will work on its own, but to be explicit, use the following setup**:
@ -248,7 +168,7 @@ export ETHEREUM_JSONRPC_WEB_SOCKET_CASE=EthereumJSONRPC.WebSocket.Case.Mox
mix coveralls.html --umbrella --exclude no_parity
```
###### HTTP / WebSocket
##### HTTP / WebSocket
```shell
export ETHEREUM_JSONRPC_CASE=EthereumJSONRPC.Case.Parity.HTTPWebSocket
@ -261,9 +181,9 @@ mix coveralls.html --umbrella --exclude no_parity
| HTTP | `http://localhost:8545` |
| WebSocket | `ws://localhost:8546` |
##### Geth
#### Geth
###### Mox
##### Mox
```shell
export ETHEREUM_JSONRPC_CASE=EthereumJSONRPC.Case.Geth.Mox
@ -271,7 +191,7 @@ export ETHEREUM_JSONRPC_WEB_SOCKET_CASE=EthereumJSONRPC.WebSocket.Case.Mox
mix coveralls.html --umbrella --exclude no_geth
```
###### HTTP / WebSocket
##### HTTP / WebSocket
```shell
export ETHEREUM_JSONRPC_CASE=EthereumJSONRPC.Case.Geth.HTTPWebSocket

@ -14,7 +14,7 @@ pre {
.pre-decompiled code::before {
content: counter(line);
display: inline-block;
width: flex;
width: 3em;
border-right: 1px solid #ddd;
padding: 0 .5em;
margin-right: .5em;

@ -20,4 +20,12 @@
@include media-breakpoint-down(md) {
margin-right: 0;
}
}
}
.clearfix:after {
clear: both;
content: " "; /* Older browser do not support empty content */
display: block;
height: 0;
visibility: hidden;
}

@ -69,7 +69,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "components/panels";
@import "components/nav_tabs";
@import "components/dot";
@import "components/pagination";
@import "components/pagination_container";
@import "components/address_link";
@import "components/footer";
@import "components/filter";

@ -1,7 +1,7 @@
$button-primary-color: $primary !default;
$button-secondary-color: $secondary !default;
.button {
.button, .btn {
border-radius: 2px;
border: none;
cursor: pointer;

@ -18,8 +18,8 @@ $card-background-1-text-color: #fff !default;
background-color: $card-background-1;
color: $card-background-1-text-color;
a,
a:hover {
a:not(.dropdown-item),
a:not(.dropdown-item):hover {
color: $card-background-1-text-color;
}
}
@ -67,7 +67,7 @@ $card-background-1-text-color: #fff !default;
}
.card-subtitle {
color: #aaa;
color: #333;
font-size: 12px;
font-weight: normal;
line-height: 1.2;

@ -60,9 +60,9 @@
.dropdown-search-icon {
color: $gray-300;
left: 0.625rem;
left: 8px;
pointer-events: none;
top: 0.5rem;
top: 5px;
}
.dropdown-search-field {

@ -1,4 +1,4 @@
$modal-overlay-color: rgba($secondary, 0.9) !default;
$modal-overlay-color: rgba($primary, 0.9) !default;
$modal-horizontal-padding: 30px !default;
$modal-vertical-padding: 25px !default;
$modal-border-radius: 10px !default;

@ -1,42 +0,0 @@
$pagination-page-link-background: #f5f6fa !default;
$pagination-page-link-color: #a3a9b5 !default;
$pagination-page-link-background-active: $primary !default;
$pagination-page-link-color-active: #fff !default;
.pagination {
margin: 0;
padding: 30px;
.page-item {
margin: 0 10px 0 0;
&:last-child {
margin-right: 0;
}
}
.page-link {
background-color: $pagination-page-link-background;
border: 1px solid $pagination-page-link-background;
color: $pagination-page-link-color;
display: block;
line-height: 1.25;
margin: 0;
padding: 0.5rem 0.75rem;
position: relative;
&:hover {
background-color: darken($pagination-page-link-background, 5%);
border-color: darken($pagination-page-link-background, 5%);
}
.active & {
&,
&:hover {
background-color: $pagination-page-link-background-active;
border-color: $pagination-page-link-background-active;
color: $pagination-page-link-color-active;
}
}
}
}

@ -0,0 +1,113 @@
$pagination-page-link-background: #f5f6fa !default;
$pagination-page-link-color: #a3a9b5 !default;
$pagination-page-link-background-active: $primary !default;
$pagination-page-link-color-active: #fff !default;
@mixin pagination-container-base($background-color, $text-color) {
background-color: $background-color;
border: 1px solid $background-color;
color: $text-color;
path {
fill: $text-color;
}
}
.pagination-container {
display: flex;
justify-content: space-between;
@include media-breakpoint-down(sm) {
flex-direction: column;
}
&.position-bottom {
padding-top: 30px;
}
&.position-top {
padding-bottom: 30px;
}
.pagination-limit {
align-items: center;
color: #033333;
display: flex;
font-size: 12px;
font-weight: 600;
line-height: 1.2;
@include media-breakpoint-down(sm) {
margin-bottom: 15px;
}
select {
margin: 0 10px;
}
}
.pagination {
margin: 0 0 0 auto;
padding: 0;
@include media-breakpoint-down(sm) {
justify-content: space-between;
margin: 0;
}
.page-item {
margin: 0 5px 0 0;
&:last-child {
margin-right: 0;
}
&.active .page-link {
@include pagination-container-base($pagination-page-link-background-active, $pagination-page-link-color-active);
cursor: default;
pointer-events: none;
&:hover {
@include pagination-container-base($pagination-page-link-background-active, $pagination-page-link-color-active);
}
}
}
.page-link {
@include pagination-container-base($pagination-page-link-background, $pagination-page-link-color);
align-items: center;
border-radius: 2px;
display: flex;
font-size: 12px;
font-weight: 600;
height: 24px;
margin: 0;
padding: 0 8px;
position: relative;
user-select: none;
text-align: center;
white-space: nowrap;
&:not(.no-hover):hover {
@include pagination-container-base($pagination-page-link-background-active, $pagination-page-link-color-active);
}
&[href=''] {
pointer-events: none;
}
&.no-hover {
cursor: default;
}
&[disabled] {
@include pagination-container-base($pagination-page-link-background, $pagination-page-link-color);
cursor: not-allowed;
opacity: 0.4;
outline: none;
pointer-events: none;
}
}
}
}

@ -77,6 +77,7 @@ $tile-padding: 1rem;
font-weight: 700;
line-height: 1.2;
margin: 0 0 2px;
text-align: center;
&:last-child {
margin-bottom: 0;
@ -116,6 +117,8 @@ $tile-padding: 1rem;
font-size: 12px;
font-weight: 400;
line-height: 1.2;
text-align: center;
padding: 0 5px;
}
.tile-bottom-contents {

@ -14,5 +14,6 @@ $tooltip-color: #fff !default;
.arrow::before {
border-top-color: $tooltip-background-color;
border-bottom-color: $tooltip-background-color;
}
}

@ -1,61 +1,50 @@
$primary: #fec042;
$secondary: #53546a;
$tertiary: #1755e4;
.navbar.navbar-primary {
background-color: #f2f6f8;
&.navbar-dark .navbar-nav .nav-link {
color: $secondary;
&:hover,
&:focus {
color: rgba($secondary, 0.75);
}
}
.form-control {
color: $secondary;
&::-webkit-input-placeholder {
/* Chrome/Opera/Safari */
color: transparentize($secondary, 0.5);
}
&::-moz-placeholder {
/* Firefox 19+ */
color: transparentize($secondary, 0.5);
}
&:-ms-input-placeholder {
/* IE 10+ */
color: transparentize($secondary, 0.5);
}
&:-moz-placeholder {
/* Firefox 18- */
color: transparentize($secondary, 0.5);
}
}
}
.navbar-logo {
height: 1.75em;
}
.navbar.navbar-dark .navbar-toggler {
color: $secondary;
border-color: $secondary;
.navbar-toggler-icon {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{transparentize($secondary, 0.5)}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");
}
}
.button.button-secondary {
color: $secondary;
border-color: $secondary;
&:hover,
&:focus {
background-color: $secondary;
border-color: $secondary;
}
}
// general
$primary: #2b2b2b;
$secondary: #ffb045;
$tertiary: #929292;
$additional-font: #ffffff;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #7e7e7e;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #424242; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $secondary; // top border on hover
$header-icon-color-hover: $secondary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: #424242; // button border and font color && hover bg color
$btn-copy-color: #424242; // btn copy
$btn-qr-color: #424242; // btn qr-code
//links & tile
.tile a { color: #4b89fb !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $secondary;
} // tab active bg
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;

@ -1,8 +1,50 @@
$primary: #1b1b39;
$secondary: #4beba0;
$tertiary: #4beba0;
// general
$primary: #1c1c3d;
$secondary: #4ad7a7;
$tertiary: #5959d8;
$additional-font: #bdbdff;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #fff;
$footer-item-disc-color: $secondary;
$footer-text-color: $additional-font;
$footer-item-disc-color: $tertiary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #2d2d69; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $tertiary; // top border on hover
$header-icon-color-hover: $tertiary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $tertiary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: #27275e; // button border and font color && hover bg color
$btn-copy-color: #27275e; // btn copy
$btn-qr-color: #27275e; // btn qr-code
//links & tile
.tile a { color: $tertiary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid #27275e;
} // tab active bg
// card
$card-background-1: $tertiary;
$card-tab-active: $tertiary;

@ -1,3 +1,50 @@
$primary: #16465b;
$secondary: #5ab3ff;
$tertiary: #77a4c5;
// general
$primary: #153550;
$secondary: #49a2ee;
$tertiary: #4ad7a7;
$additional-font: #89cae6;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #89cae6;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #1c476c; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $secondary; // top border on hover
$header-icon-color-hover: $secondary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: $secondary; // button border and font color && hover bg color
$btn-copy-color: $secondary; // btn copy
$btn-qr-color: $secondary; // btn qr-code
//links & tile
.tile a { color: $secondary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $secondary;
} // tab active bg
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;

@ -1,8 +1,50 @@
$primary: #20201a;
$secondary: #f0d96b;
$tertiary: #4a443a;
// general
$primary: #2b2b2b;
$secondary: #eac247;
$tertiary: #929292;
$additional-font: #ffffff;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #fff;
$footer-text-color: #7e7e7e;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #424242; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $secondary; // top border on hover
$header-icon-color-hover: $secondary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: #424242; // button border and font color && hover bg color
$btn-copy-color: #424242; // btn copy
$btn-qr-color: #424242; // btn qr-code
//links & tile
.tile a { color: #a46f30 !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $secondary;
} // tab active bg
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;

@ -1,8 +1,50 @@
$primary: #28aca4;
$secondary: #89edda;
$tertiary: #997fdc;
// general
$primary: #101f25;
$secondary: #35e3d8;
$tertiary: #1f857f;
$additional-font: #99fff9;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #fff;
$footer-text-color: $secondary;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #1a323b; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $tertiary; // top border on hover
$header-icon-color-hover: $tertiary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $tertiary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: $tertiary; // button border and font color && hover bg color
$btn-copy-color: $tertiary; // btn copy
$btn-qr-color: $tertiary; // btn qr-code
//links & tile
.tile a { color: $tertiary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $tertiary;
} // tab active bg
// card
$card-background-1: $primary;
$card-tab-active: $primary;

@ -12,7 +12,7 @@ $dashboard-stats-item-value-color: $primary;
$dashboard-stats-item-border-color: $primary;
$header-links-color-active: #333;
.dropdown-item:hover, .dropdown-item:focus { background-color: $primary !important; }
$tile-type-block-color: $secondary;
$navbar-logo-height: 18px;

@ -1,11 +1,50 @@
$primary: #5b389f;
$secondary: #7dd79f;
$tertiary: #997fdc;
// general
$primary: #5c34a2;
$secondary: #87e1a9;
$tertiary: #bf9cff;
$additional-font: #fff;
$header-links-color-active: #333;
$button-secondary-color: $primary;
$footer-background-color: $primary;
// footer
$footer-background-color: #3c226a;
$footer-title-color: #fff;
$footer-text-color: #fff;
$footer-text-color: #bda6e7;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #865bd4; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $primary; // top border on hover
$header-icon-color-hover: $primary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $primary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: $primary; // button border and font color && hover bg color
$btn-copy-color: $primary; // btn copy
$btn-qr-color: $primary; // btn qr-code
//links & tile
.tile a { color: $primary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $primary;
} // tab active bg
// card
$card-background-1: $primary;
$card-tab-active: $primary;

@ -1,3 +1,50 @@
$primary: #2a3f54;
$secondary: #39c4a9;
$tertiary: #39c4a9;
// general
$primary: #193653;
$secondary: #49a2ee;
$tertiary: #41c3a9;
$additional-font: #a3ceff;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: $additional-font;
$footer-item-disc-color: $additional-font;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $tertiary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #244468; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $tertiary; // top border on hover
$header-icon-color-hover: $tertiary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $tertiary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: $tertiary; // button border and font color && hover bg color
$btn-copy-color: $tertiary; // btn copy
$btn-qr-color: $tertiary; // btn qr-code
//links & tile
.tile a { color: $tertiary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $tertiary;
} // tab active bg
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;

@ -1,8 +1,50 @@
$primary: #2fa8f8;
$secondary: #a2daff;
$tertiary: #006aa7;
// general
$primary: #153550;
$secondary: #38a9f5;
$tertiary: #76f1ff;
$additional-font: #89cae6;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #fff;
$footer-text-color: #89cae6;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $tertiary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #1c476c; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $secondary; // top border on hover
$header-icon-color-hover: $secondary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: $secondary; // button border and font color && hover bg color
$btn-copy-color: $secondary; // btn copy
$btn-qr-color: $secondary; // btn qr-code
//links & tile
.tile a { color: $secondary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $secondary;
} // tab active bg
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;

@ -0,0 +1,50 @@
// general
$primary: #101f25;
$secondary: #27ac8d;
$tertiary: #e39a54;
$additional-font: #a1ded1;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: $additional-font;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #1a323b; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $secondary; // top border on hover
$header-icon-color-hover: $secondary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: $secondary; // button border and font color && hover bg color
$btn-copy-color: $secondary; // btn copy
$btn-qr-color: $secondary; // btn qr-code
//links & tile
.tile a { color: $secondary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $secondary;
} // tab active bg
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;

@ -1,8 +1,51 @@
$primary: #559387;
$secondary: #add7cf;
$tertiary: #38533d;
// general
$primary: #093731;
$secondary: #40bfb2;
$tertiary: #25c9ff;
$additional-font: #93e8dd;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #fff;
$footer-text-color: #93e8dd;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #0e534a; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $secondary; // top border on hover
$header-icon-color-hover: $secondary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: #1c9f90; // button border and font color && hover bg color
$btn-copy-color: #1c9f90; // btn copy
$btn-qr-color: #1c9f90; // btn qr-code
//links & tile
.tile a { color: $secondary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $secondary;
} // tab active bg
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;

@ -145,11 +145,11 @@ export const elements = {
},
'[data-async-listing] [data-next-page-button]': {
render ($el, state) {
if (state.requestError) return $el.hide()
if (!state.nextPagePath) return $el.hide()
if (state.loading) return $el.hide()
if (state.requestError || !state.nextPagePath || state.loading) {
return $el.attr('disabled', 'disabled')
}
$el.show()
$el.attr('disabled', false)
$el.attr('href', state.nextPagePath)
}
},

@ -42,8 +42,8 @@ export default function (container, newElements, { key, horizontal } = {}) {
// update kept items
currentList = currentList.map(({ el }, i) => ({
id: overlap[i].id,
el: el.outerHTML === overlap[i].el.outerHTML ? el : morph(el, overlap[i].el)
id: overlap[i] && overlap[i].id,
el: el.outerHTML === overlap[i] && overlap[i].el && overlap[i].el.outerHTML ? el : morph(el, overlap[i].el)
}))
// add new items

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

@ -1,40 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 532.5 106" style="enable-background:new 0 0 532.5 106;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<title>ethereum-logo</title>
<g>
<path class="st0" d="M121.6,73.1c-2.9,0-5.6-0.7-7.9-2.2c-2.4-1.4-4.2-3.4-5.5-6c-1.3-2.6-2-5.5-2-8.6v-1.4c0-3.3,0.6-6.3,1.9-8.9
c1.3-2.6,3.1-4.7,5.3-6.2s4.8-2.3,7.4-2.3c4.2,0,7.5,1.4,9.9,4.3c2.4,2.8,3.7,6.7,3.7,11.7v2.1H110v0.7c0,3.9,1.1,7.1,3.3,9.7
c2.2,2.6,5,3.9,8.4,3.9c2,0,3.8-0.4,5.4-1.1c1.6-0.7,3-1.9,4.2-3.6l2.4,1.8C131,71,126.9,73.1,121.6,73.1z M120.9,40.7
c-2.9,0-5.3,1-7.2,3.1c-2,2.1-3.1,4.9-3.6,8.4h20.6v-0.4c-0.1-3.3-1-6-2.8-8.1C126.1,41.7,123.8,40.7,120.9,40.7z"/>
<path class="st0" d="M164.6,29.3v8.8h7.1v3.1h-7.1v22.9c0,1.9,0.3,3.3,1,4.3c0.7,0.9,1.8,1.4,3.4,1.4c0.6,0,1.7-0.1,3.1-0.3
l0.2,3.1c-1,0.4-2.3,0.5-4.1,0.5c-2.6,0-4.5-0.8-5.7-2.3c-1.2-1.5-1.8-3.7-1.8-6.7V41.2h-6.3v-3.1h6.3v-8.8H164.6z"/>
<path class="st0" d="M200.2,43.9c1.2-2.1,2.8-3.6,4.8-4.8c1.9-1.1,4.1-1.7,6.4-1.7c3.7,0,6.4,1,8.2,3.1c1.8,2.1,2.7,5.2,2.7,9.3
v22.5h-3.8V49.9c0-3.1-0.7-5.4-2-6.9c-1.3-1.5-3.3-2.3-6.1-2.3c-2.3,0-4.4,0.7-6.2,2.2c-1.8,1.5-3.1,3.5-4,6v23.5h-3.8V23.7h3.8
V43.9z"/>
<path class="st0" d="M262.3,73.1c-2.9,0-5.6-0.7-7.9-2.2c-2.4-1.4-4.2-3.4-5.5-6c-1.3-2.6-2-5.5-2-8.6v-1.4c0-3.3,0.6-6.3,1.9-8.9
c1.3-2.6,3.1-4.7,5.3-6.2s4.8-2.3,7.4-2.3c4.2,0,7.5,1.4,9.9,4.3c2.4,2.8,3.7,6.7,3.7,11.7v2.1h-24.5v0.7c0,3.9,1.1,7.1,3.3,9.7
c2.2,2.6,5,3.9,8.4,3.9c2,0,3.8-0.4,5.4-1.1c1.6-0.7,3-1.9,4.2-3.6l2.4,1.8C271.6,71,267.6,73.1,262.3,73.1z M261.6,40.7
c-2.9,0-5.3,1-7.2,3.1c-2,2.1-3.1,4.9-3.6,8.4h20.6v-0.4c-0.1-3.3-1-6-2.8-8.1C266.8,41.7,264.4,40.7,261.6,40.7z"/>
<path class="st0" d="M315.2,41.3c-0.8-0.1-1.7-0.2-2.6-0.2c-2.4,0-4.4,0.7-6,2s-2.8,3.2-3.5,5.8v23.6h-3.8V38.1h3.7l0.1,5.5
c2-4.1,5.2-6.1,9.7-6.1c1.1,0,1.9,0.1,2.5,0.4L315.2,41.3z"/>
<path class="st0" d="M350.8,73.1c-2.9,0-5.6-0.7-7.9-2.2c-2.4-1.4-4.2-3.4-5.5-6c-1.3-2.6-2-5.5-2-8.6v-1.4c0-3.3,0.6-6.3,1.9-8.9
c1.3-2.6,3.1-4.7,5.3-6.2s4.8-2.3,7.4-2.3c4.2,0,7.5,1.4,9.9,4.3c2.4,2.8,3.7,6.7,3.7,11.7v2.1h-24.5v0.7c0,3.9,1.1,7.1,3.3,9.7
c2.2,2.6,5,3.9,8.4,3.9c2,0,3.8-0.4,5.4-1.1c1.6-0.7,3-1.9,4.2-3.6l2.4,1.8C360.1,71,356.1,73.1,350.8,73.1z M350.1,40.7
c-2.9,0-5.3,1-7.2,3.1s-3.1,4.9-3.6,8.4h20.6v-0.4c-0.1-3.3-1-6-2.8-8.1C355.3,41.7,353,40.7,350.1,40.7z"/>
<path class="st0" d="M410,68.1c-2.3,3.3-5.9,5-10.9,5c-3.7,0-6.4-1.1-8.3-3.2s-2.9-5.3-2.9-9.4V38.1h3.8v21.9
c0,6.5,2.6,9.8,7.9,9.8c5.5,0,9-2.3,10.4-6.8V38.1h3.8v34.3H410L410,68.1z"/>
<path class="st0" d="M443.9,38.1l0.1,5.6c1.3-2.1,2.9-3.6,4.8-4.7c1.9-1,4-1.6,6.3-1.6c5.4,0,8.9,2.2,10.3,6.7
c1.2-2.1,2.9-3.8,4.9-4.9c2.1-1.2,4.3-1.7,6.8-1.7c7.4,0,11.1,4,11.3,12.1v22.9h-3.8V49.8c0-3.1-0.7-5.3-2-6.8
c-1.3-1.5-3.4-2.2-6.4-2.2c-2.7,0-5,0.9-6.9,2.7c-1.9,1.7-2.9,3.8-3.1,6.3v22.7h-3.8V49.5c0-2.9-0.7-5.1-2.1-6.6
c-1.4-1.4-3.5-2.2-6.3-2.2c-2.4,0-4.4,0.7-6.2,2c-1.7,1.4-3,3.4-3.8,6.1v23.5h-3.8V38.1H443.9z"/>
</g>
<path class="st0" d="M57.5,17.7l21.7,36c-7,4.2-13.9,8.3-20.9,12.3c-0.6,0.2-1.3,0.2-1.8-0.1c-6.9-4-13.7-8-20.7-12.2
C43.1,41.7,50.2,29.8,57.5,17.7z"/>
<path class="st0" d="M78.1,58.9L57.2,88.3L36.3,58.9l0.4-0.4c1.7,1,3.4,2,5.1,3c4.5,2.6,9,5.2,13.4,7.9c1.2,0.9,2.9,1,4.1,0
c5.4-3.3,10.9-6.5,16.4-9.7c0.7-0.4,1.4-0.8,2.2-1.2L78.1,58.9z"/>
</svg>
<svg data-name="-e-eth_logo_top" xmlns="http://www.w3.org/2000/svg" width="106.094" height="30"><g data-name="1" fill-rule="evenodd"><path data-name="Фигура 1" d="M9 11.2l-9 4.4L9 0v11.2z" fill="#828083"/><path data-name="Фигура 1 копия" d="M9 10.783L0 15.2l9 5.215v-9.632z" fill="#353336"/><path data-name="Фигура 1 копия 2" d="M9 22.568l-9-5.78L9 30v-7.432z" fill="#848285"/><path data-name="Фигура 1 копия 3" d="M9 11.2l9 4.4L9 0v11.2z" fill="#2f2d30"/><path data-name="Фигура 1 копия 3" d="M9 10.783l9 4.412-9 5.215v-9.627z" fill="#121212"/><path data-name="Фигура 1 копия 3" d="M9 22.568l9-5.78L9 30v-7.432z" fill="#302e31"/></g><path d="M29.675 13.329a4.417 4.417 0 0 0 .012 5.856 3.867 3.867 0 0 0 6.084-.5.332.332 0 0 0-.289-.5.351.351 0 0 0-.289.165 3.239 3.239 0 0 1-2.77 1.395 2.9 2.9 0 0 1-2.168-.922 3.555 3.555 0 0 1-1.012-2.2h6.719a.309.309 0 0 0 .361-.338 4.287 4.287 0 0 0-1.116-2.943 3.683 3.683 0 0 0-5.532-.013zm.58.377a2.994 2.994 0 0 1 4.336 0 3.6 3.6 0 0 1 1.012 2.215h-6.36a3.6 3.6 0 0 1 1.012-2.215zm11.2-4.046a.336.336 0 1 0-.672 0v2.613h-1.728a.35.35 0 0 0 0 .7h1.728v7.01a.336.336 0 0 0 .672 0v-7.01h1.8a.35.35 0 0 0 0-.7h-1.8V9.66zm5.664 4.173V5.889a.336.336 0 1 0-.672 0v14.04a.336.336 0 0 0 .672 0v-3.492a3.921 3.921 0 0 1 .6-2.512 2.52 2.52 0 0 1 2.222-1.124 2.113 2.113 0 0 1 1.792.909 3.075 3.075 0 0 1 .621 1.962v4.258a.336.336 0 0 0 .672 0v-4.273a3.766 3.766 0 0 0-.816-2.448 2.755 2.755 0 0 0-2.28-1.1 3.047 3.047 0 0 0-2.808 1.728zm10.08-.5a4.417 4.417 0 0 0 .012 5.856 3.867 3.867 0 0 0 6.084-.5.332.332 0 0 0-.289-.5.35.35 0 0 0-.289.165 3.24 3.24 0 0 1-2.771 1.395 2.9 2.9 0 0 1-2.167-.922 3.549 3.549 0 0 1-1.012-2.2h6.719a.309.309 0 0 0 .361-.338 4.287 4.287 0 0 0-1.116-2.943 3.683 3.683 0 0 0-5.531-.017zm.58.377a2.994 2.994 0 0 1 4.336 0 3.6 3.6 0 0 1 1.012 2.215h-6.36a3.592 3.592 0 0 1 1.016-2.219zm11.108-.888a4.025 4.025 0 0 0-1.176 1.255V12.6a.336.336 0 0 0-.672 0v7.3a.336.336 0 0 0 .672 0v-3.2a4.148 4.148 0 0 1 .7-2.464 2.951 2.951 0 0 1 2.16-1.292.329.329 0 0 0 .312-.359.3.3 0 0 0-.36-.311 2.919 2.919 0 0 0-1.632.545zm5.16.511a4.417 4.417 0 0 0 .012 5.856 3.867 3.867 0 0 0 6.084-.5.332.332 0 0 0-.289-.5.353.353 0 0 0-.29.165 3.237 3.237 0 0 1-2.77 1.395 2.9 2.9 0 0 1-2.167-.922 3.549 3.549 0 0 1-1.012-2.2h6.719a.309.309 0 0 0 .361-.338 4.287 4.287 0 0 0-1.116-2.943 3.683 3.683 0 0 0-5.528-.017zm.58.377a2.994 2.994 0 0 1 4.336 0 3.6 3.6 0 0 1 1.012 2.215h-6.36a3.592 3.592 0 0 1 1.016-2.219zm15.044-1.1v2.736q0 4.44-2.785 4.44a2.144 2.144 0 0 1-1.823-.912 3.159 3.159 0 0 1-.6-1.968v-4.3a.336.336 0 1 0-.672 0v4.308a3.779 3.779 0 0 0 .817 2.455 2.747 2.747 0 0 0 2.279 1.107 2.983 2.983 0 0 0 2.785-1.9v1.392a.336.336 0 1 0 .672 0V12.61a.336.336 0 1 0-.672 0zm10.295 1.632a2.8 2.8 0 0 0-2.856-2.136 3.052 3.052 0 0 0-2.808 1.7V12.6a.336.336 0 0 0-.672 0v7.33a.336.336 0 0 0 .672 0v-3.4a4.571 4.571 0 0 1 .6-2.679 2.529 2.529 0 0 1 2.208-1.053 2.146 2.146 0 0 1 1.8.885 3.067 3.067 0 0 1 .624 1.962v4.285a.336.336 0 0 0 .672 0v-3.3a5.018 5.018 0 0 1 .624-2.56 2.4 2.4 0 0 1 2.16-1.268 2.106 2.106 0 0 1 1.8.885 3.067 3.067 0 0 1 .624 1.962v4.281a.336.336 0 0 0 .672 0v-4.3a3.84 3.84 0 0 0-.84-2.484 2.746 2.746 0 0 0-2.256-1.044 3.142 3.142 0 0 0-3.024 2.136z" fill="#1b1635" fill-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="20"><path data-name="-e-logo_top" d="M13.82 10.054h-6.9v2.731h3.191l-.011 3.432a1.456 1.456 0 0 1-.43.319 4 4 0 0 1-.655.267 5.306 5.306 0 0 1-.795.182 5.647 5.647 0 0 1-.861.065 3.012 3.012 0 0 1-2.715-1.424 7.745 7.745 0 0 1-.9-4.063v-2.6a9.439 9.439 0 0 1 .265-2.36 5.76 5.76 0 0 1 .715-1.71 3.229 3.229 0 0 1 1.059-1.047 2.57 2.57 0 0 1 1.324-.357 2.922 2.922 0 0 1 2.191.735 3.762 3.762 0 0 1 .894 2.191h3.628a8.468 8.468 0 0 0-.616-2.458A5.315 5.315 0 0 0 11.9 2.1 5.626 5.626 0 0 0 9.854.936a9.017 9.017 0 0 0-2.84-.4 6.711 6.711 0 0 0-2.774.572 6.354 6.354 0 0 0-2.225 1.664A7.926 7.926 0 0 0 .532 5.431 10.952 10.952 0 0 0 0 8.988v2.575a11.473 11.473 0 0 0 .51 3.556 7.5 7.5 0 0 0 1.45 2.646 6.25 6.25 0 0 0 2.264 1.651 7.406 7.406 0 0 0 2.966.572 11.15 11.15 0 0 0 2.278-.221 10.5 10.5 0 0 0 1.913-.579 7.641 7.641 0 0 0 1.477-.8 5.159 5.159 0 0 0 .98-.871zm2.661 2.783a8.686 8.686 0 0 0 .451 2.854 6.513 6.513 0 0 0 1.317 2.269 5.984 5.984 0 0 0 2.132 1.5 7.277 7.277 0 0 0 2.88.54 7.194 7.194 0 0 0 2.86-.54 5.934 5.934 0 0 0 2.119-1.5 6.6 6.6 0 0 0 1.311-2.269 8.713 8.713 0 0 0 .45-2.854v-.274a8.673 8.673 0 0 0-.45-2.841 6.532 6.532 0 0 0-1.318-2.269 6.078 6.078 0 0 0-2.125-1.508 7.813 7.813 0 0 0-5.74 0 6.082 6.082 0 0 0-2.119 1.508 6.515 6.515 0 0 0-1.317 2.269 8.647 8.647 0 0 0-.451 2.841v.273zm3.681-.273a7.394 7.394 0 0 1 .173-1.625 4.223 4.223 0 0 1 .542-1.352 2.633 2.633 0 0 1 2.357-1.261 2.777 2.777 0 0 1 1.417.338 2.693 2.693 0 0 1 .947.923 4.31 4.31 0 0 1 .536 1.352 7.394 7.394 0 0 1 .173 1.625v.273a7.606 7.606 0 0 1-.173 1.658 4.227 4.227 0 0 1-.536 1.352 2.621 2.621 0 0 1-2.337 1.255 2.818 2.818 0 0 1-1.424-.338 2.758 2.758 0 0 1-.96-.917 4.143 4.143 0 0 1-.542-1.352 7.606 7.606 0 0 1-.173-1.658v-.274zm-1.747-10.3a1.492 1.492 0 0 0 .37.514 1.761 1.761 0 0 0 .57.338 2.207 2.207 0 0 0 1.456 0 1.761 1.761 0 0 0 .57-.338 1.492 1.492 0 0 0 .37-.514 1.593 1.593 0 0 0 0-1.274 1.562 1.562 0 0 0-.37-.52 1.7 1.7 0 0 0-.57-.344 2.206 2.206 0 0 0-1.456 0 1.7 1.7 0 0 0-.57.345 1.562 1.562 0 0 0-.37.52 1.593 1.593 0 0 0 0 1.274zm6.356.013a1.558 1.558 0 0 0 .37.52 1.7 1.7 0 0 0 .57.345 2.207 2.207 0 0 0 1.456 0 1.7 1.7 0 0 0 .57-.345 1.558 1.558 0 0 0 .37-.52 1.593 1.593 0 0 0 .133-.65 1.562 1.562 0 0 0-.133-.637 1.492 1.492 0 0 0-.37-.514 1.762 1.762 0 0 0-.57-.338 2.206 2.206 0 0 0-1.456 0 1.762 1.762 0 0 0-.57.338 1.492 1.492 0 0 0-.37.514 1.546 1.546 0 0 0-.133.637 1.576 1.576 0 0 0 .133.651z" fill="#2b2b2b" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@ -1,467 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
]>
<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 381 106"
style="enable-background:new 0 0 381 106;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{enable-background:new ;}
</style>
<switch>
<foreignObject requiredExtensions="&ns_ai;" x="0" y="0" width="1" height="1">
<i:pgfRef xlink:href="#adobe_illustrator_pgf">
</i:pgfRef>
</foreignObject>
<g i:extraneous="self">
<g>
<path class="st0" d="M79.1,73.9c2.5,2.4,4.7,4.3,6.8,6.4c0.5,0.7,0.8,1.4,1,2.2c-0.7,0.3-1.4,0.6-2.1,0.7c-12.3,0-24.7,0-37,0
c-0.8-0.2-1.6-0.4-2.3-0.9c0.3-0.8,0.7-1.5,1.2-2.2c2.1-2.1,4.3-4,6.2-5.8c-3.3-1.2-6.6-2.1-9.6-3.7c-3.8-2-5.7-5.4-5.7-10
c0.1-10.1,0.2-20.1,0-30.2c-0.1-5.7,2.5-9.5,7.3-11.7c2.6-1.2,5.4-1.9,8.2-2c8.8-0.2,17.6-0.4,26.3,0.1c3.5,0.3,6.9,1.4,10,3.1
c3.7,1.9,5.4,5.4,5.4,9.8c-0.1,9.8,0,19.5,0,29.3c0,7.8-3.5,12.2-11.2,14C82.3,73.4,80.9,73.6,79.1,73.9z M89.7,45V26.5H68.8V45
H89.7z M63.6,45V26.5H44V45L63.6,45z M54.2,59.5c0-3.2-2.6-5.8-5.8-5.8c-3.1,0-5.7,2.4-5.8,5.5c0.1,3.2,2.6,5.8,5.8,5.9
C51.5,65,54,62.6,54.2,59.5z M84,65.2c3.1-0.1,5.6-2.6,5.8-5.6c0.1-3.2-2.4-5.9-5.6-6c-3.2-0.1-5.9,2.4-6,5.6c0,0.1,0,0.3,0,0.4
C78.4,62.6,80.9,65,84,65.2z"/>
<g class="st1">
<path class="st0" d="M140.3,56.8l-3.6,3.8v11.8h-5.7V24.7h5.7v28.8l3.1-3.7l10.4-11h7l-13,14l14.6,19.5H152L140.3,56.8z"/>
</g>
<g class="st1">
<path class="st0" d="M175.7,55.2c0-3.3,0.6-6.2,1.9-8.9c1.3-2.6,3.1-4.6,5.4-6.1c2.3-1.4,4.9-2.1,7.9-2.1
c4.6,0,8.3,1.6,11.1,4.7c2.8,3.2,4.2,7.4,4.2,12.6v0.4c0,3.3-0.6,6.2-1.9,8.8c-1.2,2.6-3,4.6-5.4,6.1c-2.3,1.4-5,2.2-8,2.2
c-4.5,0-8.2-1.6-11-4.7c-2.8-3.2-4.2-7.3-4.2-12.6V55.2z M181.4,55.9c0,3.7,0.9,6.7,2.6,9c1.7,2.3,4,3.4,6.9,3.4
c2.9,0,5.2-1.1,6.9-3.4c1.7-2.3,2.6-5.5,2.6-9.6c0-3.7-0.9-6.7-2.6-8.9s-4.1-3.4-7-3.4c-2.8,0-5.1,1.1-6.8,3.4
C182.3,48.5,181.4,51.7,181.4,55.9z"/>
<path class="st0" d="M239.7,64.5l8.3-25.8h5.9l-12,33.5h-4.4l-12.1-33.5h5.9L239.7,64.5z"/>
</g>
<g class="st1">
<path class="st0" d="M294.7,72.3c-0.3-0.7-0.6-1.8-0.8-3.5c-2.7,2.8-5.8,4.2-9.5,4.2c-3.3,0-6-0.9-8.1-2.8
c-2.1-1.9-3.2-4.2-3.2-7.1c0-3.5,1.3-6.2,4-8.1c2.7-1.9,6.4-2.9,11.2-2.9h5.6v-2.6c0-2-0.6-3.6-1.8-4.8c-1.2-1.2-3-1.8-5.3-1.8
c-2,0-3.8,0.5-5.1,1.5c-1.4,1-2.1,2.3-2.1,3.8h-5.8c0-1.7,0.6-3.3,1.8-4.9c1.2-1.6,2.8-2.8,4.8-3.7c2-0.9,4.3-1.4,6.7-1.4
c3.9,0,6.9,1,9.1,2.9c2.2,1.9,3.3,4.6,3.4,8v15.4c0,3.1,0.4,5.5,1.2,7.3v0.5H294.7z M285.2,67.9c1.8,0,3.5-0.5,5.1-1.4
c1.6-0.9,2.8-2.1,3.5-3.6V56h-4.5c-7,0-10.5,2.1-10.5,6.2c0,1.8,0.6,3.2,1.8,4.2C281.8,67.4,283.3,67.9,285.2,67.9z"/>
<path class="st0" d="M330.2,38.8l0.2,4.2c2.6-3.2,5.9-4.8,10-4.8c7.1,0,10.7,4,10.7,12v22.2h-5.7V50.1c0-2.4-0.6-4.2-1.7-5.4
c-1.1-1.2-2.8-1.7-5.1-1.7c-1.9,0-3.5,0.5-4.9,1.5c-1.4,1-2.5,2.3-3.3,3.9v23.9h-5.7V38.8H330.2z"/>
</g>
</g>
</g>
</switch>
<i:pgf id="adobe_illustrator_pgf">
<![CDATA[
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
]]>
<![CDATA[
t2W+5VKbF/mPWJLf34xlcisXkXgstfW1EUue3Cux9EcbXr28ZWOp0dplLH18W4plmGOOyW3eJUj3
YqyYPBcG3OAYBlf6ErZPX7b4gszL+fv89/1G5qXSk37xTNN6y+zXWsVIXFW3Nhu76f7J4c6RMtiS
9zd+ZSu9e+GmrD7eM6X7yt1VZXN385Vd3ZW6ei/80mRTA4xpk1NVIZa+eT6IZeSMHEu9Zi9xVjI+
K8fStaYYS7a/OrHksNDGqSXpqQnpC/ytAAN53CXT2FL2lz6tCUXiZEqD2NNKiVvZWig5GmVzA3mP
217cf4Y/9zpMc/muZEyjOlDV9cGN+tiRj5iccKkh1cITfBm/5XfOEwnopbnMEkycWnRTn4qrO1m+
Ko9SW3uxZYsQpFOhd3HZ9er0WX2qfVw6OjXmIu9tvog/q33GtdPn/P2ZV6f7i51G7t69043Yw2Dx
5u4MenGd6/nmytZa8eHQrdPU+quw4dFpfnHx5v5EdHSKvZBuhbt7plLIn7p2ulD5lJe6/PqZW6dM
5e1137PTZU64KxOpdJmrcNdk9vbUO/eZVn6uueJVA2kq9MZouvK9pnd6trJCOiW96FTl1ZvcB+kU
WLJRtlP1QX0q3Zxhp8lxVhKehGH2OuPeaX//MBJ3dGt1mj9h1he9On1Vn2X21r3Tk/Lq4k9+dGx1
Golb3Q4W+4WKV6f721yXvXfvVEjepdY71yeunS5U6mIk7uiWpurRecGj0/xiXJTFbY9O72pMpXd1
ZXUKc6G63VvaXK62Pq5dO907l288Z7qciWV1mpYfvyo2oVlIRuKDlZ30ALtdHZvrfu3bkFSp7+y0
enDypHd6l0k4ZiqJ2ey91SnwGD3X+wJT/T6X3Ds9WBjJ1btX2bXT005r37PTSPwo+9NPu89VeEgx
l9WfkXunR/xztVLZjrl2enXQPrA6BbrYu708zl+9eHVaYm6YZ8W902pm8apZW1136xQ0zM3z5sBz
rjeJVq3v1ekx8yuzXfDotJz6tSOrRdJpJO6c63366tmz08+Fq2rBo9PHPPNUf0m5dQo8tnBy3f5a
i5+kXRH8/Hxb8+y019pOvHt1esy8lKsl0inymFNWr9mF2+H5gVunqnqSWdQ7bfBJh9CklNUyr3Va
XxjuWZ2id7ERW1NHfJHBbtNjnZ5uJn6ey7c70Omm6rQ0a727tN7pl7Lq6DT+9rDwRjqNxLnCHXtg
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
]]>
<![CDATA[
STwSZ/bEIXq6aXuaZA/RUrbv7pihNM3bslFVaaHqwORhkDsxQR3f82iiihOfOj6b5+Vax7dKJ628
S9NankUwTlc6YA/8nt8e+NMLM7McQD+9ji9oD3z4Oj7XHeJ0zfsEdXyODGYQM5AdEd7AAgpswo6L
xMg33mvmE08y8JSASYB5r15MgbGA8pvJMMbPAsye+NWOl7RtdCLVTwHVM6F82X1nzne8YsgS9nD1
cj7awgMA0iUo2CPSzQZq5/d9t2DPZR9siGBvuB1Q/2H5zhYAe8XQcHt5chA2AFsDxuVoFHv0alLa
CydBhXIeFKI82P2xlRGfMMyz1s5VXO2yH4iO0PkFr9x4UJXcmHnz8FxwQoJjQmN7R+3hld9W/kRJ
dVbFPg3eh24op2qs7H6kByeD6ZwobZGkvL6AArkAreNdEeXcQTS1P/Z54CnxlqhHQkk84Cm0uLrt
Q7J47PNgsvSOT+WYfRUHWMAZV4ZkgeDKONuQzBNBXQc1UUbGZ0i4I2I+/OSXkTHP7Ao3qMkyMo4o
yZ7/3Rw6MzJYkjRLRsbise/DmTMy/NJaYsktjqM1TMiw4XDyjIxnvP99OHNGBqYmJLx3d4QvQwuZ
kfE7T4mUoc2akcEiNN5RkTpFRuYwREYmEq4+zzsjE6o4x/BhEDsTlef47pLIOZxlo8YqoA41lLN8
5LlBYpKaxLXzACJ6xgZje6747WspROloiHPDjqyds157ekNNLRmWPzE/5s6hRyG3LgSVj+HWhRDV
goF1dcFKNhKiri5M/aiv4JLKR5+0W5gNIhR2vFKgdk72kl/HVj3QkSvOdVR45s0M1M6u4MWHqevh
7LGYURE373q4Wc8fC1cPF8Rj86mH007Sc1bETQ7Hvx4u/A7VWerhKD+Zqoibdz1c4Imgc6mH89kN
Zbiac6iHo28ychHDOdXDaXvgnRVx866H86jinHM9nH8s5rWss3fTm0NlPRq4gL3kofdEAig2nG8Z
Yk8kAOPmIPuA78sQK1aubgC1E/J6Hu4EgTK2M3jyFV4Cxx48B47GLQ9D4MxcY0+g6EJI2UpqkWai
Hc+eZwC77YEPteMZHPGtVacYlh+L/gjU9vWFEMO7mQ6FNfKWbytBp6aE35q88uOUnGA95rk1eeUn
dDmptzdedNvaMDGj3cznNGACJ+hsmRDRK4EzoRi6WrGbuYjhjact9D5Ny3Ob9c3YkcBBp6GlfE9r
hPmN7SrCZxMH1B4VqfWFC88DjMMi8Nc8K1J/zbMi9dd8KlIff+ZQkcouZOZSkQpw5lKRinBmr0hF
KPOoSMXqteBjoB37+jzrt0BAfA5NDbXJyH5jDiiIcTGsqTPntTQNQxXDzbyjx60UjrZiYXb02CcZ
NmwPPgt6HqVwllTqxXB/pRRu6rhyolI47zOI5lkKp+2ICCiPnLkUjpyh+uxvS0LGZ42Bp2IiHiyl
DMIVPtk3SASfCG/eleZCX+fRwlMfqKZh7Md1AWjiBDKOa+jq303hw9w5DxkOXlzwrEbHIrYQSzh+
p/OiKs8Rk+dV9xpc3OwYkuOkbztHULug/fegWg57gZzs4dIffS164mJJiqU/Pi/xUvRqJI4XiNdi
q0frbCxduviFF4hf4gXiV7HVq908/naGLYuxzFFNZHK3X5JujDZ7X/SQjYyT/bo4rRaLiittxW5n
OYbGsq3ubLCy1KMvT7UXuyUaSxdfXhV2QvLRr9jtOePZKblU26PT/CIpi/KusHv2K3aLid6d4qXa
Zqf8+H183nVnG7Enn0vUzncuqE4d18XhVdOeFXbix+rOr9W+VwnYnV+x2zvj6NR+H9/TvneFXfwr
d9Pw6rTu0+kes+Z7H9/74aJnp7HHxfy1F3rTfhV2C5WDZQdVUVwzpHvym1GJN2qGane62LLv6fVq
uXC6GQsBUR3VvuiDuHHOliNq5scM0YWv0wmHQfXLHQdvuR3zYM+Wv50b5Z0Z1alKe7R7rPqeiSf3
rIn3PVY7rkc1e+658i7tCbyjZXzxyy3XN9tNcvYhjRw77ed1k5wb6UJm4c5WFmaphrQyvQ+l4BtH
bPv6fK4yc14hF5yFm+ASOc/5Bd/7FnTZSJj5uZ2lNnUJaph7RsIiPeAmhvDywrxVhcdQeKJznt4X
0JkR39yq6dzCiwnzMCGq6dziANcs3EzVdG61dMHnw0xaTeeWE4zE511N51ZLh/Iy32o6N86JzL2a
zjNrPddqOreNJJOcEBKumi5oj+J8qunc1mnc115nqaaz01SrpfNeGZm2ms597XXe1XTeNSPzrKYL
ec7VjNV01MZ7s5bOdVV0pmo6N2MUsSUJ51FN5zYkarV6TtV0brV0LjfmzFhN50Y/80zIuVXTuYHS
V3jnWE3nVkvnUjMyYzXdtBibrJouAGNzqqZzq6WbEGMhquncauk8aqxmqKZz8zydtdWzV9O5KRz7
vQnzqKZzWy0hceVcq+nsAJaDotcpq+nc6Oy5MjJ1NR1NIWNpxce+TFlN5x5XeqJjymo6ChmmK+ld
yTVtNZ3bhKgziLycUhzUjAEgWd9fG4wV7yRKgS6GX4GYMYbPAxIA2k5rnLbwKVBb2L2LedxXF+Bd
zOm+ui2X2+rcvItweAq82ZZiUpJR9L4XLrAYPhwL4JnDQTfRroYj3Ye3sXXdae93u1zQFbSuQxrb
3YGDCiPOoYZkRJghNYwPnvLhNYxnRMQvKV85e0R06IyIxncfOZNgHrdl2S+6m7JmzcoXe+2HCemS
h7zmLhImYzzzNXckdxF00V3IQro5nJ490zV3dBWn50V34cuUPK65mzCjOOU1d64ZRedFdxPWKo1f
czd2ErjbRXdTbPYAu0DdxT7tOVdHc6yz6B/N57RupMva+cy1PEf+ezHMnZCBhXRuew8n3GuNNJ/5
ipwjz72/zp0qgRfUeW/iCFuVRu6mC9jeFm4TGeJGCsXJnjds2RZAkonxQBkr8WyGjo7FJlrvwdR8
6MIun93pMFDBPyM+wW4o4vPPZzcUqf2fmccA32E2QoWofJzDUgiBYnNYXagfEs4kJs9zZxfCmUoC
x6BACBtcKRzi0nQCzPtswRA3sDsLaz9bibHC2s9W4FpS+MKvz1aoK39d/LvxHd0AbDWUMqNslycq
L7sElZPd9+q3tATe2vgO6hvt0Fv/WzLDpP6KYztHpqtMuZ7nDYbX87vB8NpRyDCl7N/0JvLfvSsf
U7O4ExYU312dk8CZ/ZQADc50t1Xb4heE47NlaLK9qiAgLoUMM6zwgu81LobwzKWQYYoM/BQ33LnW
V97MLIYUqPndWx10w104b3zWG+6oykfXO+4mrLzxuOFuqpvyJq4n8rgpb1YxdNxw53s+f4j6kHA3
3EW8gTkLa6e64S7sqeZ7jz8zF3bhKc3sQsCJFuELa9kF17iRPnswfGEtuzDZLemelY+tELUXgZWP
RnX7LOdcETihsln+e64InNkKawkUYitnL6z95Xsu3A7ayknq28c214S6Lo/2YZxlTOOba7B+69rf
gLnmtdzvffMRwwmLmG7JSpOnFXMvY/IrUmt4J+/08/rCBu4A7CPEdkFn2O4ulQDsK4RUhihiuiWx
+3ziyprqH8A740oPm7SWyPrsZQx0DB1ZBRiUbxnTpI5hQ1tvdfQCT+dxdhvWpzWpA9KdN+VNWuNa
zHrvs7NUgeMceJ+KsFmOphrD2Nyue2wMrAVY39rqED5MMSuFsJohb8q7rYW/BdRrLYncSDe36x5h
SH5nd4SucbWkd0s87rr2p1OgOlBVbrgUietFeofKHVb3XeGPnVjqNXuIZX1FUtuX5avKkkm6ZQfG
9N9spWnqgI2rVqfIyfZ72Ba4NcW9Hm5jYdmzHk4dvWS9i/Cglw3u3XnnXMq6h83ldj2zSuzer/Lv
k7XHL47av7eTS89Ol9nD2qtXp03P0rRIfCCfFC6pudpL0waLHy2vejh5f+tn6ducqaMeLkkV4Zl3
pVEI3uQ8O2UqCnPi0Wl+cenim3t26zQSx7n6FBwuVAaCd6d76Zcbz05XWgnpw8pcOcvwsn6dVlc8
O1UH11sxt04jca32b+cpc2Wjaksxuie/6YRIFu+b32HaPY++u7SG8WiZX/x5Lt+eBkIUP3S+080k
lsg87jqcTmtHROJ7LKtSGaneJso0dCG2TWqRuMt60ENpLpcQlDDWqthXrIK2DPlcQGfzed1uMQs7
qLAbMccXumjND3Sr+J/HE9bTLTnSuS43s4TOJD2UAi9BsXZC+uNpkq1VAVVpq57h1WRVaV47NB3n
9Ibipwl3aXnu7cH5Be5JD1t1B363r7yEr7oL2M0WmWBQ3gfeTCgv6z630mujGd8baw+tXQ7DJDd/
zSOUKPsfRxsyB3uXHs6S3LJhrPx4478VJuy6dXkuqzx3mcXZ82PleZzbiDWAhvROf641uVEvZEJT
y456VgEGHNgZrgYwdL1YUNRS9t2lFSo/Zt80wo6v7TS4H/85h9Uw9cr8YuQGvxCGECHq4OsLx5Sy
Gtt1M+FhV4Asn6PwjQSNVlkfLqvyJfed18o4E4we/oh2Ck1gdRt4bh5KP1QhmbWS2Nzz99wmKCST
Rw77MUuNVSPgnAMrXUa0pXd1m/c5ByG8cdpTGkt4TloKSNHPsZzoVr8fupQz8M6bMfp57e35ktXA
Qp3QzKCGuCstPDDPelXzfrFJgE3M8T4YC6zlmQRj8zpzBIB5rlxOgzGfgrSxcmHbCu+UVYBhvUP7
XWmTVgHapdK7BtDlVI0JqgDtY/CuAXTcjzxhFWDYGkBd83uGQF4gJrtRz2VdbIIqQA9VN1YD6HtH
amAVYLBp8dirMFEVoAc+x2oA/WqsPNEx8Y167jFy2CrAsDWAnjHy6bX7rKa6lG/KG9kmvJTPsyJ1
rpfyBWQV5nQpXyS80pjhUj6HHvtLl/Jp2dFpb8ALeymfkYX7u5fyIY/hoP7upXyT3185zaV8rlkF
HFTL9VJN4jtrowk6G4q+1Y++xWweZ0O53+o3cSWXx71+U5wNNcW9fp5Tm8PZUNa9frPsUwp/r59/
1d0czoYi9/rNfjZUmHv9QtVXznyvn4Udt1SGCydPda/flu+tfpF4CJfdxI73vX6TVXJNe6+fkyPs
t/o5d6pMe6+f/9R876+c4F4//1v9Zr4BRL/Xz39CkTnd6xe0Q3U+9/r5X4QViU+w58znXj9/6TW8
cWf50aT3+vkbOoc/NvW9frYtSmO3+s1wApXtXj//rVOROd3rF1zNMY97/fxv9ZvsPj7ve/0mu49v
2nv97FCct/p5nNQ68b1+3tvJtF7mc6+f/4KKpsdmv9fPtzyF7BufV5WY961+zrrXae/181+nQbs/
j3v9/Ddce1akTnivn1cVGLWaMGPdAwALUB6R8HUPLb97/cLL/iz3+pmM5nqr35T38U14iofnfXyz
1z1Qt/rNVM1x7Rl6O5aIQ+22DXGvn//GVrN+3xTD6e718z/Pw7qXZ7Z7/cySK9fCaA==
]]>
<![CDATA[
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
]]>
<![CDATA[
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
]]>
<![CDATA[
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
]]>
</i:pgf>
</svg>
<svg id="_-e-logo_top" data-name="-e-logo_top" xmlns="http://www.w3.org/2000/svg" width="81.281" height="26"><defs><style>.cls-1{fill:#1f857f;fill-rule:evenodd}</style></defs><path id="Forma_1" data-name="Forma 1" class="cls-1" d="M96 18c-6.05 0-11 .684-11 5.474v13a4.86 4.86 0 0 0 4.813 4.79l-2.063 2.052V44h16.5v-.684l-2.062-2.053A4.86 4.86 0 0 0 107 36.474v-13c0-4.79-4.95-5.474-11-5.474zm-8 5h7v7h-7v-7zm9 0h7v7h-7v-7zm-7 11a2 2 0 1 1-2 2 2 2 0 0 1 2-2zm12 0a2 2 0 1 1-2 2 2 2 0 0 1 2-2z" transform="translate(-85 -18)"/><path id="kovan" class="cls-1" d="M124.758 35.983L120.87 32.6l3.546-3.168a.717.717 0 0 0 .252-.54.676.676 0 0 0-.668-.667.672.672 0 0 0-.486.216l-4.3 3.942v-7.308a.683.683 0 0 0-.207-.531.732.732 0 0 0-.513-.189.757.757 0 0 0-.531.189.683.683 0 0 0-.207.531V36.5a.683.683 0 0 0 .207.531.757.757 0 0 0 .531.189.732.732 0 0 0 .513-.189.683.683 0 0 0 .207-.531v-3.541l4.7 4.05a.762.762 0 0 0 .486.216.611.611 0 0 0 .459-.2.655.655 0 0 0 .189-.468.788.788 0 0 0-.288-.576zm6.372 1.278a4.269 4.269 0 0 0 2.2-.558 3.7 3.7 0 0 0 1.467-1.593 5.885 5.885 0 0 0 0-4.806 3.7 3.7 0 0 0-1.467-1.593 4.271 4.271 0 0 0-2.2-.558 4.225 4.225 0 0 0-2.187.558 3.712 3.712 0 0 0-1.457 1.593 5.885 5.885 0 0 0 0 4.806 3.709 3.709 0 0 0 1.457 1.593 4.223 4.223 0 0 0 2.187.558zm0-1.206a2.4 2.4 0 0 1-1.989-.864 3.888 3.888 0 0 1-.693-2.484 3.859 3.859 0 0 1 .7-2.475 2.683 2.683 0 0 1 3.961 0 3.865 3.865 0 0 1 .7 2.475 3.887 3.887 0 0 1-.692 2.493 2.415 2.415 0 0 1-1.99.855zm13.464-7.416l-3.006 6.714-3.006-6.75a.689.689 0 0 0-.261-.306.65.65 0 0 0-.351-.108.824.824 0 0 0-.531.2.589.589 0 0 0-.243.468.534.534 0 0 0 .072.27l3.492 7.56a.966.966 0 0 0 .342.369.837.837 0 0 0 .45.135.867.867 0 0 0 .468-.135.841.841 0 0 0 .324-.369l3.51-7.56a.57.57 0 0 0 .072-.288.563.563 0 0 0-.216-.45.74.74 0 0 0-.486-.18.658.658 0 0 0-.63.432zm7.255-.486a6.343 6.343 0 0 0-1.593.207 5.783 5.783 0 0 0-1.432.567 1.794 1.794 0 0 0-.5.387.68.68 0 0 0-.153.441.6.6 0 0 0 .144.414.462.462 0 0 0 .36.162 1.635 1.635 0 0 0 .684-.306 5.291 5.291 0 0 1 2.485-.666 1.81 1.81 0 0 1 1.43.5 2.367 2.367 0 0 1 .441 1.584v.594h-.4a16.365 16.365 0 0 0-3.2.243 3.05 3.05 0 0 0-1.655.792 2.188 2.188 0 0 0-.5 1.539 2.356 2.356 0 0 0 .413 1.35 2.777 2.777 0 0 0 1.126.954 3.541 3.541 0 0 0 1.557.342 3.075 3.075 0 0 0 1.619-.423 2.574 2.574 0 0 0 1.044-1.2v.866a.68.68 0 0 0 .72.72.675.675 0 0 0 .513-.2.725.725 0 0 0 .19-.522v-4.9q0-3.456-3.294-3.456zm-.594 7.956a1.861 1.861 0 0 1-1.288-.459 1.49 1.49 0 0 1-.513-1.161 1.179 1.179 0 0 1 .352-.927 2.343 2.343 0 0 1 1.178-.45 16.125 16.125 0 0 1 2.412-.135h.324v.523a2.619 2.619 0 0 1-.693 1.881 2.338 2.338 0 0 1-1.772.729zm11.861-7.956a3.621 3.621 0 0 0-1.764.423 2.952 2.952 0 0 0-1.206 1.233v-.918a.7.7 0 0 0-.188-.5.679.679 0 0 0-.513-.2.731.731 0 0 0-.541.2.705.705 0 0 0-.2.522v7.6a.7.7 0 0 0 .2.531.751.751 0 0 0 .541.189.655.655 0 0 0 .719-.72v-4.4a2.739 2.739 0 0 1 .72-2 2.568 2.568 0 0 1 1.926-.738 1.9 1.9 0 0 1 1.522.558 2.723 2.723 0 0 1 .477 1.782V36.5a.7.7 0 0 0 .2.531.75.75 0 0 0 .54.189.657.657 0 0 0 .72-.72v-4.873q0-3.474-3.15-3.474z" transform="translate(-85 -18)"/></svg>

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -1 +1,3 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 784.802 295.795"><defs><style>.cls-1{fill:#fff;}</style></defs><title>poa_logo</title><path class="cls-1" d="M396.219,268.878c-67.974,3.629-128.341-52.06-131.534-121.338-3.13-67.91,51.1-129.093,117.646-132.732,73.163-4,132.938,49.141,137.089,121.875C523.353,205.623,467.972,265.048,396.219,268.878Z"/><path class="cls-1" d="M11.9,141.308c0-34.343.283-68.69-.17-103.027C11.59,27.8,15.167,23.995,25.764,24.09c44.441.4,88.889-.137,133.33.255,49.985.441,91.942,43.057,93.616,94.385,1.574,48.276-37.962,93.594-85.93,98.278a242.125,242.125,0,0,1-24.193,1.036c-7.854-.023-11.592,2.835-12.116,11.258-1.95,31.322-2.173,31.308-33.906,31.308q-33.333,0-66.666-.008c-17.414-.022-17.988-.582-18-17.477Q11.875,192.216,11.9,141.308Z"/><path class="cls-1" d="M633.094,260.608q-63.645,0-127.289-.025c-15.248-.026-18.476-5.46-10.744-18.3Q559.1,135.943,623.33,29.714c7.883-13.036,13.493-12.908,21.482.331q63.82,105.768,127.5,211.619c8.277,13.763,5.324,18.9-10.719,18.921Q697.345,260.685,633.094,260.608Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="18">
<path fill="#5C34A2" fill-rule="evenodd" d="M10.313 14.437h-.938v2.657h-.003l.003.015c0 .492-.42.891-.938.891h-7.5C.42 18 0 17.601 0 17.109l.003-.015H0V.937h.003L0 .922C0 .43.42.031.937.031h9.376c4.142 0 7.499 3.225 7.499 7.203 0 3.979-3.357 7.203-7.499 7.203zM29.062.031c5.178 0 9.375 4.023 9.375 8.985S34.24 18 29.062 18c-5.177 0-9.374-4.022-9.374-8.984S23.885.031 29.062.031zM60 17.43c0 .307-.26.556-.58.556H38.151c-.025.003-.047.014-.073.014a.57.57 0 0 1-.578-.562c0-.123.048-.23.116-.322l-.009-.018L48.165.449h.023a.566.566 0 0 1 .557-.444c.28 0 .502.192.557.444h.023L60 17.209l-.037.048a.51.51 0 0 1 .037.173z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 694 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

@ -0,0 +1,47 @@
<svg id="_-e-logo_top_rsk" data-name="-e-logo_top_rsk" xmlns="http://www.w3.org/2000/svg" width="76.406" height="40" viewBox="0 0 76.406 40">
<metadata><?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.6-c140 79.160451, 2017/05/06-01:08:21 ">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""/>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?></metadata>
<defs>
<style>
.cls-1 {
fill: #27aa8b;
}
.cls-1, .cls-2 {
fill-rule: evenodd;
}
.cls-2 {
fill: #27ac8d;
}
</style>
</defs>
<path id="Эллипс_1" data-name="Эллипс 1" class="cls-1" d="M103,11a4.03,4.03,0,1,1-3.952,4.03A3.991,3.991,0,0,1,103,11Zm0,31.944a4.028,4.028,0,1,1-3.954,4.028A3.992,3.992,0,0,1,103,42.944ZM88.955,19.056A4.028,4.028,0,1,1,85,23.083,3.992,3.992,0,0,1,88.955,19.056Zm0,15.833A4.028,4.028,0,1,1,85,38.917,3.992,3.992,0,0,1,88.955,34.889Zm28.091-15.833a4.028,4.028,0,1,1-3.954,4.028A3.991,3.991,0,0,1,117.045,19.056Zm0,15.833a4.028,4.028,0,1,1-3.954,4.028A3.991,3.991,0,0,1,117.045,34.889Zm-1.093-8.2h2.178v8.9h-2.178v-8.9Zm-28.082,0h2.178v8.9H87.87v-8.9Zm17.386-9.106,1.091-1.924,9.672,5.687-1.091,1.924Zm-4.3.067-1.092-1.931-9.679,5.707,1.092,1.931Zm-0.035,26.994-1.089,1.909-9.648-5.642L91.27,39Zm4.292-.067L106.3,46.5l9.656-5.662-1.09-1.916Zm-4.292-15.767-1.089,1.909L90.182,25.08l1.088-1.909Zm4.292-.067,1.089,1.916L115.955,25l-1.09-1.916Zm0.009,4.718,1.088-1.909,9.648,5.642-1.089,1.909Zm-4.293.067-1.089-1.916-9.655,5.662,1.089,1.916Zm0.978-16H104.1v8.882H101.9V17.529Zm0,16.941H104.1v8.9H101.9v-8.9ZM103,24.056s4.364,3.632,4.364,7.083S103,38.222,103,38.222s-4.364-3.632-4.364-7.083S103,24.056,103,24.056Zm0,2.639s2.727,2.279,2.727,4.444S103,35.583,103,35.583s-2.727-2.279-2.727-4.444S103,26.694,103,26.694Zm0,4.173a1.1,1.1,0,0,1,1.1,1.1v6.69a1.1,1.1,0,1,1-2.192,0v-6.69A1.1,1.1,0,0,1,103,30.868Zm-14.046-9.59a1.806,1.806,0,1,1-1.773,1.806A1.789,1.789,0,0,1,88.955,21.278ZM103,12.945a1.806,1.806,0,1,1-1.773,1.806A1.79,1.79,0,0,1,103,12.945Zm14.045,8.333a1.806,1.806,0,1,1-1.772,1.806A1.789,1.789,0,0,1,117.045,21.278Zm0,15.833a1.806,1.806,0,1,1-1.772,1.806A1.789,1.789,0,0,1,117.045,37.111ZM103,45.167a1.806,1.806,0,1,1-1.773,1.806A1.79,1.79,0,0,1,103,45.167ZM88.955,37.111a1.806,1.806,0,1,1-1.773,1.806A1.789,1.789,0,0,1,88.955,37.111Z" transform="translate(-85 -11)"/>
<path id="rsk" class="cls-2" d="M134.057,37.863V29.487l0.528-.216a16.858,16.858,0,0,1,3.528-1.056V25.6a11.416,11.416,0,0,0-4.08,1.7v-1.44h-2.592v12h2.616Zm14.424-11.712-0.744-.144a22.876,22.876,0,0,0-3.768-.384,5.371,5.371,0,0,0-3.228.912,3.183,3.183,0,0,0-1.26,2.76,3.029,3.029,0,0,0,.912,2.544,6.571,6.571,0,0,0,2.868,1.02,10.246,10.246,0,0,1,2.472.6,1.029,1.029,0,0,1,.516,1,1.1,1.1,0,0,1-.54,1.032,3.843,3.843,0,0,1-1.812.312,35.663,35.663,0,0,1-4.152-.384l-0.1,2.184,0.744,0.12a21.326,21.326,0,0,0,3.7.408,5.941,5.941,0,0,0,3.54-.888,3.22,3.22,0,0,0,1.212-2.784,3.412,3.412,0,0,0-.84-2.64,5.863,5.863,0,0,0-2.844-1.092,12.128,12.128,0,0,1-2.544-.612,0.932,0.932,0,0,1-.54-0.912,1.029,1.029,0,0,1,.492-0.948,3.661,3.661,0,0,1,1.764-.3,34.588,34.588,0,0,1,4.1.384Zm5.5,6.816,1.56-.168,2.928,5.064h2.952l-3.648-6.384,3.456-5.616H158.3l-2.832,4.68-1.488.144V20.871h-2.616V37.863h2.616v-4.9Z" transform="translate(-85 -11)"/>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

@ -1 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 406.5 106"><defs><style>.cls-1{fill:#fff;}</style></defs><title>sokol_logo</title><path class="cls-1" d="M382.031,72.458a2.025,2.025,0,0,1-1.441.536,2.106,2.106,0,0,1-1.507-.536,2.014,2.014,0,0,1-.57-1.541V27.17a2.013,2.013,0,0,1,.57-1.541,2.106,2.106,0,0,1,1.507-.536,1.905,1.905,0,0,1,2.01,2.077V70.917A2.021,2.021,0,0,1,382.031,72.458Zm-32.663-1.407a15.894,15.894,0,0,1-15.711,0,13.931,13.931,0,0,1-5.259-5.9,19.956,19.956,0,0,1-1.876-8.91,19.962,19.962,0,0,1,1.876-8.91,13.923,13.923,0,0,1,5.259-5.9,15.894,15.894,0,0,1,15.711,0,13.649,13.649,0,0,1,5.259,5.9,20.278,20.278,0,0,1,1.844,8.91,20.272,20.272,0,0,1-1.844,8.91A13.657,13.657,0,0,1,349.368,71.051Zm.034-24.62a10.606,10.606,0,0,0-15.779,0q-2.814,3.516-2.813,9.814,0,6.432,2.746,9.848t7.907,3.417a9.745,9.745,0,0,0,7.972-3.417q2.814-3.416,2.814-9.848Q352.249,49.948,349.4,46.431ZM307.158,72.994a2.264,2.264,0,0,1-1.407-.6L287.527,56.848V70.917a1.905,1.905,0,0,1-2.009,2.077,2.112,2.112,0,0,1-1.508-.536,2.017,2.017,0,0,1-.569-1.541V27.17a2.016,2.016,0,0,1,.569-1.541,2.112,2.112,0,0,1,1.508-.536,1.905,1.905,0,0,1,2.009,2.077v28L304.21,40.167a2.266,2.266,0,0,1,1.407-.6,1.944,1.944,0,0,1,1.943,1.943,1.908,1.908,0,0,1-.8,1.607l-14.471,12.8L308.1,69.443a2.307,2.307,0,0,1,.871,1.675,1.856,1.856,0,0,1-.536,1.306A1.7,1.7,0,0,1,307.158,72.994ZM254.3,71.051a15.9,15.9,0,0,1-15.712,0,13.951,13.951,0,0,1-5.259-5.9,19.983,19.983,0,0,1-1.876-8.91,19.989,19.989,0,0,1,1.876-8.91,13.942,13.942,0,0,1,5.259-5.9,15.9,15.9,0,0,1,15.712,0,13.67,13.67,0,0,1,5.26,5.9,20.306,20.306,0,0,1,1.842,8.91,20.3,20.3,0,0,1-1.842,8.91A13.678,13.678,0,0,1,254.3,71.051Zm.033-24.62a10.6,10.6,0,0,0-15.778,0q-2.814,3.516-2.814,9.814,0,6.432,2.747,9.848t7.906,3.417a9.747,9.747,0,0,0,7.973-3.417q2.813-3.416,2.813-9.848Q257.176,49.948,254.329,46.431Zm-59.763,6.632a27.51,27.51,0,0,0,4.924,1.507,35.038,35.038,0,0,1,7.1,2.278,8.468,8.468,0,0,1,3.552,2.881,8.385,8.385,0,0,1-2.378,10.886q-3.453,2.513-9.146,2.513a20.2,20.2,0,0,1-5.527-.771,17.7,17.7,0,0,1-4.792-2.11,8.313,8.313,0,0,1-1.775-1.507,2.267,2.267,0,0,1-.5-1.441,1.612,1.612,0,0,1,.436-1.139,1.37,1.37,0,0,1,1.038-.469,4.79,4.79,0,0,1,2.077,1,21.855,21.855,0,0,0,3.987,2.077,14.108,14.108,0,0,0,5.126.8,11.236,11.236,0,0,0,6.163-1.44,4.632,4.632,0,0,0,2.212-4.12,4.194,4.194,0,0,0-.805-2.647,6.387,6.387,0,0,0-2.68-1.809,32.6,32.6,0,0,0-5.359-1.507q-5.965-1.34-8.477-3.45a7.017,7.017,0,0,1-2.512-5.661,8.416,8.416,0,0,1,3.35-6.934,13.634,13.634,0,0,1,8.71-2.646,18.3,18.3,0,0,1,4.991.67,12.791,12.791,0,0,1,4.122,1.943q2.343,1.606,2.345,3.148a1.742,1.742,0,0,1-.436,1.173,1.331,1.331,0,0,1-1.038.5,4.255,4.255,0,0,1-2.077-1.072,20.422,20.422,0,0,0-3.585-2.043,11.424,11.424,0,0,0-4.523-.771,8.975,8.975,0,0,0-5.56,1.575,5.054,5.054,0,0,0-2.077,4.254,4.338,4.338,0,0,0,.7,2.546A5.743,5.743,0,0,0,194.566,53.063ZM138.731,79.4h-40.5a7.02,7.02,0,0,1-1.644-.208l.056.208H79.168L73.922,59.86H20.807v-.287a3.157,3.157,0,0,1-2.792-3.116V32.687h0a6.344,6.344,0,0,1,6.345-6.324l.022,0v0H124.47a8.883,8.883,0,0,1,8.056,6.333l10.856,40.372C144.322,76.565,142.24,79.4,138.731,79.4ZM43.477,36.125H29.167L33,50.111H47.312Zm23.738,0H52.905l3.837,13.986H71.051Zm39.107,36.28h6.593l-1.771-6.94H104.55Zm17.343-36.28H96.182l7.383,26.521h27.483Zm8.434,29.34h-6.594l1.772,6.94h6.593ZM20.807,65.443H64.074v.021h4.914L72.456,79.4H24.994v-.032a6.338,6.338,0,0,1-6.929-5.551h-.05V69.63h.39a2.724,2.724,0,0,1-.39-1.4A2.79,2.79,0,0,1,20.807,65.443Z"/></svg>
<svg id="_-e-logo_top" data-name="-e-logo_top" xmlns="http://www.w3.org/2000/svg" width="96" height="19"><defs><style>.cls-1{fill:#40bfb2;fill-rule:evenodd}</style></defs><path id="_2" data-name="2" class="cls-1" d="M108.627 22h14.51a3.182 3.182 0 0 1 2.886 2.269l3.888 14.463A1.683 1.683 0 0 1 128.245 41h-14.509a3.183 3.183 0 0 1-2.887-2.269l-3.889-14.462A1.683 1.683 0 0 1 108.627 22zm-21.354 0A2.273 2.273 0 1 1 85 24.274 2.273 2.273 0 0 1 87.273 22zm-1.133 9.656A1.125 1.125 0 1 1 85 32.781a1.133 1.133 0 0 1 1.141-1.125zM85 24.266h25.609v8.516H85v-8.516zM87.281 22h23.031v2.266H87.281V22zM86 32h25v2H86v-2zm18.471-.075h6.259L113.166 41h-6.259zM98 25h5.521L105 31.009h-5.521zm-9 0h5.521L96 31.009h-5.525zm24 0h10.239l2.751 10h-10.24zm3 11.01h2.363L119 38h-2.362zm8.007 0h2.363L127 38h-2.362z" transform="translate(-85 -22)"/><path id="_3" data-name="3" class="cls-1" d="M141.538 37a4.271 4.271 0 0 0 2.554-.7 2.164 2.164 0 0 0 .968-1.839 1.96 1.96 0 0 0-1.269-1.993 9.24 9.24 0 0 0-1.925-.6 7.486 7.486 0 0 1-1.286-.372 1.588 1.588 0 0 1-.639-.435 1.012 1.012 0 0 1-.191-.643 1.2 1.2 0 0 1 .52-1.015 2.276 2.276 0 0 1 1.377-.381 3.092 3.092 0 0 1 1.132.181 5.827 5.827 0 0 1 .967.507 1.366 1.366 0 0 0 .657.308.45.45 0 0 0 .346-.163.573.573 0 0 0 .146-.4 1.179 1.179 0 0 0-.62-.906 4.12 4.12 0 0 0-1.177-.534 4.988 4.988 0 0 0-1.378-.19 4.3 4.3 0 0 0-1.761.344 2.944 2.944 0 0 0-1.213.942 2.27 2.27 0 0 0-.438 1.377 1.947 1.947 0 0 0 .692 1.58 5.439 5.439 0 0 0 2.3.924 9.919 9.919 0 0 1 1.441.389 1.662 1.662 0 0 1 .694.435.987.987 0 0 1 .2.643 1.107 1.107 0 0 1-.547 1 2.876 2.876 0 0 1-1.533.344 4.065 4.065 0 0 1-1.341-.19 6.079 6.079 0 0 1-1.086-.516 1.368 1.368 0 0 0-.639-.272.452.452 0 0 0-.355.154.562.562 0 0 0-.137.389.765.765 0 0 0 .137.462 1.786 1.786 0 0 0 .465.408 4.872 4.872 0 0 0 1.341.562 6.254 6.254 0 0 0 1.6.2zm10.641 0a4.3 4.3 0 0 0 2.211-.562 3.73 3.73 0 0 0 1.477-1.6 5.928 5.928 0 0 0 0-4.838 3.733 3.733 0 0 0-1.477-1.6 4.3 4.3 0 0 0-2.211-.562 4.248 4.248 0 0 0-2.2.562 3.737 3.737 0 0 0-1.468 1.6 5.928 5.928 0 0 0 0 4.838 3.735 3.735 0 0 0 1.468 1.6 4.246 4.246 0 0 0 2.2.562zm0-1.214a2.418 2.418 0 0 1-2-.87 3.915 3.915 0 0 1-.7-2.5 3.886 3.886 0 0 1 .707-2.491 2.7 2.7 0 0 1 3.986 0 3.88 3.88 0 0 1 .707 2.491 3.913 3.913 0 0 1-.7 2.51 2.43 2.43 0 0 1-2 .861zm14.731-.072l-3.83-3.414 3.493-3.189a.728.728 0 0 0 .249-.544.652.652 0 0 0-.195-.471.626.626 0 0 0-.461-.2.655.655 0 0 0-.479.217l-4.238 3.968v-7.352a.7.7 0 0 0-.2-.534.711.711 0 0 0-.5-.19.734.734 0 0 0-.523.19.692.692 0 0 0-.2.534v11.506a.691.691 0 0 0 .2.535.735.735 0 0 0 .523.19.712.712 0 0 0 .5-.19.7.7 0 0 0 .2-.535v-3.57l4.628 4.077a.741.741 0 0 0 .479.217.6.6 0 0 0 .452-.2.668.668 0 0 0 .186-.471.8.8 0 0 0-.284-.58zM173.158 37a4.275 4.275 0 0 0 2.2-.562 3.726 3.726 0 0 0 1.472-1.6 5.949 5.949 0 0 0 0-4.838 3.728 3.728 0 0 0-1.472-1.6 4.277 4.277 0 0 0-2.2-.562 4.222 4.222 0 0 0-2.194.562 3.739 3.739 0 0 0-1.463 1.6 5.938 5.938 0 0 0 0 4.838 3.737 3.737 0 0 0 1.463 1.6 4.22 4.22 0 0 0 2.194.562zm0-1.214a2.407 2.407 0 0 1-2-.87 3.927 3.927 0 0 1-.695-2.5 3.9 3.9 0 0 1 .7-2.491 2.686 2.686 0 0 1 3.974 0 3.9 3.9 0 0 1 .7 2.491 3.919 3.919 0 0 1-.695 2.51 2.418 2.418 0 0 1-2 .861zm7.116 1.178a.735.735 0 0 0 .515-.19.69.69 0 0 0 .211-.539V24.729a.69.69 0 0 0-.208-.534.734.734 0 0 0-.515-.19.759.759 0 0 0-.533.19.69.69 0 0 0-.207.534v11.506a.69.69 0 0 0 .207.535.76.76 0 0 0 .533.19z" transform="translate(-85 -22)"/><path id="_1" data-name="1" class="cls-1" d="M87.273 36.453A2.273 2.273 0 1 1 85 38.727a2.273 2.273 0 0 1 2.273-2.274zM86 36a1 1 0 1 1-1 1 1 1 0 0 1 1-1zm-1 1.5h1.5V39H85v-1.5zm2.5-1.5h14v5h-14v-5zm12.494.008h3.266L104.5 41h-3.267zM86 36h1.5v1.5H86V36z" transform="translate(-85 -22)"/></svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

@ -28,65 +28,7 @@ config :block_scout_web,
"EtherChain" => "https://www.etherchain.org/",
"Bloxy" => "https://bloxy.info/"
},
other_networks: [
%{
title: "POA Core",
url: "https://blockscout.com/poa/core"
},
%{
title: "POA Sokol",
url: "https://blockscout.com/poa/sokol",
test_net?: true
},
%{
title: "xDai Chain",
url: "https://blockscout.com/poa/dai"
},
%{
title: "Ethereum Mainnet",
url: "https://blockscout.com/eth/mainnet"
},
%{
title: "Kovan Testnet",
url: "https://blockscout.com/eth/kovan",
test_net?: true
},
%{
title: "Ropsten Testnet",
url: "https://blockscout.com/eth/ropsten",
test_net?: true
},
%{
title: "Goerli Testnet",
url: "https://blockscout.com/eth/goerli",
test_net?: true
},
%{
title: "Rinkeby Testnet",
url: "https://blockscout.com/eth/rinkeby",
test_net?: true
},
%{
title: "Ethereum Classic",
url: "https://blockscout.com/etc/mainnet",
other?: true
},
%{
title: "Aerum Mainnet",
url: "https://blockscout.com/aerum/mainnet",
other?: true
},
%{
title: "Callisto Mainnet",
url: "https://blockscout.com/callisto/mainnet",
other?: true
},
%{
title: "RSK Mainnet",
url: "https://blockscout.com/rsk/mainnet",
other?: true
}
]
other_networks: System.get_env("SUPPORTED_CHAINS")
config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: true

@ -25,7 +25,8 @@ defmodule BlockScoutWeb.Chain do
InternalTransaction,
Log,
TokenTransfer,
Transaction
Transaction,
Wei
}
alias Explorer.PagingOptions
@ -87,6 +88,16 @@ defmodule BlockScoutWeb.Chain do
Map.merge(params, paging_params(List.last(list)))
end
def paging_options(%{"hash" => hash, "fetched_coin_balance" => fetched_coin_balance}) do
with {coin_balance, ""} <- Integer.parse(fetched_coin_balance),
{:ok, address_hash} <- string_to_address_hash(hash) do
[paging_options: %{@default_paging_options | key: {%Wei{value: Decimal.new(coin_balance)}, address_hash}}]
else
_ ->
[paging_options: @default_paging_options]
end
end
def paging_options(%{
"block_number" => block_number_string,
"transaction_index" => transaction_index_string,
@ -177,6 +188,10 @@ defmodule BlockScoutWeb.Chain do
end
end
defp paging_params({%Address{hash: hash, fetched_coin_balance: fetched_coin_balance}, _}) do
%{"hash" => hash, "fetched_coin_balance" => Decimal.to_string(fetched_coin_balance.value)}
end
defp paging_params({%Reward{block: %{number: number}}, _}) do
%{"block_number" => number, "index" => 0}
end
@ -190,8 +205,12 @@ defmodule BlockScoutWeb.Chain do
%{"block_number" => block_number, "transaction_index" => transaction_index, "index" => index}
end
defp paging_params(%Log{index: index}) do
%{"index" => index}
defp paging_params(%Log{index: index} = log) do
if Ecto.assoc_loaded?(log.transaction) do
%{"block_number" => log.transaction.block_number, "transaction_index" => log.transaction.index, "index" => index}
else
%{"index" => index}
end
end
defp paging_params(%Transaction{block_number: nil, inserted_at: inserted_at, hash: hash}) do

@ -1,16 +1,55 @@
defmodule BlockScoutWeb.AddressController do
use BlockScoutWeb, :controller
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias Explorer.{Chain, Market}
alias Explorer.Chain.Address
alias Explorer.ExchangeRates.Token
def index(conn, _params) do
def index(conn, params) do
addresses =
params
|> paging_options()
|> Chain.list_top_addresses()
{addresses_page, next_page} = split_list_by_page(addresses)
cur_page_number =
cond do
!params["prev_page_number"] -> 1
params["next_page"] -> String.to_integer(params["prev_page_number"]) + 1
params["prev_page"] -> String.to_integer(params["prev_page_number"]) - 1
end
next_page_path =
case next_page_params(next_page, addresses_page, params) do
nil ->
nil
next_page_params ->
next_params =
next_page_params
|> Map.put("prev_page_path", cur_page_path(conn, params))
|> Map.put("next_page", true)
|> Map.put("prev_page_number", cur_page_number)
address_path(
conn,
:index,
next_params
)
end
render(conn, "index.html",
address_tx_count_pairs: Chain.list_top_addresses(),
address_tx_count_pairs: addresses_page,
page_address_count: Enum.count(addresses_page),
address_count: Chain.count_addresses_with_balance_from_cache(),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
total_supply: Chain.total_supply()
total_supply: Chain.total_supply(),
next_page_path: next_page_path,
prev_page_path: params["prev_page_path"],
cur_page_number: cur_page_number
)
end
@ -25,4 +64,16 @@ defmodule BlockScoutWeb.AddressController do
def validation_count(%Address{} = address) do
Chain.address_to_validation_count(address)
end
defp cur_page_path(conn, %{"hash" => _hash, "fetched_coin_balance" => _balance} = params) do
new_params = Map.put(params, "next_page", false)
address_path(
conn,
:index,
new_params
)
end
defp cur_page_path(conn, _), do: address_path(conn, :index)
end

@ -0,0 +1,46 @@
defmodule BlockScoutWeb.AddressLogsController do
@moduledoc """
Manages events logs tab.
"""
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1]
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token
alias Indexer.Fetcher.CoinBalanceOnDemand
use BlockScoutWeb, :controller
def index(conn, %{"address_id" => address_hash_string} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do
logs_plus_one = Chain.address_to_logs(address, paging_options(params))
{results, next_page} = split_list_by_page(logs_plus_one)
next_page_url =
case next_page_params(next_page, results, params) do
nil ->
nil
next_page_params ->
address_logs_path(conn, :index, address, next_page_params)
end
render(
conn,
"index.html",
address: address,
logs: results,
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address),
next_page_url: next_page_url
)
else
_ ->
not_found(conn)
end
end
end

@ -4,6 +4,7 @@ defmodule BlockScoutWeb.API.RPC.AddressController do
alias BlockScoutWeb.API.RPC.Helpers
alias Explorer.{Chain, Etherscan}
alias Explorer.Chain.{Address, Wei}
alias Indexer.Fetcher.CoinBalanceOnDemand
def listaccounts(conn, params) do
options =
@ -279,12 +280,15 @@ defmodule BlockScoutWeb.API.RPC.AddressController do
offset = (max(page_number, 1) - 1) * page_size
# limit is just page_size
Chain.list_ordered_addresses(offset, page_size)
offset
|> Chain.list_ordered_addresses(page_size)
|> trigger_balances_and_add_status()
end
defp hashes_to_addresses(address_hashes) do
address_hashes
|> Chain.hashes_to_addresses()
|> trigger_balances_and_add_status()
|> add_not_found_addresses(address_hashes)
end
@ -307,6 +311,18 @@ defmodule BlockScoutWeb.API.RPC.AddressController do
end)
end
defp trigger_balances_and_add_status(addresses) do
Enum.map(addresses, fn address ->
case CoinBalanceOnDemand.trigger_fetch(address) do
:current ->
%{address | stale?: false}
_ ->
%{address | stale?: true}
end
end)
end
defp to_contract_address_hash(nil), do: {:contract_address, {:ok, nil}}
defp to_contract_address_hash(address_hash_string) do

@ -3,6 +3,7 @@ defmodule BlockScoutWeb.API.RPC.BlockController do
alias BlockScoutWeb.Chain, as: ChainWeb
alias Explorer.Chain
alias Explorer.Chain.BlockNumberCache
def getblockreward(conn, params) do
with {:block_param, {:ok, unsafe_block_number}} <- {:block_param, Map.fetch(params, "blockno")},
@ -23,4 +24,11 @@ defmodule BlockScoutWeb.API.RPC.BlockController do
render(conn, :error, error: "Block does not exist")
end
end
def eth_block_number(conn, params) do
id = Map.get(params, "id", 1)
max_block_number = BlockNumberCache.max_number()
render(conn, :eth_block_number, number: max_block_number, id: id)
end
end

@ -8,16 +8,21 @@ defmodule BlockScoutWeb.API.RPC.ContractController do
def verify(conn, %{"addressHash" => address_hash} = params) do
with {:params, {:ok, fetched_params}} <- {:params, fetch_verify_params(params)},
{:format, {:ok, casted_address_hash}} <- to_address_hash(address_hash),
{:params, external_libraries} <-
{:params, fetch_external_libraries(params)},
{:publish, {:ok, smart_contract}} <-
{:publish, Publisher.publish(address_hash, fetched_params, external_libraries)},
preloaded_smart_contract <- SmartContract.preload_decompiled_smart_contract(smart_contract) do
render(conn, :verify, %{contract: preloaded_smart_contract, address_hash: address_hash})
{:publish, {:ok, _}} <-
{:publish, Publisher.publish(address_hash, fetched_params, external_libraries)} do
address = Chain.address_hash_to_address_with_source_code(casted_address_hash)
render(conn, :verify, %{contract: address})
else
{:publish, _} ->
render(conn, :error, error: "Something went wrong while publishing the contract.")
{:format, :error} ->
render(conn, :error, error: "Invalid address hash")
{:params, {:error, error}} ->
render(conn, :error, error: error)
end
@ -63,11 +68,11 @@ defmodule BlockScoutWeb.API.RPC.ContractController do
def getsourcecode(conn, params) do
with {:address_param, {:ok, address_param}} <- fetch_address(params),
{:format, {:ok, address_hash}} <- to_address_hash(address_param),
{:contract, {:ok, contract}} <- to_smart_contract(address_hash) do
{:format, {:ok, address_hash}} <- to_address_hash(address_param) do
address = Chain.address_hash_to_address_with_source_code(address_hash)
render(conn, :getsourcecode, %{
contract: contract,
address_hash: address_hash
contract: address
})
else
{:address_param, :error} ->
@ -98,6 +103,9 @@ defmodule BlockScoutWeb.API.RPC.ContractController do
:not_decompiled ->
Chain.list_not_decompiled_contracts(page_size, offset)
:empty ->
Chain.list_empty_contracts(page_size, offset)
_ ->
Chain.list_contracts(page_size, offset)
end
@ -135,10 +143,12 @@ defmodule BlockScoutWeb.API.RPC.ContractController do
defp contracts_filter(2), do: {:ok, :decompiled}
defp contracts_filter(3), do: {:ok, :unverified}
defp contracts_filter(4), do: {:ok, :not_decompiled}
defp contracts_filter(5), do: {:ok, :empty}
defp contracts_filter("verified"), do: {:ok, :verified}
defp contracts_filter("decompiled"), do: {:ok, :decompiled}
defp contracts_filter("unverified"), do: {:ok, :unverified}
defp contracts_filter("not_decompiled"), do: {:ok, :not_decompiled}
defp contracts_filter("empty"), do: {:ok, :empty}
defp contracts_filter(filter) when is_bitstring(filter) do
case Integer.parse(filter) do

@ -8,14 +8,24 @@ defmodule BlockScoutWeb.BlockController do
alias Phoenix.View
def index(conn, params) do
[
necessity_by_association: %{
:transactions => :optional,
[miner: :names] => :optional,
:rewards => :optional
}
]
|> handle_render(conn, params)
case params["block_type"] do
"Uncle" ->
uncle(conn, params)
"Reorg" ->
reorg(conn, params)
_ ->
[
necessity_by_association: %{
:transactions => :optional,
[miner: :names] => :optional,
:rewards => :optional
},
block_type: "Block"
]
|> handle_render(conn, params)
end
end
def show(conn, %{"hash_or_number" => hash_or_number}) do
@ -55,21 +65,26 @@ defmodule BlockScoutWeb.BlockController do
{blocks, next_page} = split_list_by_page(blocks_plus_one)
block_type = Keyword.get(full_options, :block_type, "Block")
next_page_path =
case next_page_params(next_page, blocks, params) do
nil ->
nil
next_page_params ->
params_with_block_type =
next_page_params
|> Map.delete("type")
|> Map.put("block_type", block_type)
block_path(
conn,
:index,
Map.delete(next_page_params, "type")
params_with_block_type
)
end
block_type = Keyword.get(full_options, :block_type, "Block")
json(
conn,
%{

@ -3,7 +3,7 @@ defmodule BlockScoutWeb.ChainController do
alias BlockScoutWeb.ChainView
alias Explorer.{Chain, PagingOptions, Repo}
alias Explorer.Chain.{Address, Block, BlockCountCache, Transaction}
alias Explorer.Chain.{Address, Block, Transaction}
alias Explorer.Counters.AverageBlockTime
alias Explorer.ExchangeRates.Token
alias Explorer.Market
@ -11,7 +11,7 @@ defmodule BlockScoutWeb.ChainController do
def show(conn, _params) do
transaction_estimated_count = Chain.transaction_estimated_count()
block_count = BlockCountCache.count()
block_count = Chain.block_estimated_count()
exchange_rate = Market.get_exchange_rate(Explorer.coin()) || Token.null()

@ -21,15 +21,18 @@ defmodule BlockScoutWeb.Etherscan do
"result" => [
%{
"account" => "0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a",
"balance" => "40807168566070000000000"
"balance" => "40807168566070000000000",
"stale" => true
},
%{
"account" => "0x63a9975ba31b0b9626b34300f7f627147df1f526",
"balance" => "332567136222827062478"
"balance" => "332567136222827062478",
"stale" => false
},
%{
"account" => "0x198ef1ec325a96cc354c7266a038be8b5c558f67",
"balance" => "185178830000000000"
"balance" => "185178830000000000",
"stale" => false
}
]
}
@ -276,6 +279,12 @@ defmodule BlockScoutWeb.Etherscan do
"result" => nil
}
@block_eth_block_number_example_value %{
"jsonrpc" => "2.0",
"result" => "767969",
"id" => 1
}
@contract_listcontracts_example_value %{
"status" => "1",
"message" => "OK",
@ -473,11 +482,26 @@ defmodule BlockScoutWeb.Etherscan do
enum_interpretation: %{"0" => "error", "1" => "ok"}
}
@jsonrpc_version_type %{
type: "string",
example: ~s("2.0")
}
@message_type %{
type: "string",
example: ~s("OK")
}
@hex_number_type %{
type: "string",
example: ~s("767969")
}
@id_type %{
type: "string",
example: ~s("1")
}
@wei_type %{
type: "wei",
definition: &__MODULE__.wei_type_definition/1,
@ -496,6 +520,13 @@ defmodule BlockScoutWeb.Etherscan do
example: ~s("0x95426f2bc716022fcf1def006dbc4bb81f5b5164")
}
@stale_type %{
type: "boolean",
definition:
"Represents whether or not the balance has not been checked in the last 24 hours, and will be rechecked.",
example: true
}
@transaction_hash_type %{
type: "transaction hash",
definition:
@ -563,6 +594,11 @@ defmodule BlockScoutWeb.Etherscan do
type: "block number",
definition: "A nonnegative number used to identify blocks.",
example: ~s("0x5c958")
},
index: %{
type: "log index",
definition: "A nonnegative number used to identify logs.",
example: ~s("1")
}
}
}
@ -571,7 +607,8 @@ defmodule BlockScoutWeb.Etherscan do
name: "AddressBalance",
fields: %{
address: @address_hash_type,
balance: @wei_type
balance: @wei_type,
stale: @stale_type
}
}
@ -825,48 +862,11 @@ defmodule BlockScoutWeb.Etherscan do
name: "Contract",
fields: %{
"Address" => @address_hash_type,
"SourceCode" => %{
type: "contract source code",
definition: "The contract's source code.",
example: """
"pragma solidity >0.4.24;
contract Test {
constructor() public { b = hex"12345678901234567890123456789012"; }
event Event(uint indexed a, bytes32 b);
event Event2(uint indexed a, bytes32 b);
function foo(uint a) public { emit Event(a, b); }
bytes32 b;
}"
"""
},
"DecompilerVersion" => %{
type: "decompiler version",
definition: "When decompiled source code is present, the decompiler version with which it was generated.",
example: "decompiler.version"
},
"DecompiledSourceCode" => %{
type: "contract decompiled source code",
definition: "The contract's decompiled source code.",
example: """
const name() = 'CryptoKitties'
const GEN0_STARTING_PRICE() = 10^16
const GEN0_AUCTION_DURATION() = 86400
const GEN0_CREATION_LIMIT() = 45000
const symbol() = 'CK'
const PROMO_CREATION_LIMIT() = 5000
def storage:
ceoAddress is addr # mask(160, 0) at storage #0
cfoAddress is addr # mask(160, 0) at storage #1
stor1.768 is uint16 => uint256 # mask(256, 768) at storage #1
cooAddress is addr # mask(160, 0) at storage #2
stor2.0 is uint256 => uint256 # mask(256, 0) at storage #2
paused is uint8 # mask(8, 160) at storage #2
stor2.256 is uint256 => uint256 # mask(256, 256) at storage #2
stor3 is uint32 #
...<continues>
"""
},
"ABI" => %{
type: "ABI",
definition: "JSON string for the contract's Application Binary Interface (ABI)",
@ -899,6 +899,49 @@ defmodule BlockScoutWeb.Etherscan do
}
}
@contract_source_code_type %{
type: "contract source code",
definition: "The contract's source code.",
example: """
"pragma solidity >0.4.24;
contract Test {
constructor() public { b = hex"12345678901234567890123456789012"; }
event Event(uint indexed a, bytes32 b);
event Event2(uint indexed a, bytes32 b);
function foo(uint a) public { emit Event(a, b); }
bytes32 b;
}"
"""
}
@contract_decompiled_source_code_type %{
type: "contract decompiled source code",
definition: "The contract's decompiled source code.",
example: """
const name() = 'CryptoKitties'
const GEN0_STARTING_PRICE() = 10^16
const GEN0_AUCTION_DURATION() = 86400
const GEN0_CREATION_LIMIT() = 45000
const symbol() = 'CK'
const PROMO_CREATION_LIMIT() = 5000
def storage:
ceoAddress is addr # mask(160, 0) at storage #0
cfoAddress is addr # mask(160, 0) at storage #1
stor1.768 is uint16 => uint256 # mask(256, 768) at storage #1
cooAddress is addr # mask(160, 0) at storage #2
stor2.0 is uint256 => uint256 # mask(256, 0) at storage #2
paused is uint8 # mask(8, 160) at storage #2
stor2.256 is uint256 => uint256 # mask(256, 256) at storage #2
stor3 is uint32 #
...<continues>
"""
}
@contract_with_sourcecode_model @contract_model
|> put_in([:fields, "SourceCode"], @contract_source_code_type)
|> put_in([:fields, "DecompiledSourceCode"], @contract_decompiled_source_code_type)
@transaction_receipt_status_model %{
name: "TransactionReceiptStatus",
fields: %{
@ -982,7 +1025,16 @@ defmodule BlockScoutWeb.Etherscan do
@account_balance_action %{
name: "balance",
description: "Get balance for address. Also available through a GraphQL 'addresses' query.",
description: """
Get balance for address. Also available through a GraphQL 'addresses' query.
If the balance hasn't been updated in a long time, we will double check
with the node to fetch the absolute latest balance. This will not be
reflected in the current request, but once it is updated, subsequent requests
will show the updated balance. If you want to know whether or not we are checking
for another balance, use the `balancemulti` action. That contains a property
called `stale` that will let you know to recheck that balance in the near future.
""",
required_params: [
%{
key: "address",
@ -1016,7 +1068,15 @@ defmodule BlockScoutWeb.Etherscan do
@account_balancemulti_action %{
name: "balancemulti",
description: "Get balance for multiple addresses. Also available through a GraphQL 'addresses' query.",
description: """
Get balance for multiple addresses. Also available through a GraphQL 'addresses' query.
If the balance hasn't been updated in a long time, we will double check
with the node to fetch the absolute latest balance. This will not be
reflected in the current request, but once it is updated, subsequent requests
will show the updated balance. You can know that this is taking place via
the `stale` attribute, which is set to `true` if a new balance is being fetched.
""",
required_params: [
%{
key: "address",
@ -1703,6 +1763,35 @@ defmodule BlockScoutWeb.Etherscan do
]
}
@block_eth_block_number_action %{
name: "eth_block_number",
description: "Mimics Ethereum JSON RPC's eth_blockNumber. Returns the lastest block number",
required_params: [],
optional_params: [
%{
key: "id",
placeholder: "request id",
type: "integer",
description: "A nonnegative integer that represents the json rpc request id."
}
],
responses: [
%{
code: "200",
description: "successful request",
example_value: Jason.encode!(@block_eth_block_number_example_value),
model: %{
name: "Result",
fields: %{
jsonrpc: @jsonrpc_version_type,
id: @id_type,
result: @hex_number_type
}
}
}
]
}
@block_getblockreward_action %{
name: "getblockreward",
description: "Get block reward by block number.",
@ -1761,7 +1850,7 @@ defmodule BlockScoutWeb.Etherscan do
key: "filter",
type: "string",
description:
"verified|decompiled|unverified|not_decompiled, or 1|2|3|4 respectively. This requests only contracts with that status."
"verified|decompiled|unverified|not_decompiled|empty, or 1|2|3|4|5 respectively. This requests only contracts with that status."
},
%{
key: "not_decompiled_with_version",
@ -1971,7 +2060,7 @@ defmodule BlockScoutWeb.Etherscan do
message: @message_type,
result: %{
type: "array",
array_type: @contract_model
array_type: @contract_with_sourcecode_model
}
}
}
@ -2137,7 +2226,7 @@ defmodule BlockScoutWeb.Etherscan do
@block_module %{
name: "block",
actions: [@block_getblockreward_action]
actions: [@block_getblockreward_action, @block_eth_block_number_action]
}
@contract_module %{

@ -147,6 +147,13 @@ defmodule BlockScoutWeb.Router do
as: :decompiled_contract
)
resources(
"/logs",
AddressLogsController,
only: [:index],
as: :logs
)
resources(
"/contract_verifications",
AddressContractVerificationController,

@ -22,6 +22,11 @@
"data-test": "coin_balance_tab_link",
to: address_coin_balance_path(@conn, :index, @address.hash)
) %>
<%= link(
gettext("Logs"),
class: "card-tab #{tab_status("logs", @conn.request_path)}",
to: address_logs_path(@conn, :index, @address.hash)
) %>
<%= if BlockScoutWeb.AddressView.validator?(@validation_count) do %>
<%= link(
gettext("Blocks Validated"),
@ -55,4 +60,4 @@
class: "card-tab #{tab_status("read_contract", @conn.request_path)}")
%>
<% end %>
</div>
</div>

@ -1,20 +1,20 @@
<section class="container">
<div class="card">
<div class="card-body">
<h1 class="card-title margin-bottom-0"><%= gettext "Addresses" %></h1>
<p class="card-subtitle">
<%= gettext "Showing 250 addresses of" %>
<%= Cldr.Number.to_string!(@address_count, format: "#,###") %>
<%= gettext "total addresses with a balance" %>
</p>
<span data-selector="top-addresses-list">
<h1 class="card-title"><%= gettext "Addresses" %></h1>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", prev_page_path: @prev_page_path, next_page_path: @next_page_path, cur_page_number: @cur_page_number, show_pagination_limit: true %>
<div data-selector="top-addresses-list">
<%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %>
<%= render "_tile.html",
address: address, index: index, exchange_rate: @exchange_rate,
total_supply: @total_supply, tx_count: tx_count,
validation_count: validation_count(address) %>
<% end %>
</span>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", prev_page_path: @prev_page_path, next_page_path: @next_page_path, cur_page_number: @cur_page_number, show_pagination_limit: true %>
</div>
</div>
</section>

@ -13,20 +13,22 @@
<h2 class="card-title"><%= gettext "Balances" %></h2>
<div data-chart-loading-message class="tile tile-muted text-center mt-3">
<!-- Chart -->
<div data-chart-loading-message class="tile tile-muted text-center mt-3 mb-4">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
<span class="loading-spinner-block-2"></span>
</span>
<%= gettext("Loading chart") %>...
</div>
<button data-chart-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<button data-chart-error-message class="alert alert-danger col-12 text-left mb-4" style="display: none;">
<span><%= gettext("There was a problem loading the chart.") %></span>
</button>
<div data-chart-container style="display: none;">
<div data-chart-container style="display: none;" class="mb-4">
<canvas data-chart="coinBalanceHistoryChart" data-coin_balance_history_data_path="<%= address_coin_balance_by_day_path(@conn, :index, @address) %>" width="350" height="152"></canvas>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
@ -48,9 +50,13 @@
<div data-selector="coin-balances-list" data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a href="#" class="button button-secondary button-small float-right mt-4" data-next-page-button style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div class="button button-secondary button-small float-right mt-4" data-loading-button style="display: none;">
<span class="loading-spinner-small mr-2">

@ -1,18 +1,25 @@
<% contract_creation_code = contract_creation_code(@address) %>
<section class="container">
<%= render BlockScoutWeb.AddressView, "overview.html", assigns %>
<div class="card">
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
<div class="card-body">
<%= if !BlockScoutWeb.AddressView.smart_contract_verified?(@address) do %>
<%= link(
gettext("Verify & Publish"),
to: address_verify_contract_path(@conn, :new, @address.hash),
class: "button button-primary button-sm float-right ml-3",
"data-test": "verify_and_publish"
) %>
<%= if match?({:selfdestructed, _}, contract_creation_code) do %>
<div class="button button-disabled button-sm float-right ml-3">
<%= gettext("Verify & Publish") %>
</div>
<% else %>
<%= if !BlockScoutWeb.AddressView.smart_contract_verified?(@address) do %>
<%= link(
gettext("Verify & Publish"),
to: address_verify_contract_path(@conn, :new, @address.hash),
class: "button button-primary button-sm float-right ml-3",
"data-test": "verify_and_publish"
) %>
<% end %>
<% end %>
<%= if BlockScoutWeb.AddressView.smart_contract_verified?(@address) do %>
<div class="mb-4">
<dl class="row">
@ -56,15 +63,32 @@
<% end %>
<section>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "Contract creation code" %></h3>
<button type="button" class="button button-secondary button-sm" id="button" data-clipboard-text="<%= @address.contract_code %>" aria-label="copy contract creation code">
<%= gettext "Copy Contract Creation Code" %>
</button>
</div>
<div class="tile tile-muted">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= @address.contract_code %></code></pre>
</div>
<%= case contract_creation_code do %>
<% {:selfdestructed, transaction_init} -> %>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "Contract Creation Code" %></h3>
<button type="button" class="button button-secondary button-sm" id="button" data-clipboard-text="<%= transaction_init %>" aria-label="copy contract creation code">
<%= gettext "Copy Contract Creation Code" %>
</button>
</div>
<div class="alert alert-info">
<p><%= gettext "Contracts that self destruct in their constructors have no contract code published and cannot be verified." %></p>
<p><%= gettext "Displaying the init data provided of the creating transaction." %></p>
</div>
<div class="tile tile-muted">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= transaction_init %></code></pre>
</div>
<% {:ok, contract_code} -> %>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "Contract Byte Code" %></h3>
<button type="button" class="button button-secondary button-sm" id="button" data-clipboard-text="<%= contract_code %>" aria-label="copy contract creation code">
<%= gettext "Copy Contract Byte Code" %>
</button>
</div>
<div class="tile tile-muted">
<pre class="pre-wrap pre-scrollable"><code class="nohighlight"><%= contract_code %></code></pre>
</div>
<% end %>
</section>
</div>

@ -15,44 +15,48 @@
<a href="#" class="alert-link"><%= gettext "Connection Lost, click to load newer internal transactions" %></a>
</div>
</div>
<div class="dropdown float-right u-push-sm">
<button data-test="filter_dropdown" class="btn-dropdown-line dropdown-toggle" type="button"
id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Filter: <%= format_current_filter(@filter) %>
</button>
<div class="dropdown-menu dropdown-menu-right filter" aria-labelledby="dropdownMenu2">
<%= link(
gettext("All"),
to: address_internal_transaction_path(@conn, :index, @address.hash),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<%= link(
gettext("To"),
to: address_internal_transaction_path(
@conn,
:index,
@address.hash,
filter: "to"
),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<%= link(
gettext("From"),
to: address_internal_transaction_path(
@conn,
:index,
@address.hash,
filter: "from"
),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<div class="clearfix">
<h2 class="card-title float-left"><%= gettext "Internal Transactions" %></h2>
<div class="dropdown float-right u-push-sm">
<button data-test="filter_dropdown" class="btn-dropdown-line dropdown-toggle" type="button"
id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Filter: <%= format_current_filter(@filter) %>
</button>
<div class="dropdown-menu dropdown-menu-right filter" aria-labelledby="dropdownMenu2">
<%= link(
gettext("All"),
to: address_internal_transaction_path(@conn, :index, @address.hash),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<%= link(
gettext("To"),
to: address_internal_transaction_path(
@conn,
:index,
@address.hash,
filter: "to"
),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<%= link(
gettext("From"),
to: address_internal_transaction_path(
@conn,
:index,
@address.hash,
filter: "from"
),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
</div>
</div>
</div>
<h2 class="card-title"><%= gettext "Internal Transactions" %></h2>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
</button>
@ -69,9 +73,15 @@
<%= gettext("Loading") %>...
</div>
<div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a href="#" class="button button-secondary button-small float-right mt-4" data-next-page-button style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div class="button button-secondary button-small float-right mt-4" data-loading-button style="display: none;">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>

@ -0,0 +1,82 @@
<section class="container">
<%= render BlockScoutWeb.AddressView, "overview.html", assigns %>
<div class="card">
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
<div class="card-body">
<h2 class="card-title"><%= gettext "Logs" %></h2>
<%= if @next_page_url do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: @next_page_url %>
<% end %>
<%= if !@next_page_url do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.count(@logs) > 0 do %>
<%= for log <- @logs do %>
<div data-test="transaction_log" class="tile tile-muted">
<dl class="row">
<dt class="col-md-2"> <%= gettext "Transaction" %> </dt>
<dd class="col-md-10">
<h3 class="">
<%= link(
log.transaction,
to: transaction_path(@conn, :show, log.transaction),
"data-test": "log_address_link",
"data-address-hash": log.transaction
) %>
</h3>
</dd>
<dt class="col-md-2"><%= gettext "Topics" %></dt>
<dd class="col-md-10">
<div class="raw-transaction-log-topics">
<%= unless is_nil(log.first_topic) do %>
<div class="text-dark">
<span class="text-dark">[0]</span>
<%= log.first_topic %>
</div>
<% end %>
<%= unless is_nil(log.second_topic) do %>
<div class="text-dark">
<span class="">[1] </span>
<%= log.second_topic %>
</div>
<% end %>
<%= unless is_nil(log.third_topic) do %>
<div class="text-dark">
<span>[2]</span>
<%= log.third_topic %>
</div>
<% end %>
<%= unless is_nil(log.fourth_topic) do %>
<div class="text-dark">
<span>[3]</span>
<%= log.fourth_topic %>
</div>
<% end %>
</div>
</dd>
<dt class="col-md-2">
<%= gettext "Data" %>
</dt>
<dd class="col-md-10">
<%= unless is_nil(log.data) do %>
<div class="text-dark raw-transaction-log-data">
<%= log.data %>
</div>
<% end %>
</dd>
</dl>
</div>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no logs for this address." %></span>
</div>
<% end %>
</div>
</div>
</section>

@ -6,6 +6,15 @@
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
<div class="card-body">
<h2 class="card-title"><%= gettext "Tokens" %></h2>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: address_token_path(@conn, :index, @address, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.any?(@tokens) do %>
<%= for token <- @tokens do %>
<%= render "_tokens.html", conn: @conn, token: token, address: @address %>
@ -16,20 +25,28 @@
</div>
<% end %>
<div>
<%= if @next_page_params do %>
<%= link(
gettext("Next"),
class: "button button-secondary button-sm float-right mt-3",
to: address_token_path(
@conn,
:index,
@address,
@next_page_params
)
) %>
<% end %>
</div>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: address_token_path(@conn, :index, @address, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!--
<%= if @next_page_params do %>
<%= link(
gettext("Next"),
class: "button button-secondary button-sm float-right mt-3",
to: address_token_path(
@conn,
:index,
@address,
@next_page_params
)
) %>
<% end %>
-->
</div>
</div>
</section>

@ -1,6 +1,6 @@
<%= if Enum.any?(@token_balances) do %>
<a href="#"
class="text-white text-faded"
<a
href="#"
data-dropdown-toggle
data-toggle="dropdown"
role="button"

@ -8,6 +8,9 @@
<h2 class="card-title">
<span class="text-muted"><%= gettext "Tokens" %></span> / <%= token_name(@token) %>
</h2>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<div data-loading-message class="tile tile-muted text-center mt-3">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
@ -15,18 +18,27 @@
</span>
<%= gettext("Loading...") %>
</div>
<div data-empty-response-message class="tile tile-muted text-center" style="display: none;">
<span><%= gettext "There are no token transfers for this address." %></span>
</div>
<button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<span class="alert-link">
<%= gettext "Something went wrong, click to reload." %>
</span>
</button>
<div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a data-next-page-button href="#" class="button button-secondary button-small float-right mt-4" style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div data-loading-button class="button button-secondary button-small float-right mt-4" style="display: none;">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>

@ -11,43 +11,48 @@
<a href="#" class="alert-link"><%= gettext "Connection Lost, click to load newer transactions" %></a>
</div>
</div>
<div class="dropdown float-right u-push-sm">
<button data-test="filter_dropdown" class="btn-dropdown-line dropdown-toggle" type="button"
id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Filter: <%= format_current_filter(@filter) %>
</button>
<div class="dropdown-menu dropdown-menu-right filter" aria-labelledby="dropdownMenu2">
<%= link(
gettext("All"),
to: address_transaction_path(@conn, :index, @address.hash),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<%= link(
gettext("To"),
to: address_transaction_path(
@conn,
:index,
@address.hash,
filter: "to"
),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<%= link(
gettext("From"),
to: address_transaction_path(
@conn,
:index,
@address.hash,
filter: "from"
),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<div class="clearfix">
<h2 class="card-title float-left"><%= gettext "Transactions" %></h2>
<div class="dropdown float-right u-push-sm">
<button data-test="filter_dropdown" class="btn-dropdown-line dropdown-toggle" type="button"
id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Filter: <%= format_current_filter(@filter) %>
</button>
<div class="dropdown-menu dropdown-menu-right filter" aria-labelledby="dropdownMenu2">
<%= link(
gettext("All"),
to: address_transaction_path(@conn, :index, @address.hash),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<%= link(
gettext("To"),
to: address_transaction_path(
@conn,
:index,
@address.hash,
filter: "to"
),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
<%= link(
gettext("From"),
to: address_transaction_path(
@conn,
:index,
@address.hash,
filter: "from"
),
class: "address__link address__link--active dropdown-item",
"data-test": "filter_option"
) %>
</div>
</div>
</div>
<h2 class="card-title"><%= gettext "Transactions" %></h2>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
</button>
@ -68,9 +73,13 @@
<div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a href="#" class="button button-secondary button-small float-right mt-4" data-next-page-button style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div class="button button-secondary button-small float-right mt-4" data-loading-button style="display: none;">
<span class="loading-spinner-small mr-2">

@ -11,6 +11,9 @@
</div>
</div>
<h2 class="card-title"><%=gettext("Blocks Validated")%></h2>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<div data-loading-message class="tile tile-muted text-center mt-3">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
@ -27,9 +30,15 @@
</span>
</button>
<div data-items data-selector="validations-list"></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a data-next-page-button href="#" class="button button-secondary button-small float-right mt-4" style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div data-loading-button class="button button-secondary button-small float-right mt-4" style="display: none;">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>

@ -26,8 +26,10 @@
<span class="mr-2">
<%= ngettext("%{count} transaction", "%{count} transactions", Enum.count(@block.transactions)) %>
</span>
<!-- size -->
<span class="mr-2"> <%= Cldr.Unit.new(:byte, @block.size) |> cldr_unit_to_string!() %> </span>
<%= if @block.size do %>
<!-- size -->
<span class="mr-2"> <%= Cldr.Unit.new(:byte, @block.size) |> cldr_unit_to_string!() %> </span>
<% end %>
<!-- age -->
<span data-from-now="<%= @block.timestamp %>"></span>
</div>

@ -6,7 +6,11 @@
<a href="#" class="alert-link"><%= gettext "Connection Lost, click to load newer blocks" %></a>
</div>
</div>
<h1 class="card-title"><%= gettext("%{block_type}s", block_type: @block_type) %></h1>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<div data-loading-message class="tile tile-muted text-center mt-3">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
@ -18,10 +22,15 @@
<div data-empty-response-message style="display: none;">
<span><%= gettext "There are no blocks." %></span>
</div>
</span>
<a href="#" class="button button-secondary button-small float-right mt-4" data-next-page-button style="display: none;">
<%= gettext("Older") %>
</a>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a href="#" class="button button-secondary button-small float-right mt-4" data-next-page-button style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div class="button button-secondary button-small float-right mt-4" data-loading-button style="display: none;">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
@ -29,6 +38,7 @@
</span>
<%= gettext("Loading") %>...
</div>
</div>
</div>
</section>

@ -20,8 +20,10 @@
<!-- # of Transactions -->
<span class="mr-4"> <%= gettext "%{count} Transactions", count: @block_transaction_count %> </span>
<%= if @block.size do %>
<!-- Block Size -->
<span class="mr-4"> <%= Cldr.Unit.new(:byte, @block.size) |> cldr_unit_to_string!() %> </span>
<span class="mr-4"> <%= Cldr.Unit.new(:byte, @block.size) |> cldr_unit_to_string!() %> </span>
<% end %>
<!-- Block Age -->
<span class="mr-4" data-from-now="<%= @block.timestamp %>"></span>

@ -15,6 +15,15 @@
</div>
<div class="card-body">
<h2 class="card-title"><%= gettext "Transactions" %></h2>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_path(@conn, :index, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.count(@transactions) > 0 do %>
<span data-selector="transactions-list">
<%= for transaction <- @transactions do %>
@ -27,6 +36,15 @@
</div>
<% end %>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_path(@conn, :index, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!--
<%= if @next_page_params do %>
<%= link(
gettext("Older"),
@ -38,6 +56,7 @@
)
) %>
<% end %>
-->
</div>
</div>
</section>

@ -1,9 +0,0 @@
<ul class="pagination">
<li class="page-item"><a class="page-link" href="#"><</a></li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">...</a></li>
<li class="page-item"><a class="page-link" href="#">12</a></li>
<li class="page-item"><a class="page-link" href="#">></a></li>
</ul>

@ -0,0 +1,60 @@
<div class='pagination-container <%= if assigns[:position] == "top" do %>position-top<% end %> <%= if assigns[:position] == "bottom" do %>position-bottom<% end %>'>
<%= if assigns[:show_pagination_limit] do %>
<!-- Pagination limit -->
<div class="pagination-limit">
<%= gettext "Show" %>
<select>
<option>20</option>
<option>50</option>
<option>100</option>
</select>
<%= gettext "Records" %>
</div>
<% end %>
<!-- Pagination -->
<ul class="pagination">
<!-- First -->
<li class="page-item">
<a
<%= if !assigns[:first_page_path] do %>disabled<% end %>
class="page-link"
href='<%= "#{assigns[:first_page_path]}" %>'
>First</a>
</li>
<!-- Previous -->
<li class="page-item">
<a
<%= if !assigns[:prev_page_path] do %>disabled<% end %>
class="page-link"
href='<%= "#{assigns[:prev_page_path]}" %>'
>
<svg xmlns="http://www.w3.org/2000/svg" width="6" height="10">
<path fill-rule="evenodd" d="M2.358 5l3.357 3.358a.959.959 0 1 1-1.357 1.357L.502 5.859c-.076-.042-.153-.08-.217-.144A.949.949 0 0 1 .011 5a.949.949 0 0 1 .274-.715c.064-.064.142-.102.217-.145L4.358.285a.959.959 0 1 1 1.357 1.357L2.358 5z"/>
</svg>
</a>
</li>
<!-- Page X of XX -->
<li class="page-item"><a class="page-link no-hover" href><%= gettext "Page" %> <%= assigns[:cur_page_number] || "" %> <% if assigns[:total_pages_number] do %> <%= gettext "of" %> <%= assigns[:total_pages_number] || "undefined" %><% end %></a></li>
<!-- Next -->
<li class="page-item">
<a
<%= if !assigns[:next_page_path] do %>disabled<% end %>
class="page-link"
href='<%= "#{assigns[:next_page_path]}" %>'
<%= if assigns[:data_next_page_button] do %>data-next-page-button<% end %>
>
<svg xmlns="http://www.w3.org/2000/svg" width="6" height="10">
<path fill-rule="evenodd" d="M5.715 5.715c-.064.064-.141.102-.217.144L1.642 9.715A.959.959 0 1 1 .285 8.358L3.642 5 .285 1.642A.959.959 0 1 1 1.642.285L5.498 4.14c.075.043.153.081.217.145A.949.949 0 0 1 5.989 5a.949.949 0 0 1-.274.715z"/>
</svg>
</a>
</li>
<!-- Last -->
<li class="page-item">
<a
<%= if !assigns[:last_page_path] do %>disabled<% end %>
class="page-link"
href='<%= "#{assigns[:last_page_path]}" %>'
>Last</a>
</li>
</ul>
</div>

@ -37,7 +37,7 @@
<li><a href="https://forum.poa.network/c/blockscout" rel="noreferrer" class="footer-link"><%= gettext("Support") %></a></li>
</ul>
</div>
<% main_nets = main_nets() %>
<% main_nets = main_nets(other_networks()) %>
<%= unless Enum.empty?(main_nets) do %>
<div class="col-md-<%= col_size %> footer-list">
@ -50,7 +50,7 @@
</div>
<% end %>
<% test_nets = test_nets() %>
<% test_nets = test_nets(other_networks()) %>
<%= unless Enum.empty?(test_nets) do %>
<div class="col-md-<%= col_size %> footer-list">

@ -85,15 +85,15 @@
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item header division">Mainnets</a>
<%= for %{url: url, title: title} <- head_main_nets() do %>
<%= for %{url: url, title: title} <- dropdown_head_main_nets() do %>
<a class="dropdown-item" href="<%= url%>"><%= title %></a>
<% end %>
<a class="dropdown-item header division">Testnets</a>
<%= for %{url: url, title: title} <- test_nets() do %>
<%= for %{url: url, title: title} <- test_nets(dropdown_nets()) do %>
<a class="dropdown-item" href="<%= url%>"><%= title %></a>
<% end %>
<a class="dropdown-item header division">Other networks</a>
<%= for %{url: url, title: title} <- other_nets() do %>
<%= for %{url: url, title: title} <- dropdown_other_nets() do %>
<a class="dropdown-item" href="<%= url%>"><%= title %></a>
<% end %>
</div>
@ -112,9 +112,8 @@
"data-test": "search_input"
],
[ url: "#{chain_path(@conn, :token_autocomplete)}?q=",
prepop: true,
minChars: 3,
maxItems: 8,
limit: 0,
minChars: 2,
value: "contract_address_hash",
label: "contract_address_hash",
descrSearch: true,

@ -1,12 +1,10 @@
<section class="container" data-page="transaction-pending-list">
<div class="card">
<div class="card-body" data-async-listing="<%= @current_path %>">
<h1 class="card-title margin-bottom-0"><%= gettext "Pending Transactions" %></h1>
<p class="card-subtitle">
<%= gettext("Showing") %>
<span data-selector="transaction-pending-count"><%= Cldr.Number.to_string!(@pending_transaction_count, format: "#,###") %></span>
<%= gettext("Pending Transactions") %>
</p>
<h1 class="card-title"><%= gettext "Pending Transactions" %></h1>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<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>
@ -33,9 +31,15 @@
</span>
<%= gettext("Loading") %>...
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a href="#" class="button button-secondary button-small float-right mt-4" data-next-page-button style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div class="button button-secondary button-small float-right mt-4" data-loading-button style="display: none;">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>

@ -13,14 +13,19 @@
<%= render OverviewView, "_tabs.html", assigns %>
<div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Token Transfers" %></h2>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
</button>
<div data-empty-response-message class="tile tile-muted text-center" style="display: none;">
<span data-selector="empty-transactions-list">
<%= gettext "There are no transfers for this Token." %>
</span>
</div>
<div data-loading-message class="tile tile-muted text-center mt-3">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
@ -28,11 +33,17 @@
</span>
<%= gettext("Loading") %>...
</div>
<div data-items>
</div>
<div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a href="#" class="button button-secondary button-small float-right mt-4" data-next-page-button style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div class="button button-secondary button-small float-right mt-4" data-loading-button style="display: none;">
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>

@ -22,7 +22,7 @@
%>
<%= link(
gettext("Raw Trace"),
class: "nav-link #{tab_status("raw_trace", @conn.request_path)}",
class: "card-tab #{tab_status("raw_trace", @conn.request_path)}",
to: transaction_raw_trace_path(@conn, :index, @transaction)
) %>
</div>

@ -1,12 +1,10 @@
<section class="container" data-page="transaction-list">
<div class="card">
<div class="card-body" data-async-listing="<%= @current_path %>">
<h1 class="card-title margin-bottom-0"><%= gettext "Validated Transactions" %></h1>
<p class="card-subtitle">
<%= gettext("Showing") %>
<span data-selector="transaction-count"><%= Cldr.Number.to_string!(@transaction_estimated_count, format: "#,###") %></span>
<%= gettext("Validated Transactions") %>
</p>
<h1 class="card-title"><%= gettext "Validated Transactions" %></h1>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<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>
@ -40,9 +38,13 @@
<div data-selector="transactions-list" data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true %>
<!--
<a href="#" data-next-page-button class="button button-secondary button-small float-right mt-4" style="display: none;">
<%= gettext("Older") %>
</a>
-->
<div class="button button-secondary button-small float-right mt-4" data-loading-button style="display: none;">
<span class="loading-spinner-small mr-2">

@ -4,6 +4,15 @@
<%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %>
<div class="card-body">
<h2 class="card-title"><%= gettext "Internal Transactions" %></h2>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_internal_transaction_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.count(@internal_transactions) > 0 do %>
<%= for internal_transaction <- @internal_transactions do %>
<%= render BlockScoutWeb.InternalTransactionView, "_tile.html", internal_transaction: internal_transaction %>
@ -14,6 +23,15 @@
</div>
<% end %>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_internal_transaction_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!--
<%= if @next_page_params do %>
<%= link(
gettext("Newer"),
@ -26,6 +44,7 @@
)
) %>
<% end %>
-->
</div>
</div>
</section>

@ -6,6 +6,15 @@
<div class="card-body">
<h2 class="card-title"><%= gettext "Logs" %></h2>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_log_path(@conn,:index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.count(@logs) > 0 do %>
<%= for log <- @logs do %>
<div data-test="transaction_log" class="tile tile-muted">
@ -139,6 +148,15 @@
</div>
<% end %>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_log_path(@conn,:index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!--
<%= if @next_page_params do %>
<%= link(
gettext("Newer"),
@ -151,6 +169,7 @@
)
) %>
<% end %>
-->
</div>
</div>
</section>

@ -2,16 +2,15 @@
<%= render BlockScoutWeb.TransactionView, "overview.html", assigns %>
<div class="card">
<div class="card-header">
<%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %>
</div>
<%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %>
<div class="card-body">
<h2 class="card-title"><%= gettext "Raw Trace" %></h2>
<%= if Enum.count(@internal_transactions) > 0 do %>
<pre class="pre-scrollable line-numbers" data-activate-highlight><code class="json "><%= for {line, number} <- raw_traces_with_lines(@internal_transactions) do %><div data-line-number="<%= number %>"><%= line %></div><% end %></code></pre>
<% else %>
No trace entries found.
<div class="tile tile-muted text-center">
<span>No trace entries found.</span>
</div>
<% end %>
</div>
</div>

@ -5,6 +5,15 @@
<%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %>
<div class="card-body">
<h2 class="card-title"><%= gettext "Token Transfers" %></h2>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_token_transfer_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.any?(@token_transfers) do %>
<%= for token_transfer <- @token_transfers do %>
<%= render "_token_transfer.html", token_transfer: token_transfer, conn: @conn %>
@ -14,18 +23,29 @@
<span><%= gettext "There are no token transfers for this transaction." %></span>
</div>
<% end %>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_token_transfer_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!--
<%= if @next_page_params do %>
<%= link(
gettext("Older"),
class: "button button-secondary button-sm u-float-left mt-3",
to: transaction_token_transfer_path(
@conn,
:index,
@transaction,
@next_page_params
)
) %>
<% end %>
-->
</div>
</div>
<%= if @next_page_params do %>
<%= link(
gettext("Older"),
class: "button button-secondary button-sm u-float-left mt-3",
to: transaction_token_transfer_path(
@conn,
:index,
@transaction,
@next_page_params
)
) %>
<% end %>
</section>

@ -1,6 +1,8 @@
defmodule BlockScoutWeb.AddressContractView do
use BlockScoutWeb, :view
alias Explorer.Chain.{Address, Data, InternalTransaction}
def render("scripts.html", %{conn: conn}) do
render_scripts(conn, "address_contract/code_highlighting.js")
end
@ -34,4 +36,15 @@ defmodule BlockScoutWeb.AddressContractView do
{value, String.pad_leading(to_string(line), max_digits, " ")}
end)
end
def contract_creation_code(%Address{
contract_code: %Data{bytes: <<>>},
contracts_creation_internal_transaction: %InternalTransaction{init: init}
}) do
{:selfdestructed, init}
end
def contract_creation_code(%Address{contract_code: contract_code}) do
{:ok, contract_code}
end
end

@ -2,32 +2,234 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do
use BlockScoutWeb, :view
@colors %{
"\e[95m" => "136, 0, 0",
"\e[95m" => "",
# red
"\e[91m" => "236, 89, 58",
"\e[91m" => "",
# gray
"\e[38;5;8m" => "111, 110, 111",
"\e[38;5;8m" => "<span style=\"color:rgb(111, 110, 111)\">",
# green
"\e[32m" => "57, 115, 0",
"\e[32m" => "",
# yellowgreen
"\e[93m" => "57, 115, 0",
"\e[93m" => "",
# yellow
"\e[92m" => "119, 232, 81",
"\e[92m" => "",
# red
"\e[94m" => "136, 0, 0"
"\e[94m" => ""
}
@comment_start "#"
@reserved_words_types [
"var",
"bool",
"string",
"int",
"uint",
"int8",
"uint8",
"int16",
"uint16",
"int24",
"uint24",
"int32",
"uint32",
"int40",
"uint40",
"int48",
"uint48",
"int56",
"uint56",
"int64",
"uint64",
"int72",
"uint72",
"int80",
"uint80",
"int88",
"uint88",
"int96",
"uint96",
"int104",
"uint104",
"int112",
"uint112",
"int120",
"uint120",
"int128",
"uint128",
"int136",
"uint136",
"int144",
"uint144",
"int152",
"uint152",
"int160",
"uint160",
"int168",
"uint168",
"int176",
"uint176",
"int184",
"uint184",
"int192",
"uint192",
"int200",
"uint200",
"int208",
"uint208",
"int216",
"uint216",
"int224",
"uint224",
"int232",
"uint232",
"int240",
"uint240",
"int248",
"uint248",
"int256",
"uint256",
"byte",
"bytes",
"bytes1",
"bytes2",
"bytes3",
"bytes4",
"bytes5",
"bytes6",
"bytes7",
"bytes8",
"bytes9",
"bytes10",
"bytes11",
"bytes12",
"bytes13",
"bytes14",
"bytes15",
"bytes16",
"bytes17",
"bytes18",
"bytes19",
"bytes20",
"bytes21",
"bytes22",
"bytes23",
"bytes24",
"bytes25",
"bytes26",
"bytes27",
"bytes28",
"bytes29",
"bytes30",
"bytes31",
"bytes32",
"true",
"false",
"enum",
"struct",
"mapping",
"address"
]
@reserved_words_keywords [
"def",
"require",
"revert",
"return",
"assembly",
"memory",
"mem"
]
@modifiers [
"payable",
"public",
"view",
"pure",
"returns",
"internal"
]
@reserved_words @reserved_words_keywords ++ @reserved_words_types
@reserved_words_regexp ([@comment_start | @reserved_words] ++ @modifiers)
|> Enum.reduce("", fn el, acc -> acc <> "|" <> el end)
|> Regex.compile!()
def highlight_decompiled_code(code) do
@colors
|> Enum.reduce(code, fn {symbol, rgb}, acc ->
String.replace(acc, symbol, "<span style=\"color:rgb(#{rgb})\">")
{_, result} =
@colors
|> Enum.reduce(code, fn {symbol, rgb}, acc ->
String.replace(acc, symbol, rgb)
end)
|> String.replace("\e[1m", "<span style=\"font-weight:bold\">")
|> String.replace("»", "&raquo;")
|> String.replace("\e[0m", "</span>")
|> String.split(~r/\<span style=.*?\)"\>|\<span style=\"font-weight:bold\"\>|\<\/span\>/,
include_captures: true,
trim: true
)
|> add_styles_to_every_line()
result
|> Enum.reduce("", fn part, acc ->
part <> acc
end)
|> String.replace("\e[1m", "<span style=\"font-weight:bold\">")
|> String.replace("»", "&raquo;")
|> String.replace("\e[0m", "</span>")
|> add_styles_to_reserved_words()
|> add_line_numbers()
end
defp add_styles_to_every_line(lines) do
lines
|> Enum.reduce({"", []}, fn part, {style, acc} ->
new_style =
cond do
String.contains?(part, "<span style") -> part
part == "</span>" -> ""
true -> style
end
new_part = new_part(part, new_style)
{new_style, [new_part | acc]}
end)
end
defp add_styles_to_reserved_words(code) do
code
|> String.split("\n")
|> Enum.map(fn line ->
add_styles_to_line(line)
end)
|> Enum.reduce("", fn el, acc ->
acc <> el <> "\n"
end)
end
defp add_styles_to_line(line) do
parts =
line
|> String.split(@reserved_words_regexp,
include_captures: true
)
comment_position = Enum.find_index(parts, fn part -> part == "#" end)
parts
|> Enum.with_index()
|> Enum.map(fn {el, index} ->
cond do
!(is_nil(comment_position) || comment_position > index) -> el
el in @reserved_words -> "<span class=\"hljs-keyword\">" <> el <> "</span>"
el in @modifiers -> "<span class=\"hljs-title\">" <> el <> "</span>"
true -> el
end
end)
|> Enum.reduce("", fn el, acc ->
acc <> el
end)
end
def sort_contracts_by_version(decompiled_contracts) do
decompiled_contracts
|> Enum.sort_by(& &1.decompiler_version)
@ -41,4 +243,28 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do
acc <> "<code>#{line}</code>\n"
end)
end
defp new_part(part, new_style) do
cond do
part == "" ->
""
part == "</span>" ->
""
part == new_style ->
""
new_style == "" ->
part
true ->
part
|> String.split("\n")
|> Enum.reduce("", fn p, a ->
a <> new_style <> p <> "</span>\n"
end)
|> String.slice(0..-2)
end
end
end

@ -0,0 +1,3 @@
defmodule BlockScoutWeb.AddressLogsView do
use BlockScoutWeb, :view
end

@ -308,6 +308,7 @@ defmodule BlockScoutWeb.AddressView do
defp tab_name(["read_contract"]), do: gettext("Read Contract")
defp tab_name(["coin_balances"]), do: gettext("Coin Balance History")
defp tab_name(["validations"]), do: gettext("Blocks Validated")
defp tab_name(["logs"]), do: gettext("Logs")
def short_hash(%Address{hash: hash}) do
<<

@ -17,13 +17,7 @@ defmodule BlockScoutWeb.API.RPC.AddressView do
end
def render("balancemulti.json", %{addresses: addresses}) do
data =
Enum.map(addresses, fn address ->
%{
"account" => "#{address.hash}",
"balance" => balance(address)
}
end)
data = Enum.map(addresses, &render_address/1)
RPCView.render("show.json", data: data)
end
@ -61,10 +55,19 @@ defmodule BlockScoutWeb.API.RPC.AddressView do
RPCView.render("error.json", assigns)
end
defp render_address(address) do
%{
"account" => "#{address.hash}",
"balance" => balance(address),
"stale" => address.stale? || false
}
end
defp prepare_account(address) do
%{
"balance" => to_string(address.fetched_coin_balance.value),
"address" => to_string(address.hash)
"balance" => to_string(address.fetched_coin_balance && address.fetched_coin_balance.value),
"address" => to_string(address.hash),
"stale" => address.stale? || false
}
end

@ -1,7 +1,7 @@
defmodule BlockScoutWeb.API.RPC.BlockView do
use BlockScoutWeb, :view
alias BlockScoutWeb.API.RPC.RPCView
alias BlockScoutWeb.API.RPC.{EthRPCView, RPCView}
alias Explorer.Chain.{Hash, Wei}
def render("block_reward.json", %{block: block, reward: reward}) do
@ -22,7 +22,33 @@ defmodule BlockScoutWeb.API.RPC.BlockView do
RPCView.render("show.json", data: data)
end
def render("eth_block_number.json", %{number: number, id: id}) do
result = encode_quantity(number)
EthRPCView.render("show.json", %{result: result, id: id})
end
def render("error.json", %{error: error}) do
RPCView.render("error.json", error: error)
end
defp encode_quantity(binary) when is_binary(binary) do
hex_binary = Base.encode16(binary, case: :lower)
result = String.replace_leading(hex_binary, "0", "")
final_result = if result == "", do: "0", else: result
"0x#{final_result}"
end
defp encode_quantity(value) when is_integer(value) do
value
|> :binary.encode_unsigned()
|> encode_quantity()
end
defp encode_quantity(value) when is_nil(value) do
nil
end
end

@ -14,43 +14,63 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
RPCView.render("show.json", data: Jason.encode!(abi))
end
def render("getsourcecode.json", %{contract: contract, address_hash: address_hash}) do
RPCView.render("show.json", data: [prepare_source_code_contract(contract, address_hash)])
def render("getsourcecode.json", %{contract: contract}) do
RPCView.render("show.json", data: [prepare_source_code_contract(contract)])
end
def render("error.json", assigns) do
RPCView.render("error.json", assigns)
end
def render("verify.json", %{contract: contract, address_hash: address_hash}) do
RPCView.render("show.json", data: prepare_source_code_contract(contract, address_hash))
def render("verify.json", %{contract: contract}) do
RPCView.render("show.json", data: prepare_source_code_contract(contract))
end
defp prepare_source_code_contract(nil, address_hash) do
defp prepare_source_code_contract(nil) do
%{
"Address" => to_string(address_hash),
"Address" => "",
"SourceCode" => "",
"ABI" => "Contract source code not verified",
"ContractName" => "",
"CompilerVersion" => "",
"DecompiledSourceCode" => "",
"DecompilerVersion" => "",
"DecompilerVersion" => decompiler_version(nil),
"OptimizationUsed" => ""
}
end
defp prepare_source_code_contract(contract, _) do
decompiled_smart_contract = latest_decompiled_smart_contract(contract.decompiled_smart_contracts)
defp prepare_source_code_contract(address) do
decompiled_smart_contract = latest_decompiled_smart_contract(address.decompiled_smart_contracts)
contract = address.smart_contract || %{}
contract_abi =
if is_nil(address.smart_contract) do
"Contract source code not verified"
else
Jason.encode!(contract.abi)
end
contract_optimization =
case Map.get(contract, :optimization, "") do
true ->
"1"
false ->
"0"
"" ->
""
end
%{
"Address" => to_string(contract.address_hash),
"SourceCode" => contract.contract_source_code,
"ABI" => Jason.encode!(contract.abi),
"ContractName" => contract.name,
"Address" => to_string(address.hash),
"SourceCode" => Map.get(contract, :contract_source_code, ""),
"ABI" => contract_abi,
"ContractName" => Map.get(contract, :name, ""),
"DecompiledSourceCode" => decompiled_source_code(decompiled_smart_contract),
"DecompilerVersion" => decompiler_version(decompiled_smart_contract),
"CompilerVersion" => contract.compiler_version,
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0")
"CompilerVersion" => Map.get(contract, :compiler_version, ""),
"OptimizationUsed" => contract_optimization
}
end
@ -63,10 +83,8 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
%{
"Address" => to_string(hash),
"SourceCode" => "",
"ABI" => "Contract source code not verified",
"ContractName" => "",
"DecompiledSourceCode" => decompiled_source_code(decompiled_smart_contract),
"DecompilerVersion" => decompiler_version(decompiled_smart_contract),
"CompilerVersion" => "",
"OptimizationUsed" => ""
@ -82,10 +100,8 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
%{
"Address" => to_string(hash),
"SourceCode" => contract.contract_source_code,
"ABI" => Jason.encode!(contract.abi),
"ContractName" => contract.name,
"DecompiledSourceCode" => decompiled_source_code(decompiled_smart_contract),
"DecompilerVersion" => decompiler_version(decompiled_smart_contract),
"CompilerVersion" => contract.compiler_version,
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0")

@ -0,0 +1,33 @@
defmodule BlockScoutWeb.API.RPC.EthRPCView do
use BlockScoutWeb, :view
defstruct [:result, :id, :error]
def render("show.json", %{result: result, id: id}) do
%__MODULE__{
result: result,
id: id
}
end
def render("error.json", %{error: message, id: id}) do
%__MODULE__{
error: message,
id: id
}
end
defimpl Poison.Encoder, for: BlockScoutWeb.API.RPC.EthRPCView do
def encode(%BlockScoutWeb.API.RPC.EthRPCView{result: result, id: id, error: error}, _options) when is_nil(error) do
"""
{"jsonrpc":"2.0","result":"#{result}","id":#{id}}
"""
end
def encode(%BlockScoutWeb.API.RPC.EthRPCView{id: id, error: error}, _options) do
"""
{"jsonrpc":"2.0","error": #{error},"id": #{id}}
"""
end
end
end

@ -77,7 +77,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionView do
%{
"address" => "#{log.address_hash}",
"topics" => get_topics(log),
"data" => "#{log.data}"
"data" => "#{log.data}",
"index" => "#{log.index}"
}
end

@ -2,8 +2,68 @@ defmodule BlockScoutWeb.LayoutView do
use BlockScoutWeb, :view
alias Plug.Conn
alias Poison.Parser
@issue_url "https://github.com/poanetwork/blockscout/issues/new"
@default_other_networks [
%{
title: "POA Core",
url: "https://blockscout.com/poa/core"
},
%{
title: "POA Sokol",
url: "https://blockscout.com/poa/sokol",
test_net?: true
},
%{
title: "xDai Chain",
url: "https://blockscout.com/poa/dai"
},
%{
title: "Ethereum Mainnet",
url: "https://blockscout.com/eth/mainnet"
},
%{
title: "Kovan Testnet",
url: "https://blockscout.com/eth/kovan",
test_net?: true
},
%{
title: "Ropsten Testnet",
url: "https://blockscout.com/eth/ropsten",
test_net?: true
},
%{
title: "Goerli Testnet",
url: "https://blockscout.com/eth/goerli",
test_net?: true
},
%{
title: "Rinkeby Testnet",
url: "https://blockscout.com/eth/rinkeby",
test_net?: true
},
%{
title: "Ethereum Classic",
url: "https://blockscout.com/etc/mainnet",
other?: true
},
%{
title: "Aerum Mainnet",
url: "https://blockscout.com/aerum/mainnet",
other?: true
},
%{
title: "Callisto Mainnet",
url: "https://blockscout.com/callisto/mainnet",
other?: true
},
%{
title: "RSK Mainnet",
url: "https://blockscout.com/rsk/mainnet",
other?: true
}
]
alias BlockScoutWeb.SocialMedia
@ -82,10 +142,22 @@ defmodule BlockScoutWeb.LayoutView do
end
def release_link(version) do
release_link = Application.get_env(:block_scout_web, :release_link)
release_link_env_var = Application.get_env(:block_scout_web, :release_link)
if release_link == "" || release_link == nil do
version
release_link =
cond do
version == "" || version == nil ->
nil
release_link_env_var == "" || release_link_env_var == nil ->
"https://github.com/poanetwork/blockscout/releases/tag/" <> version
true ->
release_link_env_var
end
if release_link == nil do
""
else
html_escape({:safe, "<a href=\"#{release_link}\" class=\"footer-link\" target=\"_blank\">#{version}</a>"})
end
@ -95,29 +167,47 @@ defmodule BlockScoutWeb.LayoutView do
def ignore_version?(_), do: false
def other_networks do
:block_scout_web
|> Application.get_env(:other_networks, [])
get_other_networks =
if Application.get_env(:block_scout_web, :other_networks) do
:block_scout_web
|> Application.get_env(:other_networks)
|> Parser.parse!(%{keys: :atoms!})
else
@default_other_networks
end
get_other_networks
|> Enum.reject(fn %{title: title} ->
title == subnetwork_title()
end)
|> Enum.sort()
end
def main_nets do
Enum.reject(other_networks(), &Map.get(&1, :test_net?))
def main_nets(nets) do
nets
|> Enum.reject(&Map.get(&1, :test_net?))
end
def head_main_nets do
main_nets()
|> Enum.reject(&Map.get(&1, :other?))
def test_nets(nets) do
nets
|> Enum.filter(&Map.get(&1, :test_net?))
end
def test_nets do
Enum.filter(other_networks(), &Map.get(&1, :test_net?))
def dropdown_nets do
other_networks()
|> Enum.reject(&Map.get(&1, :hide_in_dropdown?))
end
def dropdown_head_main_nets do
dropdown_nets()
|> main_nets()
|> Enum.reject(&Map.get(&1, :other?))
end
def other_nets do
Enum.filter(other_networks(), &Map.get(&1, :other?))
def dropdown_other_nets do
dropdown_nets()
|> main_nets()
|> Enum.filter(&Map.get(&1, :other?))
end
def other_explorers do

@ -28,7 +28,7 @@ msgid "%{block_type} Height:"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/index.html.eex:9
#: lib/block_scout_web/templates/block/index.html.eex:10
msgid "%{block_type}s"
msgstr ""
@ -98,7 +98,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:13
#: lib/block_scout_web/templates/transaction_log/index.html.eex:22
#: lib/block_scout_web/views/address_view.ex:101
msgid "Address"
msgstr ""
@ -110,8 +110,8 @@ msgid "Addresses"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:25
#: lib/block_scout_web/templates/address_transaction/index.html.eex:21
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:27
#: lib/block_scout_web/templates/address_transaction/index.html.eex:23
#: lib/block_scout_web/views/address_internal_transaction_view.ex:8
#: lib/block_scout_web/views/address_transaction_view.ex:8
msgid "All"
@ -187,7 +187,7 @@ msgid "Blocks Indexed"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:27
#: lib/block_scout_web/templates/address/_tabs.html.eex:32
#: lib/block_scout_web/templates/address/overview.html.eex:95
#: lib/block_scout_web/templates/address_validation/index.html.eex:13
#: lib/block_scout_web/views/address_view.ex:310
@ -215,7 +215,7 @@ msgid "Close"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:37
#: lib/block_scout_web/templates/address/_tabs.html.eex:42
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:165
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187
#: lib/block_scout_web/views/address_view.ex:306
@ -228,7 +228,7 @@ msgid "Compiler"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:23
#: lib/block_scout_web/templates/address_contract/index.html.eex:30
msgid "Compiler version"
msgstr ""
@ -245,8 +245,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:11
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:17
#: lib/block_scout_web/templates/transaction/index.html.eex:17
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:15
#: lib/block_scout_web/templates/transaction/index.html.eex:15
msgid "Connection Lost, click to load newer transactions"
msgstr ""
@ -256,7 +256,7 @@ msgid "Connection Lost, click to load newer validations"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:46
#: lib/block_scout_web/templates/address_contract/index.html.eex:53
msgid "Contract ABI"
msgstr ""
@ -289,17 +289,12 @@ msgid "Contract Name"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:60
msgid "Contract creation code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:19
#: lib/block_scout_web/templates/address_contract/index.html.eex:26
msgid "Contract name:"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:34
#: lib/block_scout_web/templates/address_contract/index.html.eex:41
msgid "Contract source code"
msgstr ""
@ -334,9 +329,10 @@ msgid "Curl"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:63
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
#: lib/block_scout_web/templates/transaction_log/index.html.eex:58
#: lib/block_scout_web/templates/transaction_log/index.html.eex:124
#: lib/block_scout_web/templates/transaction_log/index.html.eex:67
#: lib/block_scout_web/templates/transaction_log/index.html.eex:133
msgid "Data"
msgstr ""
@ -353,7 +349,7 @@ msgid "Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:56
#: lib/block_scout_web/templates/block/overview.html.eex:58
msgid "Difficulty"
msgstr ""
@ -414,8 +410,8 @@ msgid "Forked Blocks (Reorgs)"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:42
#: lib/block_scout_web/templates/address_transaction/index.html.eex:38
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:44
#: lib/block_scout_web/templates/address_transaction/index.html.eex:40
#: lib/block_scout_web/views/address_internal_transaction_view.ex:7
#: lib/block_scout_web/views/address_transaction_view.ex:7
msgid "From"
@ -427,16 +423,16 @@ msgid "GET"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:54
#: lib/block_scout_web/templates/block/overview.html.eex:103
#: lib/block_scout_web/templates/block/overview.html.eex:150
#: lib/block_scout_web/templates/block/_tile.html.eex:56
#: lib/block_scout_web/templates/block/overview.html.eex:105
#: lib/block_scout_web/templates/block/overview.html.eex:152
msgid "Gas Limit"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:59
#: lib/block_scout_web/templates/block/overview.html.eex:96
#: lib/block_scout_web/templates/block/overview.html.eex:144
#: lib/block_scout_web/templates/block/_tile.html.eex:61
#: lib/block_scout_web/templates/block/overview.html.eex:98
#: lib/block_scout_web/templates/block/overview.html.eex:146
msgid "Gas Used"
msgstr ""
@ -452,7 +448,7 @@ msgid "Gwei"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:36
#: lib/block_scout_web/templates/block/overview.html.eex:38
msgid "Hash"
msgstr ""
@ -479,7 +475,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:14
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:55
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:19
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6
#: lib/block_scout_web/views/address_view.ex:305
@ -505,8 +501,11 @@ msgid "Limit"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:26
#: lib/block_scout_web/templates/address_logs/index.html.eex:8
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:303
#: lib/block_scout_web/views/transaction_view.ex:340
msgid "Logs"
msgstr ""
@ -524,8 +523,8 @@ msgid "Max of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:36
#: lib/block_scout_web/templates/block/overview.html.eex:119
#: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:121
#: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner"
msgstr ""
@ -547,8 +546,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:111
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:12
#: lib/block_scout_web/templates/transaction/index.html.eex:12
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:10
#: lib/block_scout_web/templates/transaction/index.html.eex:10
msgid "More transactions have come in"
msgstr ""
@ -561,7 +560,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:55
#: lib/block_scout_web/templates/transaction_log/index.html.eex:64
msgid "Name"
msgstr ""
@ -572,13 +571,13 @@ msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:19
#: lib/block_scout_web/templates/transaction_log/index.html.eex:144
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:37
#: lib/block_scout_web/templates/transaction_log/index.html.eex:162
msgid "Newer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:22
#: lib/block_scout_web/templates/address_token/index.html.eex:39
msgid "Next"
msgstr ""
@ -594,8 +593,8 @@ msgid "No"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:71
#: lib/block_scout_web/templates/transaction/overview.html.eex:80
#: lib/block_scout_web/templates/block/overview.html.eex:73
#: lib/block_scout_web/templates/transaction/overview.html.eex:77
msgid "Nonce"
msgstr ""
@ -606,22 +605,22 @@ msgid "OUT"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:52
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:73
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:28
#: lib/block_scout_web/templates/address_transaction/index.html.eex:72
#: lib/block_scout_web/templates/address_validation/index.html.eex:31
#: lib/block_scout_web/templates/block/index.html.eex:23
#: lib/block_scout_web/templates/block_transaction/index.html.eex:32
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:37
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:34
#: lib/block_scout_web/templates/transaction/index.html.eex:44
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:21
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:57
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:81
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:38
#: lib/block_scout_web/templates/address_transaction/index.html.eex:80
#: lib/block_scout_web/templates/address_validation/index.html.eex:38
#: lib/block_scout_web/templates/block/index.html.eex:30
#: lib/block_scout_web/templates/block_transaction/index.html.eex:50
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:39
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:43
#: lib/block_scout_web/templates/transaction/index.html.eex:45
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:38
msgid "Older"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:27
#: lib/block_scout_web/templates/address_contract/index.html.eex:34
msgid "Optimization enabled"
msgstr ""
@ -641,7 +640,7 @@ msgid "Parameters"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:43
#: lib/block_scout_web/templates/block/overview.html.eex:45
msgid "Parent Hash"
msgstr ""
@ -654,12 +653,11 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:4
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:8
msgid "Pending Transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:82
#: lib/block_scout_web/templates/block/overview.html.eex:84
msgid "Position %{index}"
msgstr ""
@ -683,7 +681,7 @@ msgid "Query"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:53
#: lib/block_scout_web/templates/address/_tabs.html.eex:58
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:25
#: lib/block_scout_web/views/address_view.ex:308
#: lib/block_scout_web/views/tokens/overview_view.ex:37
@ -712,7 +710,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:111
#: lib/block_scout_web/templates/layout/_topnav.html.eex:129
#: lib/block_scout_web/templates/layout/_topnav.html.eex:128
msgid "Search"
msgstr ""
@ -733,17 +731,6 @@ msgstr ""
msgid "Show QR Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:6
#: lib/block_scout_web/templates/transaction/index.html.eex:6
msgid "Showing"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
msgid "Showing 250 addresses of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:210
@ -768,33 +755,33 @@ msgid "There are no holders for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:65
msgid "There are no internal transactions for this address."
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:13
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:22
msgid "There are no internal transactions for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:138
#: lib/block_scout_web/templates/transaction_log/index.html.eex:147
msgid "There are no logs for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:19
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:23
msgid "There are no token transfers for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:14
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:23
msgid "There are no token transfers for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:15
#: lib/block_scout_web/templates/address_token/index.html.eex:24
msgid "There are no tokens for this address."
msgstr ""
@ -804,17 +791,17 @@ msgid "There are no tokens."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:57
#: lib/block_scout_web/templates/address_transaction/index.html.eex:62
msgid "There are no transactions for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block_transaction/index.html.eex:26
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35
msgid "There are no transactions for this block."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:21
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:25
msgid "There are no transfers for this Token."
msgstr ""
@ -824,8 +811,8 @@ msgid "This transaction is pending confirmation."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:31
#: lib/block_scout_web/templates/address_transaction/index.html.eex:27
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:33
#: lib/block_scout_web/templates/address_transaction/index.html.eex:29
#: lib/block_scout_web/views/address_internal_transaction_view.ex:6
#: lib/block_scout_web/views/address_transaction_view.ex:6
msgid "To"
@ -886,12 +873,13 @@ msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:94
#: lib/block_scout_web/templates/address_logs/index.html.eex:33
#: lib/block_scout_web/templates/transaction_log/index.html.eex:103
msgid "Topics"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:65
#: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty"
msgstr ""
@ -906,6 +894,7 @@ msgid "Total transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:22
#: lib/block_scout_web/views/transaction_view.ex:287
msgid "Transaction"
msgstr ""
@ -928,7 +917,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:3
#: lib/block_scout_web/templates/address_transaction/index.html.eex:50
#: lib/block_scout_web/templates/address_transaction/index.html.eex:15
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:17
#: lib/block_scout_web/templates/chain/show.html.eex:108
@ -958,7 +947,7 @@ msgid "Twitter"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:78
#: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/layout/_topnav.html.eex:23
msgid "Uncles"
msgstr ""
@ -980,7 +969,6 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/index.html.eex:4
#: lib/block_scout_web/templates/transaction/index.html.eex:8
msgid "Validated Transactions"
msgstr ""
@ -995,7 +983,8 @@ msgid "Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:9
#: lib/block_scout_web/templates/address_contract/index.html.eex:11
#: lib/block_scout_web/templates/address_contract/index.html.eex:16
msgid "Verify & Publish"
msgstr ""
@ -1060,7 +1049,7 @@ msgid "at"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/address_contract_view.ex:20
#: lib/block_scout_web/views/address_contract_view.ex:22
msgid "false"
msgstr ""
@ -1078,12 +1067,7 @@ msgid "string"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:8
msgid "total addresses with a balance"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/address_contract_view.ex:19
#: lib/block_scout_web/views/address_contract_view.ex:21
msgid "true"
msgstr ""
@ -1103,7 +1087,7 @@ msgid "Delegate Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:45
#: lib/block_scout_web/templates/block/_tile.html.eex:47
#: lib/block_scout_web/templates/chain/_block.html.eex:23
#: lib/block_scout_web/views/internal_transaction_view.ex:27
msgid "Reward"
@ -1121,9 +1105,9 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:14
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:16
#: lib/block_scout_web/templates/address_validation/index.html.eex:19
#: lib/block_scout_web/templates/address_validation/index.html.eex:38
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:19
#: lib/block_scout_web/templates/address_validation/index.html.eex:22
#: lib/block_scout_web/templates/address_validation/index.html.eex:47
#: lib/block_scout_web/templates/chain/show.html.eex:99
#: lib/block_scout_web/templates/chain/show.html.eex:125
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:21
@ -1146,22 +1130,22 @@ msgid "GraphQL"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:60
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:69
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:80
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:35
#: lib/block_scout_web/templates/address_transaction/index.html.eex:66
#: lib/block_scout_web/templates/address_transaction/index.html.eex:80
#: lib/block_scout_web/templates/block/index.html.eex:15
#: lib/block_scout_web/templates/block/index.html.eex:30
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:34
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:44
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:66
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:73
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:90
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:47
#: lib/block_scout_web/templates/address_transaction/index.html.eex:71
#: lib/block_scout_web/templates/address_transaction/index.html.eex:89
#: lib/block_scout_web/templates/block/index.html.eex:19
#: lib/block_scout_web/templates/block/index.html.eex:39
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:32
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:48
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:33
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:44
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:29
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:41
#: lib/block_scout_web/templates/transaction/index.html.eex:38
#: lib/block_scout_web/templates/transaction/index.html.eex:52
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:34
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:52
#: lib/block_scout_web/templates/transaction/index.html.eex:36
#: lib/block_scout_web/templates/transaction/index.html.eex:54
msgid "Loading"
msgstr ""
@ -1256,18 +1240,18 @@ msgid "Static Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:24
#: lib/block_scout_web/templates/transaction_log/index.html.eex:33
msgid "Decoded"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:57
#: lib/block_scout_web/templates/transaction_log/index.html.eex:66
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:56
#: lib/block_scout_web/templates/transaction_log/index.html.eex:65
msgid "Type"
msgstr ""
@ -1277,7 +1261,7 @@ msgid "Method Id"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:29
#: lib/block_scout_web/templates/transaction_log/index.html.eex:38
msgid "To see decoded input data, the contract must be verified."
msgstr ""
@ -1293,13 +1277,13 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:32
#: lib/block_scout_web/templates/transaction_log/index.html.eex:41
msgid "Verify the contract "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:32
#: lib/block_scout_web/templates/transaction_log/index.html.eex:41
msgid "here"
msgstr ""
@ -1315,41 +1299,41 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
#: lib/block_scout_web/templates/transaction_log/index.html.eex:68
#: lib/block_scout_web/templates/transaction_log/index.html.eex:77
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:39
#: lib/block_scout_web/templates/transaction_log/index.html.eex:48
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:52
#: lib/block_scout_web/templates/transaction_log/index.html.eex:61
msgid "Log Data"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:32
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:57
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:23
#: lib/block_scout_web/templates/address_transaction/index.html.eex:52
#: lib/block_scout_web/templates/address_validation/index.html.eex:26
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:28
#: lib/block_scout_web/templates/address_transaction/index.html.eex:57
#: lib/block_scout_web/templates/address_validation/index.html.eex:29
#: lib/block_scout_web/templates/chain/show.html.eex:91
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:21
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:19
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:19
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:17
#: lib/block_scout_web/templates/transaction/index.html.eex:22
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20
#: lib/block_scout_web/templates/transaction/index.html.eex:20
msgid "Something went wrong, click to reload."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_validation/index.html.eex:22
#: lib/block_scout_web/templates/address_validation/index.html.eex:25
msgid "There are no blocks validated by this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/index.html.eex:28
#: lib/block_scout_web/templates/transaction/index.html.eex:26
msgid "There are no transactions."
msgstr ""
@ -1370,34 +1354,34 @@ msgid "Coin Balance History"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:46
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:48
msgid "Loading balances"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:21
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:22
#: lib/block_scout_web/templates/chain/show.html.eex:13
msgid "Loading chart"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:37
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:39
msgid "There is no coin history for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:24
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:25
#: lib/block_scout_web/templates/chain/show.html.eex:16
msgid "There was a problem loading the chart."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:25
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:23
msgid "There are no pending transactions."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/index.html.eex:19
#: lib/block_scout_web/templates/block/index.html.eex:23
msgid "There are no blocks."
msgstr ""
@ -1432,7 +1416,7 @@ msgid "Validator Info"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:137
#: lib/block_scout_web/templates/block/overview.html.eex:139
msgid "Block Rewards"
msgstr ""
@ -1527,17 +1511,17 @@ msgid "Support"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:48
#: lib/block_scout_web/templates/address_contract/index.html.eex:55
msgid "Copy ABI"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:62
#: lib/block_scout_web/templates/address_contract/index.html.eex:71
msgid "Copy Contract Creation Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:36
#: lib/block_scout_web/templates/address_contract/index.html.eex:43
msgid "Copy Source Code"
msgstr ""
@ -1679,7 +1663,7 @@ msgid "Decompiled Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:47
#: lib/block_scout_web/templates/address/_tabs.html.eex:52
msgid "Decompiled code"
msgstr ""
@ -1708,11 +1692,6 @@ msgstr ""
msgid "ERC-721"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/api_docs/index.html.eex:4
msgid "API Documentation"
@ -1735,7 +1714,66 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:24
#: lib/block_scout_web/templates/transaction_raw_trace/index.html.eex:10
#: lib/block_scout_web/templates/transaction_raw_trace/index.html.eex:7
#: lib/block_scout_web/views/transaction_view.ex:341
msgid "Raw Trace"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:37
msgid "Page"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:11
msgid "Records"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:5
msgid "Show"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:37
msgid "of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:83
msgid "Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:69
msgid "Contract Creation Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:75
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:85
msgid "Copy Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:76
msgid "Displaying the init data provided of the creating transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:77
msgid "There are no logs for this address."
msgstr ""

@ -28,7 +28,7 @@ msgid "%{block_type} Height:"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/index.html.eex:9
#: lib/block_scout_web/templates/block/index.html.eex:10
msgid "%{block_type}s"
msgstr ""
@ -98,7 +98,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:13
#: lib/block_scout_web/templates/transaction_log/index.html.eex:22
#: lib/block_scout_web/views/address_view.ex:101
msgid "Address"
msgstr ""
@ -110,8 +110,8 @@ msgid "Addresses"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:25
#: lib/block_scout_web/templates/address_transaction/index.html.eex:21
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:27
#: lib/block_scout_web/templates/address_transaction/index.html.eex:23
#: lib/block_scout_web/views/address_internal_transaction_view.ex:8
#: lib/block_scout_web/views/address_transaction_view.ex:8
msgid "All"
@ -187,7 +187,7 @@ msgid "Blocks Indexed"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:27
#: lib/block_scout_web/templates/address/_tabs.html.eex:32
#: lib/block_scout_web/templates/address/overview.html.eex:95
#: lib/block_scout_web/templates/address_validation/index.html.eex:13
#: lib/block_scout_web/views/address_view.ex:310
@ -215,7 +215,7 @@ msgid "Close"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:37
#: lib/block_scout_web/templates/address/_tabs.html.eex:42
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:165
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187
#: lib/block_scout_web/views/address_view.ex:306
@ -228,7 +228,7 @@ msgid "Compiler"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:23
#: lib/block_scout_web/templates/address_contract/index.html.eex:30
msgid "Compiler version"
msgstr ""
@ -245,8 +245,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:11
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:17
#: lib/block_scout_web/templates/transaction/index.html.eex:17
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:15
#: lib/block_scout_web/templates/transaction/index.html.eex:15
msgid "Connection Lost, click to load newer transactions"
msgstr ""
@ -256,7 +256,7 @@ msgid "Connection Lost, click to load newer validations"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:46
#: lib/block_scout_web/templates/address_contract/index.html.eex:53
msgid "Contract ABI"
msgstr ""
@ -289,17 +289,12 @@ msgid "Contract Name"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:60
msgid "Contract creation code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:19
#: lib/block_scout_web/templates/address_contract/index.html.eex:26
msgid "Contract name:"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:34
#: lib/block_scout_web/templates/address_contract/index.html.eex:41
msgid "Contract source code"
msgstr ""
@ -334,9 +329,10 @@ msgid "Curl"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:63
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
#: lib/block_scout_web/templates/transaction_log/index.html.eex:58
#: lib/block_scout_web/templates/transaction_log/index.html.eex:124
#: lib/block_scout_web/templates/transaction_log/index.html.eex:67
#: lib/block_scout_web/templates/transaction_log/index.html.eex:133
msgid "Data"
msgstr ""
@ -353,7 +349,7 @@ msgid "Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:56
#: lib/block_scout_web/templates/block/overview.html.eex:58
msgid "Difficulty"
msgstr ""
@ -414,8 +410,8 @@ msgid "Forked Blocks (Reorgs)"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:42
#: lib/block_scout_web/templates/address_transaction/index.html.eex:38
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:44
#: lib/block_scout_web/templates/address_transaction/index.html.eex:40
#: lib/block_scout_web/views/address_internal_transaction_view.ex:7
#: lib/block_scout_web/views/address_transaction_view.ex:7
msgid "From"
@ -427,16 +423,16 @@ msgid "GET"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:54
#: lib/block_scout_web/templates/block/overview.html.eex:103
#: lib/block_scout_web/templates/block/overview.html.eex:150
#: lib/block_scout_web/templates/block/_tile.html.eex:56
#: lib/block_scout_web/templates/block/overview.html.eex:105
#: lib/block_scout_web/templates/block/overview.html.eex:152
msgid "Gas Limit"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:59
#: lib/block_scout_web/templates/block/overview.html.eex:96
#: lib/block_scout_web/templates/block/overview.html.eex:144
#: lib/block_scout_web/templates/block/_tile.html.eex:61
#: lib/block_scout_web/templates/block/overview.html.eex:98
#: lib/block_scout_web/templates/block/overview.html.eex:146
msgid "Gas Used"
msgstr ""
@ -452,7 +448,7 @@ msgid "Gwei"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:36
#: lib/block_scout_web/templates/block/overview.html.eex:38
msgid "Hash"
msgstr ""
@ -479,7 +475,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:14
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:55
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:19
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6
#: lib/block_scout_web/views/address_view.ex:305
@ -505,8 +501,11 @@ msgid "Limit"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:26
#: lib/block_scout_web/templates/address_logs/index.html.eex:8
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:303
#: lib/block_scout_web/views/transaction_view.ex:340
msgid "Logs"
msgstr ""
@ -524,8 +523,8 @@ msgid "Max of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:36
#: lib/block_scout_web/templates/block/overview.html.eex:119
#: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:121
#: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner"
msgstr ""
@ -547,8 +546,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:111
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:12
#: lib/block_scout_web/templates/transaction/index.html.eex:12
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:10
#: lib/block_scout_web/templates/transaction/index.html.eex:10
msgid "More transactions have come in"
msgstr ""
@ -561,7 +560,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:55
#: lib/block_scout_web/templates/transaction_log/index.html.eex:64
msgid "Name"
msgstr ""
@ -572,13 +571,13 @@ msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:19
#: lib/block_scout_web/templates/transaction_log/index.html.eex:144
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:37
#: lib/block_scout_web/templates/transaction_log/index.html.eex:162
msgid "Newer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:22
#: lib/block_scout_web/templates/address_token/index.html.eex:39
msgid "Next"
msgstr ""
@ -594,8 +593,8 @@ msgid "No"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:71
#: lib/block_scout_web/templates/transaction/overview.html.eex:80
#: lib/block_scout_web/templates/block/overview.html.eex:73
#: lib/block_scout_web/templates/transaction/overview.html.eex:77
msgid "Nonce"
msgstr ""
@ -606,22 +605,22 @@ msgid "OUT"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:52
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:73
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:28
#: lib/block_scout_web/templates/address_transaction/index.html.eex:72
#: lib/block_scout_web/templates/address_validation/index.html.eex:31
#: lib/block_scout_web/templates/block/index.html.eex:23
#: lib/block_scout_web/templates/block_transaction/index.html.eex:32
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:37
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:34
#: lib/block_scout_web/templates/transaction/index.html.eex:44
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:21
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:57
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:81
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:38
#: lib/block_scout_web/templates/address_transaction/index.html.eex:80
#: lib/block_scout_web/templates/address_validation/index.html.eex:38
#: lib/block_scout_web/templates/block/index.html.eex:30
#: lib/block_scout_web/templates/block_transaction/index.html.eex:50
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:39
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:43
#: lib/block_scout_web/templates/transaction/index.html.eex:45
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:38
msgid "Older"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:27
#: lib/block_scout_web/templates/address_contract/index.html.eex:34
msgid "Optimization enabled"
msgstr ""
@ -641,7 +640,7 @@ msgid "Parameters"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:43
#: lib/block_scout_web/templates/block/overview.html.eex:45
msgid "Parent Hash"
msgstr ""
@ -654,12 +653,11 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:4
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:8
msgid "Pending Transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:82
#: lib/block_scout_web/templates/block/overview.html.eex:84
msgid "Position %{index}"
msgstr ""
@ -683,7 +681,7 @@ msgid "Query"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:53
#: lib/block_scout_web/templates/address/_tabs.html.eex:58
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:25
#: lib/block_scout_web/views/address_view.ex:308
#: lib/block_scout_web/views/tokens/overview_view.ex:37
@ -712,7 +710,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:111
#: lib/block_scout_web/templates/layout/_topnav.html.eex:129
#: lib/block_scout_web/templates/layout/_topnav.html.eex:128
msgid "Search"
msgstr ""
@ -733,17 +731,6 @@ msgstr ""
msgid "Show QR Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:6
#: lib/block_scout_web/templates/transaction/index.html.eex:6
msgid "Showing"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
msgid "Showing 250 addresses of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:210
@ -768,33 +755,33 @@ msgid "There are no holders for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:65
msgid "There are no internal transactions for this address."
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:13
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:22
msgid "There are no internal transactions for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:138
#: lib/block_scout_web/templates/transaction_log/index.html.eex:147
msgid "There are no logs for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:19
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:23
msgid "There are no token transfers for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:14
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:23
msgid "There are no token transfers for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:15
#: lib/block_scout_web/templates/address_token/index.html.eex:24
msgid "There are no tokens for this address."
msgstr ""
@ -804,17 +791,17 @@ msgid "There are no tokens."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:57
#: lib/block_scout_web/templates/address_transaction/index.html.eex:62
msgid "There are no transactions for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block_transaction/index.html.eex:26
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35
msgid "There are no transactions for this block."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:21
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:25
msgid "There are no transfers for this Token."
msgstr ""
@ -824,8 +811,8 @@ msgid "This transaction is pending confirmation."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:31
#: lib/block_scout_web/templates/address_transaction/index.html.eex:27
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:33
#: lib/block_scout_web/templates/address_transaction/index.html.eex:29
#: lib/block_scout_web/views/address_internal_transaction_view.ex:6
#: lib/block_scout_web/views/address_transaction_view.ex:6
msgid "To"
@ -886,12 +873,13 @@ msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:94
#: lib/block_scout_web/templates/address_logs/index.html.eex:33
#: lib/block_scout_web/templates/transaction_log/index.html.eex:103
msgid "Topics"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:65
#: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty"
msgstr ""
@ -906,6 +894,7 @@ msgid "Total transactions"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:22
#: lib/block_scout_web/views/transaction_view.ex:287
msgid "Transaction"
msgstr ""
@ -928,7 +917,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:3
#: lib/block_scout_web/templates/address_transaction/index.html.eex:50
#: lib/block_scout_web/templates/address_transaction/index.html.eex:15
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:17
#: lib/block_scout_web/templates/chain/show.html.eex:108
@ -958,7 +947,7 @@ msgid "Twitter"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:78
#: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/layout/_topnav.html.eex:23
msgid "Uncles"
msgstr ""
@ -980,7 +969,6 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/index.html.eex:4
#: lib/block_scout_web/templates/transaction/index.html.eex:8
msgid "Validated Transactions"
msgstr ""
@ -995,7 +983,8 @@ msgid "Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:9
#: lib/block_scout_web/templates/address_contract/index.html.eex:11
#: lib/block_scout_web/templates/address_contract/index.html.eex:16
msgid "Verify & Publish"
msgstr ""
@ -1060,7 +1049,7 @@ msgid "at"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/address_contract_view.ex:20
#: lib/block_scout_web/views/address_contract_view.ex:22
msgid "false"
msgstr ""
@ -1078,12 +1067,7 @@ msgid "string"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:8
msgid "total addresses with a balance"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/address_contract_view.ex:19
#: lib/block_scout_web/views/address_contract_view.ex:21
msgid "true"
msgstr ""
@ -1103,7 +1087,7 @@ msgid "Delegate Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:45
#: lib/block_scout_web/templates/block/_tile.html.eex:47
#: lib/block_scout_web/templates/chain/_block.html.eex:23
#: lib/block_scout_web/views/internal_transaction_view.ex:27
msgid "Reward"
@ -1121,9 +1105,9 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:14
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:16
#: lib/block_scout_web/templates/address_validation/index.html.eex:19
#: lib/block_scout_web/templates/address_validation/index.html.eex:38
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:19
#: lib/block_scout_web/templates/address_validation/index.html.eex:22
#: lib/block_scout_web/templates/address_validation/index.html.eex:47
#: lib/block_scout_web/templates/chain/show.html.eex:99
#: lib/block_scout_web/templates/chain/show.html.eex:125
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:21
@ -1146,22 +1130,22 @@ msgid "GraphQL"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:60
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:69
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:80
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:35
#: lib/block_scout_web/templates/address_transaction/index.html.eex:66
#: lib/block_scout_web/templates/address_transaction/index.html.eex:80
#: lib/block_scout_web/templates/block/index.html.eex:15
#: lib/block_scout_web/templates/block/index.html.eex:30
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:34
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:44
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:66
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:73
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:90
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:47
#: lib/block_scout_web/templates/address_transaction/index.html.eex:71
#: lib/block_scout_web/templates/address_transaction/index.html.eex:89
#: lib/block_scout_web/templates/block/index.html.eex:19
#: lib/block_scout_web/templates/block/index.html.eex:39
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:32
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:48
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:33
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:44
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:29
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:41
#: lib/block_scout_web/templates/transaction/index.html.eex:38
#: lib/block_scout_web/templates/transaction/index.html.eex:52
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:34
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:52
#: lib/block_scout_web/templates/transaction/index.html.eex:36
#: lib/block_scout_web/templates/transaction/index.html.eex:54
msgid "Loading"
msgstr ""
@ -1256,18 +1240,18 @@ msgid "Static Call"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:24
#: lib/block_scout_web/templates/transaction_log/index.html.eex:33
msgid "Decoded"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:57
#: lib/block_scout_web/templates/transaction_log/index.html.eex:66
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:56
#: lib/block_scout_web/templates/transaction_log/index.html.eex:65
msgid "Type"
msgstr ""
@ -1277,7 +1261,7 @@ msgid "Method Id"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:29
#: lib/block_scout_web/templates/transaction_log/index.html.eex:38
msgid "To see decoded input data, the contract must be verified."
msgstr ""
@ -1293,13 +1277,13 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:32
#: lib/block_scout_web/templates/transaction_log/index.html.eex:41
msgid "Verify the contract "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:32
#: lib/block_scout_web/templates/transaction_log/index.html.eex:41
msgid "here"
msgstr ""
@ -1315,41 +1299,41 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
#: lib/block_scout_web/templates/transaction_log/index.html.eex:68
#: lib/block_scout_web/templates/transaction_log/index.html.eex:77
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:39
#: lib/block_scout_web/templates/transaction_log/index.html.eex:48
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:52
#: lib/block_scout_web/templates/transaction_log/index.html.eex:61
msgid "Log Data"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:32
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:57
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:23
#: lib/block_scout_web/templates/address_transaction/index.html.eex:52
#: lib/block_scout_web/templates/address_validation/index.html.eex:26
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:28
#: lib/block_scout_web/templates/address_transaction/index.html.eex:57
#: lib/block_scout_web/templates/address_validation/index.html.eex:29
#: lib/block_scout_web/templates/chain/show.html.eex:91
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:21
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:19
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:19
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:17
#: lib/block_scout_web/templates/transaction/index.html.eex:22
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20
#: lib/block_scout_web/templates/transaction/index.html.eex:20
msgid "Something went wrong, click to reload."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_validation/index.html.eex:22
#: lib/block_scout_web/templates/address_validation/index.html.eex:25
msgid "There are no blocks validated by this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/index.html.eex:28
#: lib/block_scout_web/templates/transaction/index.html.eex:26
msgid "There are no transactions."
msgstr ""
@ -1370,34 +1354,34 @@ msgid "Coin Balance History"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:46
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:48
msgid "Loading balances"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:21
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:22
#: lib/block_scout_web/templates/chain/show.html.eex:13
msgid "Loading chart"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:37
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:39
msgid "There is no coin history for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:24
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:25
#: lib/block_scout_web/templates/chain/show.html.eex:16
msgid "There was a problem loading the chart."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:25
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:23
msgid "There are no pending transactions."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/index.html.eex:19
#: lib/block_scout_web/templates/block/index.html.eex:23
msgid "There are no blocks."
msgstr ""
@ -1432,7 +1416,7 @@ msgid "Validator Info"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:137
#: lib/block_scout_web/templates/block/overview.html.eex:139
msgid "Block Rewards"
msgstr ""
@ -1527,17 +1511,17 @@ msgid "Support"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:48
#: lib/block_scout_web/templates/address_contract/index.html.eex:55
msgid "Copy ABI"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:62
#: lib/block_scout_web/templates/address_contract/index.html.eex:71
msgid "Copy Contract Creation Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:36
#: lib/block_scout_web/templates/address_contract/index.html.eex:43
msgid "Copy Source Code"
msgstr ""
@ -1679,7 +1663,7 @@ msgid "Decompiled Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:47
#: lib/block_scout_web/templates/address/_tabs.html.eex:52
msgid "Decompiled code"
msgstr ""
@ -1708,11 +1692,6 @@ msgstr ""
msgid "ERC-721"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/api_docs/index.html.eex:4
msgid "API Documentation"
@ -1735,7 +1714,66 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:24
#: lib/block_scout_web/templates/transaction_raw_trace/index.html.eex:10
#: lib/block_scout_web/templates/transaction_raw_trace/index.html.eex:7
#: lib/block_scout_web/views/transaction_view.ex:341
msgid "Raw Trace"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:37
msgid "Page"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:11
msgid "Records"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:5
msgid "Show"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:37
msgid "of"
msgstr ""
#, elixir-format, fuzzy
#: lib/block_scout_web/templates/address_contract/index.html.eex:83
msgid "Contract Byte Code"
msgstr ""
#, elixir-format, fuzzy
#: lib/block_scout_web/templates/address_contract/index.html.eex:69
msgid "Contract Creation Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:75
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr ""
#, elixir-format, fuzzy
#: lib/block_scout_web/templates/address_contract/index.html.eex:85
msgid "Copy Contract Byte Code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:76
msgid "Displaying the init data provided of the creating transaction."
msgstr ""
#, elixir-format, fuzzy
#: lib/block_scout_web/templates/address_logs/index.html.eex:77
msgid "There are no logs for this address."
msgstr ""

@ -1,13 +1,43 @@
defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
use BlockScoutWeb.ConnCase
use BlockScoutWeb.ConnCase, async: false
import Mox
alias BlockScoutWeb.API.RPC.AddressController
alias Explorer.Chain
alias Explorer.Chain.{BlockNumberCache, Events.Subscriber, Transaction, Wei}
alias Explorer.Counters.{AddressesWithBalanceCounter, AverageBlockTime}
alias Indexer.Fetcher.CoinBalanceOnDemand
alias Explorer.Repo
alias Explorer.Chain.{Transaction, Wei}
alias BlockScoutWeb.API.RPC.AddressController
setup :set_mox_global
setup :verify_on_exit!
setup do
mocked_json_rpc_named_arguments = [
transport: EthereumJSONRPC.Mox,
transport_options: []
]
start_supervised!({Task.Supervisor, name: Indexer.TaskSupervisor})
start_supervised!(AverageBlockTime)
start_supervised!({CoinBalanceOnDemand, [mocked_json_rpc_named_arguments, [name: CoinBalanceOnDemand]]})
start_supervised!(AddressesWithBalanceCounter)
Application.put_env(:explorer, AverageBlockTime, enabled: true)
on_exit(fn ->
Application.put_env(:explorer, AverageBlockTime, enabled: false)
end)
:ok
end
describe "listaccounts" do
setup do
Subscriber.to(:addresses, :on_demand)
Subscriber.to(:address_coin_balances, :on_demand)
%{params: %{"module" => "account", "action" => "listaccounts"}}
end
@ -47,6 +77,73 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
}
] = response["result"]
end
test "with a stale balance", %{conn: conn, params: params} do
now = Timex.now()
mining_address =
insert(:address,
fetched_coin_balance: 0,
fetched_coin_balance_block_number: 2,
inserted_at: Timex.shift(now, minutes: -10)
)
mining_address_hash = to_string(mining_address.hash)
# we space these very far apart so that we know it will consider the 0th block stale (it calculates how far
# back we'd need to go to get 24 hours in the past)
insert(:block, number: 0, timestamp: Timex.shift(now, hours: -50), miner: mining_address)
insert(:block, number: 1, timestamp: Timex.shift(now, hours: -25), miner: mining_address)
AverageBlockTime.refresh()
address =
insert(:address,
fetched_coin_balance: 100,
fetched_coin_balance_block_number: 0,
inserted_at: Timex.shift(now, minutes: -5)
)
address_hash = to_string(address.hash)
expect(EthereumJSONRPC.Mox, :json_rpc, 1, fn [
%{
id: id,
method: "eth_getBalance",
params: [^address_hash, "0x1"]
}
],
_options ->
{:ok, [%{id: id, jsonrpc: "2.0", result: "0x02"}]}
end)
response =
conn
|> get("/api", params)
|> json_response(200)
assert response["message"] == "OK"
assert response["status"] == "1"
assert [
%{
"address" => ^mining_address_hash,
"balance" => "0",
"stale" => false
},
%{
"address" => ^address_hash,
"balance" => "100",
"stale" => true
}
] = response["result"]
{:ok, expected_wei} = Wei.cast(2)
assert_receive({:chain_event, :addresses, :on_demand, [received_address]})
assert received_address.hash == address.hash
assert received_address.fetched_coin_balance == expected_wei
assert received_address.fetched_coin_balance_block_number == 1
end
end
describe "balance" do
@ -140,7 +237,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
expected_result =
Enum.map(addresses, fn address ->
%{"account" => "#{address.hash}", "balance" => "#{address.fetched_coin_balance.value}"}
%{"account" => "#{address.hash}", "balance" => "#{address.fetched_coin_balance.value}", "stale" => false}
end)
assert response =
@ -209,8 +306,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
}
expected_result = [
%{"account" => address1, "balance" => "0"},
%{"account" => address2, "balance" => "0"}
%{"account" => address1, "balance" => "0", "stale" => false},
%{"account" => address2, "balance" => "0", "stale" => false}
]
assert response =
@ -242,7 +339,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
expected_result =
Enum.map(addresses, fn address ->
%{"account" => "#{address.hash}", "balance" => "#{address.fetched_coin_balance.value}"}
%{"account" => "#{address.hash}", "balance" => "#{address.fetched_coin_balance.value}", "stale" => false}
end)
assert response =
@ -266,8 +363,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
}
expected_result = [
%{"account" => address2_hash, "balance" => "0"},
%{"account" => "#{address1.hash}", "balance" => "#{address1.fetched_coin_balance.value}"}
%{"account" => address2_hash, "balance" => "0", "stale" => false},
%{"account" => "#{address1.hash}", "balance" => "#{address1.fetched_coin_balance.value}", "stale" => false}
]
assert response =
@ -314,7 +411,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
}
expected_result = [
%{"account" => "#{address.hash}", "balance" => "#{address.fetched_coin_balance.value}"}
%{"account" => "#{address.hash}", "balance" => "#{address.fetched_coin_balance.value}", "stale" => false}
]
assert response =

@ -47,10 +47,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(contract.address_hash),
"CompilerVersion" => contract.compiler_version,
"ContractName" => contract.name,
"DecompiledSourceCode" => "Contract source code not decompiled.",
"DecompilerVersion" => "",
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0"),
"SourceCode" => contract.contract_source_code
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0")
}
]
end
@ -72,10 +70,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(address.hash),
"CompilerVersion" => "",
"ContractName" => "",
"DecompiledSourceCode" => "Contract source code not decompiled.",
"DecompilerVersion" => "",
"OptimizationUsed" => "",
"SourceCode" => ""
"OptimizationUsed" => ""
}
]
end
@ -98,10 +94,36 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(address.hash),
"CompilerVersion" => "",
"ContractName" => "",
"DecompiledSourceCode" => "Contract source code not decompiled.",
"DecompilerVersion" => "",
"OptimizationUsed" => "",
"SourceCode" => ""
"OptimizationUsed" => ""
}
]
end
test "filtering for only unverified contracts does not show self destructed contracts", %{
params: params,
conn: conn
} do
address = insert(:contract_address)
insert(:smart_contract)
insert(:contract_address, contract_code: "0x")
response =
conn
|> get("/api", Map.put(params, "filter", "unverified"))
|> json_response(200)
assert response["message"] == "OK"
assert response["status"] == "1"
assert response["result"] == [
%{
"ABI" => "Contract source code not verified",
"Address" => to_string(address.hash),
"CompilerVersion" => "",
"ContractName" => "",
"DecompilerVersion" => "",
"OptimizationUsed" => ""
}
]
end
@ -123,11 +145,9 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"ABI" => Jason.encode!(contract.abi),
"Address" => to_string(contract.address_hash),
"CompilerVersion" => contract.compiler_version,
"DecompiledSourceCode" => "Contract source code not decompiled.",
"DecompilerVersion" => "",
"ContractName" => contract.name,
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0"),
"SourceCode" => contract.contract_source_code
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0")
}
]
end
@ -150,10 +170,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(decompiled_smart_contract.address_hash),
"CompilerVersion" => "",
"ContractName" => "",
"DecompiledSourceCode" => decompiled_smart_contract.decompiled_source_code,
"DecompilerVersion" => "test_decompiler",
"OptimizationUsed" => "",
"SourceCode" => ""
"OptimizationUsed" => ""
}
]
end
@ -176,10 +194,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(smart_contract.address_hash),
"CompilerVersion" => "",
"ContractName" => "",
"DecompiledSourceCode" => smart_contract.decompiled_source_code,
"DecompilerVersion" => "bizbuz",
"OptimizationUsed" => "",
"SourceCode" => ""
"OptimizationUsed" => ""
}
]
end
@ -204,10 +220,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(smart_contract.address_hash),
"CompilerVersion" => "",
"ContractName" => "",
"DecompiledSourceCode" => smart_contract.decompiled_source_code,
"DecompilerVersion" => "bizbuz",
"OptimizationUsed" => "",
"SourceCode" => ""
"OptimizationUsed" => ""
}
]
end
@ -231,10 +245,37 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(contract_address.hash),
"CompilerVersion" => "",
"ContractName" => "",
"DecompiledSourceCode" => "Contract source code not decompiled.",
"DecompilerVersion" => "",
"OptimizationUsed" => "",
"SourceCode" => ""
"OptimizationUsed" => ""
}
]
end
test "filtering for only not_decompiled (and by extension not verified contracts) does not show empty contracts", %{
params: params,
conn: conn
} do
insert(:decompiled_smart_contract)
insert(:smart_contract)
insert(:contract_address, contract_code: "0x")
contract_address = insert(:contract_address)
response =
conn
|> get("/api", Map.put(params, "filter", "not_decompiled"))
|> json_response(200)
assert response["message"] == "OK"
assert response["status"] == "1"
assert response["result"] == [
%{
"ABI" => "Contract source code not verified",
"Address" => to_string(contract_address.hash),
"CompilerVersion" => "",
"ContractName" => "",
"DecompilerVersion" => "",
"OptimizationUsed" => ""
}
]
end

@ -460,7 +460,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
%{
"address" => "#{address.hash}",
"data" => "#{log.data}",
"topics" => ["first topic", "second topic", nil, nil]
"topics" => ["first topic", "second topic", nil, nil],
"index" => "#{log.index}"
}
],
"next_page_params" => nil

@ -91,7 +91,8 @@ defmodule BlockScoutWeb.BlockControllerTest do
expected_path =
block_path(conn, :index, %{
block_number: number
block_number: number,
block_type: "Block"
})
assert Map.get(json_response(conn, 200), "next_page_path") == expected_path

@ -56,7 +56,43 @@ defmodule BlockScoutWeb.AddressDecompiledContractViewTest do
result = AddressDecompiledContractView.highlight_decompiled_code(code)
assert result ==
"<code> <span style=\"color:rgb(111, 110, 111)\">#</code>\n<code> # eveem.org 6 Feb 2019</code>\n<code> # Decompiled source of </span>0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875<span style=\"color:rgb(111, 110, 111)\"></code>\n<code> #</code>\n<code> # Let's make the world open source</code>\n<code> # </span></code>\n<code> <span style=\"color:rgb(111, 110, 111)\">#</code>\n<code> # I failed with these:</code>\n<code> </span><span style=\"color:rgb(111, 110, 111)\"># - </span><span style=\"color:rgb(236, 89, 58)\">unknowne77c646d(?)</span><span style=\"color:rgb(111, 110, 111)\"></code>\n<code> </span><span style=\"color:rgb(111, 110, 111)\"># - </span><span style=\"color:rgb(236, 89, 58)\">transferFromWithData(address _from, address _to, uint256 _value, bytes _data)</span><span style=\"color:rgb(111, 110, 111)\"></code>\n<code> # All the rest is below.</code>\n<code> #</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\"># Storage definitions and getters</span></code>\n<code></code>\n<code> <span style=\"color:rgb(57, 115, 0)\">def</span> storage:</code>\n<code> <span style=\"color:rgb(57, 115, 0)\">allowance</span> is uint256 => uint256 <span style=\"color:rgb(111, 110, 111)\"># mask(256, 0) at storage #2</span></code>\n<code> <span style=\"color:rgb(57, 115, 0)\">stor4</span> is uint256 => uint8 <span style=\"color:rgb(111, 110, 111)\"># mask(8, 0) at storage #4</span></code>\n<code></code>\n<code> <span style=\"color:rgb(136, 0, 0)\">def </span>allowance(address <span style=\"color:rgb(57, 115, 0)\">_owner</span>, address <span style=\"color:rgb(57, 115, 0)\">_spender</span>) <span style=\"color:rgb(136, 0, 0)\">payable</span>: <span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code> require (calldata.size - 4)<span style=\"font-weight:bold\"> >= </span>64</code>\n<code> return <span style=\"color:rgb(57, 115, 0)\">allowance</span><span style=\"color:rgb(57, 115, 0)\">[</span>sha3(((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span><span style=\"color:rgb(57, 115, 0)\">_owner</span>), 1), ((320 - 1)<span style=\"font-weight:bold\"> and </span><span style=\"color:rgb(57, 115, 0)\">_spender</span><span style=\"font-weight:bold\"> and </span>(320 - 1))<span style=\"color:rgb(57, 115, 0)\">]</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\">#</code>\n<code> # Regular functions - see Tutorial for understanding quirks of the code</code>\n<code> #</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\"># folder failed in this function - may be terribly long, sorry</span></code>\n<code> <span style=\"color:rgb(136, 0, 0)\">def </span>unknownc47d033b(?) <span style=\"color:rgb(136, 0, 0)\">payable</span>: <span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code> if (calldata.size - 4)<span style=\"font-weight:bold\"> < </span>32:</code>\n<code> revert</code>\n<code> else:</code>\n<code> if not (320 - 1)<span style=\"font-weight:bold\"> or </span>not cd[4]:</code>\n<code> revert</code>\n<code> else:</code>\n<code> <span style=\"color:rgb(136, 0, 0)\">mem[</span>0<span style=\"color:rgb(136, 0, 0)\">]</span> = (320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>cd[4]</code>\n<code> <span style=\"color:rgb(136, 0, 0)\">mem[</span>32<span style=\"color:rgb(136, 0, 0)\">]</span> = 4</code>\n<code> <span style=\"color:rgb(136, 0, 0)\">mem[</span>96<span style=\"color:rgb(136, 0, 0)\">]</span> = bool(<span style=\"color:rgb(57, 115, 0)\">stor4</span><span style=\"color:rgb(57, 115, 0)\">[</span>((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>cd[4])<span style=\"color:rgb(57, 115, 0)\">]</span>)</code>\n<code> return bool(<span style=\"color:rgb(57, 115, 0)\">stor4</span><span style=\"color:rgb(57, 115, 0)\">[</span>((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>cd[4])<span style=\"color:rgb(57, 115, 0)\">]</span>)</code>\n<code></code>\n<code> <span style=\"color:rgb(136, 0, 0)\">def </span>_fallback() <span style=\"color:rgb(136, 0, 0)\">payable</span>: <span style=\"color:rgb(111, 110, 111)\"># default function</span></code>\n<code> revert</code>\n<code></code>\n"
"<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # eveem.org 6 Feb 2019</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Decompiled source of </span>0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Let's make the world open source</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # </span></code>\n<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # I failed with these:</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> </span><span style=\"color:rgb(111, 110, 111)\"># - </span>unknowne77c646d(?)<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> </span><span style=\"color:rgb(111, 110, 111)\"># - </span>transferFromWithData(address _from, address _to, uint256 _value, bytes _data)<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # All the rest is below.</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\"># Storage definitions and getters</span></code>\n<code></code>\n<code> <span class=\"hljs-keyword\">def</span> storage:</code>\n<code> allowance is <span class=\"hljs-keyword\">uint</span>256 => <span class=\"hljs-keyword\">uint</span>256 <span style=\"color:rgb(111, 110, 111)\"># mask(256, 0) at storage #2</span></code>\n<code> stor4 is <span class=\"hljs-keyword\">uint</span>256 => <span class=\"hljs-keyword\">uint</span>8 <span style=\"color:rgb(111, 110, 111)\"># mask(8, 0) at storage #4</span></code>\n<code></code>\n<code> <span class=\"hljs-keyword\">def</span> allowance(<span class=\"hljs-keyword\">address</span> _owner, <span class=\"hljs-keyword\">address</span> _spender) <span class=\"hljs-title\">payable</span>: </code>\n<code> <span class=\"hljs-keyword\">require</span> (calldata.size - 4)<span style=\"font-weight:bold\"> >= </span>64</code>\n<code> <span class=\"hljs-keyword\">return</span> allowance[sha3(((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>_owner), 1), ((320 - 1)<span style=\"font-weight:bold\"> and </span>_spender<span style=\"font-weight:bold\"> and </span>(320 - 1))]</code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Regular functions - see Tutorial for understanding quirks of the code</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\"># folder failed in this function - may be terribly long, sorry</span></code>\n<code> <span class=\"hljs-keyword\">def</span> unknownc47d033b(?) <span class=\"hljs-title\">payable</span>: </code>\n<code> if (calldata.size - 4)<span style=\"font-weight:bold\"> < </span>32:</code>\n<code> <span class=\"hljs-keyword\">revert</span></code>\n<code> else:</code>\n<code> if not (320 - 1)<span style=\"font-weight:bold\"> or </span>not cd[4]:</code>\n<code> <span class=\"hljs-keyword\">revert</span></code>\n<code> else:</code>\n<code> <span class=\"hljs-keyword\">mem</span>[0] = (320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>cd[4]</code>\n<code> <span class=\"hljs-keyword\">mem</span>[32] = 4</code>\n<code> <span class=\"hljs-keyword\">mem</span>[96] = <span class=\"hljs-keyword\">bool</span>(stor4[((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>cd[4])])</code>\n<code> <span class=\"hljs-keyword\">return</span> <span class=\"hljs-keyword\">bool</span>(stor4[((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>cd[4])])</code>\n<code></code>\n<code> <span class=\"hljs-keyword\">def</span> _fallback() <span class=\"hljs-title\">payable</span>: <span style=\"color:rgb(111, 110, 111)\"># default function</span></code>\n<code> <span class=\"hljs-keyword\">revert</span></code>\n<code></code>\n<code></code>\n"
end
test "adds style span to every line" do
code = """
#
# eveem.org 6 Feb 2019
# Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875
#
# Let's make the world open source
# 
"""
assert AddressDecompiledContractView.highlight_decompiled_code(code) ==
"<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # eveem.org 6 Feb 2019</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Decompiled source of </span>0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Let's make the world open source</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # </span></code>\n<code></code>\n<code></code>\n"
end
test "does not remove bold text" do
code = """
#
# Eveem.org 26 Apr 2019
# Decompiled source of 0x06012c8cf97bead5deae237070f9587f8e7a266d
#
# Let's make the world open source
# 
const name = 'CryptoKitties'
const symbol = 'CK'
const GEN0_STARTING_PRICE = 10^16
const GEN0_AUCTION_DURATION = (24 * 3600)
const GEN0_CREATION_LIMIT = 45000
const PROMO_CREATION_LIMIT = 5000
"""
assert AddressDecompiledContractView.highlight_decompiled_code(code) ==
"<code><span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"># Eveem.org 26 Apr 2019</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"># Decompiled source of </span>0x06012c8cf97bead5deae237070f9587f8e7a266d<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"># Let's make the world open source</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"># </span></code>\n<code></code>\n<code>const name = <span style=\"font-weight:bold\">'CryptoKitties'</span></code>\n<code>const symbol = <span style=\"font-weight:bold\">'CK'</span></code>\n<code>const GEN0_STARTING_PRICE = <span style=\"font-weight:bold\">10^16</span></code>\n<code>const GEN0_AUCTION_DURATION = <span style=\"font-weight:bold\">(24 * 3600)</span></code>\n<code>const GEN0_CREATION_LIMIT = <span style=\"font-weight:bold\">45000</span></code>\n<code>const PROMO_CREATION_LIMIT = <span style=\"font-weight:bold\">5000</span></code>\n<code></code>\n<code></code>\n<code></code>\n"
end
end

@ -62,16 +62,32 @@ defmodule BlockScoutWeb.LayoutViewTest do
end
describe "release_link/1" do
test "use the version when there is no release_link env configured for it" do
test "set empty string if no blockscout version configured" do
Application.put_env(:block_scout_web, :blockscout_version, nil)
assert LayoutView.release_link(nil) == ""
end
test "set empty string if blockscout version is empty string" do
Application.put_env(:block_scout_web, :blockscout_version, "")
assert LayoutView.release_link("") == ""
end
test "use the default value when there is no release_link env configured for it" do
Application.put_env(:block_scout_web, :release_link, nil)
assert LayoutView.release_link("1.3.4") == "1.3.4"
assert LayoutView.release_link("v1.3.4-beta") ==
{:safe,
~s(<a href="https://github.com/poanetwork/blockscout/releases/tag/v1.3.4-beta" class="footer-link" target="_blank">v1.3.4-beta</a>)}
end
test "use the version when empty release_link env configured for it" do
test "use the default value when empty release_link env configured for it" do
Application.put_env(:block_scout_web, :release_link, "")
assert LayoutView.release_link("1.3.4") == "1.3.4"
assert LayoutView.release_link("v1.3.4-beta") ==
{:safe,
~s(<a href="https://github.com/poanetwork/blockscout/releases/tag/v1.3.4-beta" class="footer-link" target="_blank">v1.3.4-beta</a>)}
end
test "use the enviroment release link when it's configured" do
@ -81,9 +97,128 @@ defmodule BlockScoutWeb.LayoutViewTest do
"https://github.com/poanetwork/blockscout/releases/tag/v1.3.4-beta"
)
assert LayoutView.release_link("1.3.4") ==
assert LayoutView.release_link("v1.3.4-beta") ==
{:safe,
~s(<a href="https://github.com/poanetwork/blockscout/releases/tag/v1.3.4-beta" class="footer-link" target="_blank">1.3.4</a>)}
~s(<a href="https://github.com/poanetwork/blockscout/releases/tag/v1.3.4-beta" class="footer-link" target="_blank">v1.3.4-beta</a>)}
end
end
@supported_chains_pattern ~s([ { "title": "RSK Mainnet", "url": "https://blockscout.com/rsk/mainnet", "other?": true }, { "title": "POA Sokol", "url": "https://blockscout.com/poa/sokol", "test_net?": true }, { "title": "POA Core", "url": "https://blockscout.com/poa/core" }, { "title": "LUKSO L14 testnet", "url": "https://blockscout.com/lukso/l14", "test_net?": true, "hide_in_dropdown?": true } ])
describe "other_networks/0" do
test "get networks list based on env variables" do
Application.put_env(:block_scout_web, :other_networks, @supported_chains_pattern)
assert LayoutView.other_networks() == [
%{
title: "POA Core",
url: "https://blockscout.com/poa/core"
},
%{
title: "RSK Mainnet",
url: "https://blockscout.com/rsk/mainnet",
other?: true
},
%{
title: "POA Sokol",
url: "https://blockscout.com/poa/sokol",
test_net?: true
},
%{
title: "LUKSO L14 testnet",
url: "https://blockscout.com/lukso/l14",
test_net?: true,
hide_in_dropdown?: true
}
]
end
end
describe "main_nets/1" do
test "get all main networks list based on env variables" do
Application.put_env(:block_scout_web, :other_networks, @supported_chains_pattern)
assert LayoutView.main_nets(LayoutView.other_networks()) == [
%{
title: "POA Core",
url: "https://blockscout.com/poa/core"
},
%{
title: "RSK Mainnet",
url: "https://blockscout.com/rsk/mainnet",
other?: true
}
]
end
end
describe "test_nets/1" do
test "get all networks list based on env variables" do
Application.put_env(:block_scout_web, :other_networks, @supported_chains_pattern)
assert LayoutView.test_nets(LayoutView.other_networks()) == [
%{
title: "POA Sokol",
url: "https://blockscout.com/poa/sokol",
test_net?: true
},
%{
title: "LUKSO L14 testnet",
url: "https://blockscout.com/lukso/l14",
test_net?: true,
hide_in_dropdown?: true
}
]
end
end
describe "dropdown_nets/0" do
test "get all dropdown networks list based on env variables" do
Application.put_env(:block_scout_web, :other_networks, @supported_chains_pattern)
assert LayoutView.dropdown_nets() == [
%{
title: "POA Core",
url: "https://blockscout.com/poa/core"
},
%{
title: "RSK Mainnet",
url: "https://blockscout.com/rsk/mainnet",
other?: true
},
%{
title: "POA Sokol",
url: "https://blockscout.com/poa/sokol",
test_net?: true
}
]
end
end
describe "dropdown_head_main_nets/0" do
test "get dropdown all main networks except those of 'other' type list based on env variables" do
Application.put_env(:block_scout_web, :other_networks, @supported_chains_pattern)
assert LayoutView.dropdown_head_main_nets() == [
%{
title: "POA Core",
url: "https://blockscout.com/poa/core"
}
]
end
end
describe "dropdown_other_nets/0" do
test "get dropdown networks of 'other' type list based on env variables" do
Application.put_env(:block_scout_web, :other_networks, @supported_chains_pattern)
assert LayoutView.dropdown_other_nets() == [
%{
title: "RSK Mainnet",
url: "https://blockscout.com/rsk/mainnet",
other?: true
}
]
end
end
end

@ -1 +1,2 @@
priv/.recovery
priv/.recovery
priv/solc_compilers/

@ -13,6 +13,8 @@ config :explorer,
config :explorer, Explorer.Counters.AverageBlockTime, enabled: true
config :explorer, Explorer.Chain.BlockNumberCache, enabled: true
config :explorer, Explorer.ExchangeRates.Source.CoinMarketCap,
pages: String.to_integer(System.get_env("COINMARKETCAP_PAGES") || "10")
@ -58,6 +60,14 @@ config :explorer, Explorer.Staking.PoolsReader,
validators_contract_address: System.get_env("POS_VALIDATORS_CONTRACT"),
staking_contract_address: System.get_env("POS_STAKING_CONTRACT")
if System.get_env("POS_STAKING_CONTRACT") do
config :explorer, Explorer.Staking.EpochCounter,
enabled: true,
staking_contract_address: System.get_env("POS_STAKING_CONTRACT")
else
config :explorer, Explorer.Staking.EpochCounter, enabled: false
end
if System.get_env("SUPPLY_MODULE") == "TokenBridge" do
config :explorer, supply: Explorer.Chain.Supply.TokenBridge
end
@ -82,8 +92,6 @@ config :spandex_ecto, SpandexEcto.EctoLogger,
tracer: Explorer.Tracer,
otp_app: :explorer
config :explorer, Explorer.Chain.BlockCountCache, ttl: System.get_env("BLOCK_COUNT_CACHE_TTL")
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"

@ -13,6 +13,8 @@ config :explorer, Explorer.Repo,
config :explorer, Explorer.ExchangeRates, enabled: false, store: :ets
config :explorer, Explorer.Chain.BlockNumberCache, enabled: false
config :explorer, Explorer.KnownTokens, enabled: false, store: :ets
config :explorer, Explorer.Counters.AverageBlockTime, enabled: false

@ -26,9 +26,11 @@ defmodule Explorer.Application do
Supervisor.Spec.worker(SpandexDatadog.ApiServer, [datadog_opts()]),
Supervisor.child_spec({Task.Supervisor, name: Explorer.MarketTaskSupervisor}, id: Explorer.MarketTaskSupervisor),
Supervisor.child_spec({Task.Supervisor, name: Explorer.TaskSupervisor}, id: Explorer.TaskSupervisor),
Explorer.SmartContract.SolcDownloader,
{Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents},
{Admin.Recovery, [[], [name: Admin.Recovery]]},
{TransactionCountCache, [[], []]}
{TransactionCountCache, [[], []]},
{BlockCountCache, []}
]
children = base_children ++ configurable_children()
@ -38,7 +40,6 @@ defmodule Explorer.Application do
res = Supervisor.start_link(children, opts)
BlockNumberCache.setup()
BlockCountCache.setup()
res
end
@ -50,7 +51,8 @@ defmodule Explorer.Application do
configure(Explorer.Market.History.Cataloger),
configure(Explorer.Counters.AddressesWithBalanceCounter),
configure(Explorer.Counters.AverageBlockTime),
configure(Explorer.Validator.MetadataProcessor)
configure(Explorer.Validator.MetadataProcessor),
configure(Explorer.Staking.EpochCounter)
]
|> List.flatten()
end

@ -10,6 +10,7 @@ defmodule Explorer.Chain do
limit: 2,
order_by: 2,
order_by: 3,
offset: 2,
preload: 2,
select: 2,
subquery: 1,
@ -29,6 +30,7 @@ defmodule Explorer.Chain do
Address.CurrentTokenBalance,
Address.TokenBalance,
Block,
BlockCountCache,
BlockNumberCache,
Data,
DecompiledSmartContract,
@ -278,6 +280,38 @@ defmodule Explorer.Chain do
|> Enum.take(paging_options.page_size)
end
@spec address_to_logs(Address.t(), [paging_options]) :: [
Log.t()
]
def address_to_logs(
%Address{hash: %Hash{byte_count: unquote(Hash.Address.byte_count())} = address_hash},
options \\ []
)
when is_list(options) do
paging_options = Keyword.get(options, :paging_options) || %PagingOptions{page_size: 50}
{block_number, transaction_index, log_index} = paging_options.key || {BlockNumberCache.max_number(), 0, 0}
query =
from(log in Log,
inner_join: transaction in assoc(log, :transaction),
order_by: [desc: transaction.block_number, desc: transaction.index],
preload: [:transaction],
where:
log.address_hash == ^address_hash and
(transaction.block_number < ^block_number or
(transaction.block_number == ^block_number and transaction.index > ^transaction_index) or
(transaction.block_number == ^block_number and transaction.index == ^transaction_index and
log.index > ^log_index)),
limit: ^paging_options.page_size,
select: log
)
query
|> Repo.all()
|> Enum.take(paging_options.page_size)
end
@doc """
Finds all `t:Explorer.Chain.Transaction.t/0`s given the address_hash and the token contract
address hash.
@ -1143,21 +1177,25 @@ defmodule Explorer.Chain do
end
@doc """
Lists the top 250 `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance.
Lists the top `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance and address hash.
"""
@spec list_top_addresses :: [{Address.t(), non_neg_integer()}]
def list_top_addresses do
query =
def list_top_addresses(options \\ []) do
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
base_query =
from(a in Address,
where: a.fetched_coin_balance > ^0,
order_by: [desc: a.fetched_coin_balance, asc: a.hash],
preload: [:names],
select: {a, fragment("coalesce(1 + ?, 0)", a.nonce)},
limit: 250
select: {a, fragment("coalesce(1 + ?, 0)", a.nonce)}
)
Repo.all(query)
base_query
|> page_addresses(paging_options)
|> limit(^paging_options.page_size)
|> Repo.all()
end
@doc """
@ -1949,6 +1987,22 @@ defmodule Explorer.Chain do
end
end
@doc """
Estimated count of `t:Explorer.Chain.Block.t/0`.
Estimated count of consensus blocks.
"""
@spec block_estimated_count() :: non_neg_integer()
def block_estimated_count do
cached_value = BlockCountCache.count()
if is_nil(cached_value) do
block_consensus_count()
else
cached_value
end
end
@doc """
`t:Explorer.Chain.InternalTransaction/0`s in `t:Explorer.Chain.Transaction.t/0` with `hash`.
@ -2229,6 +2283,14 @@ defmodule Explorer.Chain do
|> repo.insert(on_conflict: :nothing, conflict_target: [:address_hash, :name])
end
@spec address_hash_to_address_with_source_code(%Explorer.Chain.Hash{}) :: %Explorer.Chain.Address{} | nil
def address_hash_to_address_with_source_code(%Explorer.Chain.Hash{} = address_hash) do
case Repo.get(Address, address_hash) do
nil -> nil
address -> Repo.preload(address, [:smart_contract, :decompiled_smart_contracts])
end
end
@spec address_hash_to_smart_contract(%Explorer.Chain.Hash{}) :: %Explorer.Chain.SmartContract{} | nil
def address_hash_to_smart_contract(%Explorer.Chain.Hash{} = address_hash) do
query =
@ -2293,6 +2355,12 @@ defmodule Explorer.Chain do
end)
end
defp page_addresses(query, %PagingOptions{key: nil}), do: query
defp page_addresses(query, %PagingOptions{key: {coin_balance, hash}}) do
where(query, [address], address.fetched_coin_balance <= ^coin_balance and address.hash > ^hash)
end
defp page_blocks(query, %PagingOptions{key: nil}), do: query
defp page_blocks(query, %PagingOptions{key: {block_number}}) do
@ -2530,7 +2598,7 @@ defmodule Explorer.Chain do
join: duplicate in subquery(query),
on: duplicate.nonce == pending.nonce,
on: duplicate.from_address_hash == pending.from_address_hash,
where: pending.hash in ^hashes
where: pending.hash in ^hashes and is_nil(pending.block_hash)
)
Repo.update_all(transactions_to_update, [set: [error: "dropped/replaced", status: :error]], timeout: timeout)
@ -2767,6 +2835,7 @@ defmodule Explorer.Chain do
on: smart_contract.address_hash == address.hash,
where: not is_nil(address.contract_code),
where: is_nil(smart_contract.address_hash),
where: address.contract_code != <<>>,
preload: [{:smart_contract, smart_contract}, :decompiled_smart_contracts],
order_by: [asc: address.inserted_at],
limit: ^limit,
@ -2776,6 +2845,19 @@ defmodule Explorer.Chain do
Repo.all(query)
end
def list_empty_contracts(limit, offset) do
query =
from(address in Address,
where: address.contract_code == <<>>,
preload: [:smart_contract, :decompiled_smart_contracts],
order_by: [asc: address.inserted_at],
limit: ^limit,
offset: ^offset
)
Repo.all(query)
end
def list_not_decompiled_contracts(limit, offset) do
query =
from(
@ -2785,6 +2867,7 @@ defmodule Explorer.Chain do
"NOT EXISTS (SELECT 1 FROM decompiled_smart_contracts WHERE decompiled_smart_contracts.address_hash = ?)",
address.hash
),
where: address.contract_code != <<>>,
left_join: smart_contract in SmartContract,
on: smart_contract.address_hash == address.hash,
left_join: decompiled_smart_contract in DecompiledSmartContract,
@ -2821,6 +2904,75 @@ defmodule Explorer.Chain do
value
end
@doc "Get staking pools from the DB"
@spec staking_pools(filter :: :validator | :active | :inactive, options :: PagingOptions.t()) :: [map()]
def staking_pools(filter, %PagingOptions{page_size: page_size, page_number: page_number} \\ @default_paging_options) do
off = page_size * (page_number - 1)
Address.Name
|> staking_pool_filter(filter)
|> limit(^page_size)
|> offset(^off)
|> Repo.all()
end
@doc "Get count of staking pools from the DB"
@spec staking_pools_count(filter :: :validator | :active | :inactive) :: integer
def staking_pools_count(filter) do
Address.Name
|> staking_pool_filter(filter)
|> Repo.aggregate(:count, :address_hash)
end
defp staking_pool_filter(query, :validator) do
where(
query,
[address],
fragment(
"""
(?->>'is_active')::boolean = true and
(?->>'deleted')::boolean is not true and
(?->>'is_validator')::boolean = true
""",
address.metadata,
address.metadata,
address.metadata
)
)
end
defp staking_pool_filter(query, :active) do
where(
query,
[address],
fragment(
"""
(?->>'is_active')::boolean = true and
(?->>'deleted')::boolean is not true
""",
address.metadata,
address.metadata
)
)
end
defp staking_pool_filter(query, :inactive) do
where(
query,
[address],
fragment(
"""
(?->>'is_active')::boolean = false and
(?->>'deleted')::boolean is not true
""",
address.metadata,
address.metadata
)
)
end
defp staking_pool_filter(query, _), do: query
defp with_decompiled_code_flag(query, hash) do
has_decompiled_code_query =
from(decompiled_contract in DecompiledSmartContract,

@ -62,7 +62,7 @@ defmodule Explorer.Chain.Address do
except: [
:__meta__,
:smart_contract,
:decompiled_smart_contract,
:decompiled_smart_contracts,
:token,
:contracts_creation_internal_transaction,
:contracts_creation_transaction,
@ -76,6 +76,7 @@ defmodule Explorer.Chain.Address do
field(:contract_code, Data)
field(:nonce, :integer)
field(:has_decompiled_code?, :boolean, virtual: true)
field(:stale?, :boolean, virtual: true)
has_one(:smart_contract, SmartContract)
has_one(:token, Token, foreign_key: :contract_address_hash)

@ -10,7 +10,7 @@ defmodule Explorer.Chain.Block do
alias Explorer.Chain.{Address, Gas, Hash, Transaction}
alias Explorer.Chain.Block.{Reward, SecondDegreeRelation}
@optional_attrs ~w(internal_transactions_indexed_at size)a
@optional_attrs ~w(internal_transactions_indexed_at size refetch_needed)a
@required_attrs ~w(consensus difficulty gas_limit gas_used hash miner_hash nonce number parent_hash timestamp total_difficulty)a
@ -63,7 +63,8 @@ defmodule Explorer.Chain.Block do
timestamp: DateTime.t(),
total_difficulty: difficulty(),
transactions: %Ecto.Association.NotLoaded{} | [Transaction.t()],
internal_transactions_indexed_at: DateTime.t()
internal_transactions_indexed_at: DateTime.t(),
refetch_needed: boolean()
}
@primary_key {:hash, Hash.Full, autogenerate: false}
@ -78,6 +79,7 @@ defmodule Explorer.Chain.Block do
field(:timestamp, :utc_datetime_usec)
field(:total_difficulty, :decimal)
field(:internal_transactions_indexed_at, :utc_datetime_usec)
field(:refetch_needed, :boolean)
timestamps()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save